17 changed files with 714 additions and 68 deletions
|
After Width: | Height: | Size: 7.3 KiB |
@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<interface> |
||||
<template class="SidebarEntryRow" parent="AdwBin"> |
||||
<style> |
||||
<class name="entry-row"/> |
||||
</style> |
||||
<child> |
||||
<object class="GtkBox"> |
||||
<property name="spacing">12</property> |
||||
<child> |
||||
<object class="GtkImage"> |
||||
<property name="icon-name">explore2-symbolic</property> |
||||
<binding name="icon-name"> |
||||
<lookup name="icon-name" type="Entry"> |
||||
<lookup name="entry">SidebarEntryRow</lookup> |
||||
</lookup> |
||||
</binding> |
||||
</object> |
||||
</child> |
||||
<child> |
||||
<object class="GtkLabel"> |
||||
<property name="halign">start</property> |
||||
<property name="hexpand">True</property> |
||||
<property name="ellipsize">end</property> |
||||
<binding name="label"> |
||||
<lookup name="display-name" type="Entry"> |
||||
<lookup name="entry">SidebarEntryRow</lookup> |
||||
</lookup> |
||||
</binding> |
||||
</object> |
||||
</child> |
||||
</object> |
||||
</child> |
||||
</template> |
||||
</interface> |
||||
|
||||
@ -0,0 +1,27 @@
|
||||
use gettextrs::gettext; |
||||
use gtk::glib; |
||||
|
||||
#[derive(Debug, Hash, Eq, PartialEq, Clone, Copy, glib::GEnum)] |
||||
#[repr(u32)] |
||||
#[genum(type_name = "ContentType")] |
||||
pub enum ContentType { |
||||
None = 0, |
||||
Explore = 1, |
||||
Room = 2, |
||||
} |
||||
|
||||
impl Default for ContentType { |
||||
fn default() -> Self { |
||||
ContentType::None |
||||
} |
||||
} |
||||
|
||||
impl ToString for ContentType { |
||||
fn to_string(&self) -> String { |
||||
match self { |
||||
ContentType::None => gettext("No selection"), |
||||
ContentType::Explore => gettext("Explore"), |
||||
ContentType::Room => gettext("Room"), |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,109 @@
|
||||
use gtk::{glib, prelude::*, subclass::prelude::*}; |
||||
|
||||
use crate::session::content::ContentType; |
||||
|
||||
mod imp { |
||||
use std::cell::{Cell, RefCell}; |
||||
|
||||
use super::*; |
||||
|
||||
#[derive(Debug, Default)] |
||||
pub struct Entry { |
||||
pub type_: Cell<ContentType>, |
||||
pub display_name: RefCell<Option<String>>, |
||||
pub icon_name: RefCell<Option<String>>, |
||||
} |
||||
|
||||
#[glib::object_subclass] |
||||
impl ObjectSubclass for Entry { |
||||
const NAME: &'static str = "Entry"; |
||||
type Type = super::Entry; |
||||
type ParentType = glib::Object; |
||||
} |
||||
|
||||
impl ObjectImpl for Entry { |
||||
fn properties() -> &'static [glib::ParamSpec] { |
||||
use once_cell::sync::Lazy; |
||||
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| { |
||||
vec![ |
||||
glib::ParamSpec::new_enum( |
||||
"type", |
||||
"Type", |
||||
"The type of this category", |
||||
ContentType::static_type(), |
||||
ContentType::default() as i32, |
||||
glib::ParamFlags::READWRITE | glib::ParamFlags::CONSTRUCT_ONLY, |
||||
), |
||||
glib::ParamSpec::new_string( |
||||
"display-name", |
||||
"Display Name", |
||||
"The display name of this Entry", |
||||
None, |
||||
glib::ParamFlags::READWRITE | glib::ParamFlags::EXPLICIT_NOTIFY, |
||||
), |
||||
glib::ParamSpec::new_string( |
||||
"icon-name", |
||||
"Icon Name", |
||||
"The icon name used for this Entry", |
||||
None, |
||||
glib::ParamFlags::READWRITE | glib::ParamFlags::EXPLICIT_NOTIFY, |
||||
), |
||||
] |
||||
}); |
||||
|
||||
PROPERTIES.as_ref() |
||||
} |
||||
|
||||
fn set_property( |
||||
&self, |
||||
_obj: &Self::Type, |
||||
_id: usize, |
||||
value: &glib::Value, |
||||
pspec: &glib::ParamSpec, |
||||
) { |
||||
match pspec.name() { |
||||
"type" => { |
||||
self.type_.set(value.get().unwrap()); |
||||
} |
||||
"display-name" => { |
||||
let _ = self.display_name.replace(value.get().unwrap()); |
||||
} |
||||
"icon-name" => { |
||||
let _ = self.icon_name.replace(value.get().unwrap()); |
||||
} |
||||
_ => unimplemented!(), |
||||
} |
||||
} |
||||
|
||||
fn property(&self, obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { |
||||
match pspec.name() { |
||||
"type" => obj.type_().to_value(), |
||||
"display-name" => obj.type_().to_string().to_value(), |
||||
"icon-name" => obj.icon_name().to_value(), |
||||
_ => unimplemented!(), |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
glib::wrapper! { |
||||
pub struct Entry(ObjectSubclass<imp::Entry>); |
||||
} |
||||
|
||||
impl Entry { |
||||
pub fn new(type_: ContentType) -> Self { |
||||
glib::Object::new(&[("type", &type_)]).expect("Failed to create Entry") |
||||
} |
||||
|
||||
pub fn type_(&self) -> ContentType { |
||||
let priv_ = imp::Entry::from_instance(self); |
||||
priv_.type_.get() |
||||
} |
||||
|
||||
pub fn icon_name(&self) -> Option<&str> { |
||||
match self.type_() { |
||||
ContentType::Explore => Some("explore-symbolic"), |
||||
_ => None, |
||||
} |
||||
} |
||||
} |
||||
@ -0,0 +1,101 @@
|
||||
use adw; |
||||
use adw::subclass::prelude::BinImpl; |
||||
use gtk::subclass::prelude::*; |
||||
use gtk::{self, prelude::*}; |
||||
use gtk::{glib, CompositeTemplate}; |
||||
|
||||
use crate::session::sidebar::Entry; |
||||
|
||||
mod imp { |
||||
use super::*; |
||||
use glib::subclass::InitializingObject; |
||||
use std::cell::RefCell; |
||||
|
||||
#[derive(Debug, Default, CompositeTemplate)] |
||||
#[template(resource = "/org/gnome/FractalNext/sidebar-entry-row.ui")] |
||||
pub struct EntryRow { |
||||
pub entry: RefCell<Option<Entry>>, |
||||
} |
||||
|
||||
#[glib::object_subclass] |
||||
impl ObjectSubclass for EntryRow { |
||||
const NAME: &'static str = "SidebarEntryRow"; |
||||
type Type = super::EntryRow; |
||||
type ParentType = adw::Bin; |
||||
|
||||
fn class_init(klass: &mut Self::Class) { |
||||
Self::bind_template(klass); |
||||
} |
||||
|
||||
fn instance_init(obj: &InitializingObject<Self>) { |
||||
obj.init_template(); |
||||
} |
||||
} |
||||
|
||||
impl ObjectImpl for EntryRow { |
||||
fn properties() -> &'static [glib::ParamSpec] { |
||||
use once_cell::sync::Lazy; |
||||
static PROPERTIES: Lazy<Vec<glib::ParamSpec>> = Lazy::new(|| { |
||||
vec![glib::ParamSpec::new_object( |
||||
"entry", |
||||
"Entry", |
||||
"The entry of this row", |
||||
Entry::static_type(), |
||||
glib::ParamFlags::READWRITE | glib::ParamFlags::EXPLICIT_NOTIFY, |
||||
)] |
||||
}); |
||||
|
||||
PROPERTIES.as_ref() |
||||
} |
||||
|
||||
fn set_property( |
||||
&self, |
||||
obj: &Self::Type, |
||||
_id: usize, |
||||
value: &glib::Value, |
||||
pspec: &glib::ParamSpec, |
||||
) { |
||||
match pspec.name() { |
||||
"entry" => obj.set_entry(value.get().unwrap()), |
||||
_ => unimplemented!(), |
||||
} |
||||
} |
||||
|
||||
fn property(&self, obj: &Self::Type, _id: usize, pspec: &glib::ParamSpec) -> glib::Value { |
||||
match pspec.name() { |
||||
"entry" => obj.entry().to_value(), |
||||
_ => unimplemented!(), |
||||
} |
||||
} |
||||
} |
||||
|
||||
impl WidgetImpl for EntryRow {} |
||||
impl BinImpl for EntryRow {} |
||||
} |
||||
|
||||
glib::wrapper! { |
||||
pub struct EntryRow(ObjectSubclass<imp::EntryRow>) |
||||
@extends gtk::Widget, adw::Bin, @implements gtk::Accessible; |
||||
} |
||||
|
||||
impl EntryRow { |
||||
pub fn new() -> Self { |
||||
glib::Object::new(&[]).expect("Failed to create EntryRow") |
||||
} |
||||
|
||||
pub fn entry(&self) -> Option<Entry> { |
||||
let priv_ = imp::EntryRow::from_instance(&self); |
||||
priv_.entry.borrow().clone() |
||||
} |
||||
|
||||
pub fn set_entry(&self, entry: Option<Entry>) { |
||||
let priv_ = imp::EntryRow::from_instance(&self); |
||||
|
||||
if self.entry() == entry { |
||||
return; |
||||
} |
||||
|
||||
priv_.entry.replace(entry); |
||||
self.notify("entry"); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue