diff --git a/Cargo.toml b/Cargo.toml index 1900f54..c170f68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,14 +8,18 @@ cascade = "1.0.0" derivative = { version = "2", optional = true } gtk4 = { version = "0.4.4", features = ["v4_4"] } gdk4 = "0.4.4" -gdk4-wayland = { version = "0.4.2", features = [ "wayland_crate" ], optional = true } -gdk4-x11 = { version = "0.4.2", features = [ "xlib" ] } +gdk4-wayland = { version = "0.4.2", features = ["wayland_crate"], optional = true } +gdk4-x11 = { version = "0.4.2", features = ["xlib"] } gio = "0.15.2" gobject-sys = "0.15.1" wayland-client = { version = "0.29.4", optional = true } -wayland-protocols = { version = "0.29.4", features = [ "client", "unstable_protocols" ], optional = true } +wayland-protocols = { version = "0.29.4", features = ["client", "unstable_protocols"], optional = true } x11 = { version = "2.19.1", features = ["xlib"] } once_cell = "1.9.0" +libcosmic-widgets = { path = "widgets" } [features] layer-shell = ["derivative", "gdk4-wayland", "wayland-client", "wayland-protocols"] + +[workspace] +members = ["widgets"] diff --git a/src/lib.rs b/src/lib.rs index 70ef094..9a5e77f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,3 +4,5 @@ pub mod wayland; #[cfg(feature = "layer-shell")] mod wayland_custom_surface; pub mod x; + +pub use libcosmic_widgets as widgets; diff --git a/widgets/Cargo.toml b/widgets/Cargo.toml new file mode 100644 index 0000000..20d4dd9 --- /dev/null +++ b/widgets/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "libcosmic-widgets" +version = "0.1.0" +edition = "2021" + +[dependencies] +gtk4 = { version = "0.4.6", features = ["v4_4"] } +relm4 = { git = "https://github.com/AaronErhardt/relm4", branch = "new-approach" } +relm4-macros = { git = "https://github.com/AaronErhardt/relm4", branch = "new-approach" } +tracker = "0.1.1" diff --git a/widgets/src/labeled_item.rs b/widgets/src/labeled_item.rs new file mode 100644 index 0000000..f8c2e69 --- /dev/null +++ b/widgets/src/labeled_item.rs @@ -0,0 +1,113 @@ +use gtk4::{prelude::*, Align, Label, Orientation, Widget}; +use relm4::{ComponentParts, Sender, SimpleComponent}; + +#[derive(Debug)] +pub enum LabeledItemMessage { + Title(String), + Desc(Option), + Align(Align), + Child(Widget), +} + +#[track] +struct LabeledItem { + title: String, + desc: Option, + align: Align, + child: Option, +} + +#[component] +impl SimpleComponent for LabeledItem { + type Widgets = AppWidgets; + type InitParams = (); + type Input = LabeledItemMessage; + type Output = (); + + view! { + base_box = gtk4::Box { + add_css_class: "labeled-item", + set_orientation: Orientation::Horizontal, + set_hexpand: true, + set_margin_start: 24, + set_margin_end: 24, + set_margin_top: 8, + set_margin_bottom: 8, + set_spacing: 16, + append: labeled_item_info = >k4::Box { + add_css_class: "labeled-item-info", + set_orientation: Orientation::Vertical, + set_hexpand: true, + set_spacing: 8, + set_valign: Align::Center, + &Label { + add_css_class: "labeled-item-title", + set_halign: Align::Start, + set_label: watch! { &model.title } + }, + &Label { + add_css_class: "labeled-item-desc", + set_halign: Align::Start, + set_visible: watch! { model.desc.is_some() }, + set_label: watch! { &model.desc.clone().unwrap_or_default() } + }, + } + } + } + + fn init_parts( + _init_params: Self::InitParams, + root: &Self::Root, + _input: &Sender, + _output: &Sender, + ) -> ComponentParts { + let model = LabeledItem { + title: String::default(), + desc: None, + align: Align::Start, + child: None, + tracker: 0, + }; + let widgets = view_output!(); + + ComponentParts { model, widgets } + } + + fn update( + &mut self, + msg: Self::Input, + _input: &Sender, + _ouput: &Sender, + ) { + self.reset(); + match msg { + LabeledItemMessage::Title(title) => self.set_title(title), + LabeledItemMessage::Desc(desc) => self.set_desc(desc), + LabeledItemMessage::Align(align) => self.set_align(align), + LabeledItemMessage::Child(child) => self.set_child(Some(child)), + } + } + + fn post_view() { + if self.changed(LabeledItem::child()) { + let child = self.child.as_ref().expect("there's no child??"); + widgets.base_box.append(child); + } + if self.changed(LabeledItem::align()) { + let child = self.child.as_ref().expect("set alignment without child"); + match self.align { + Align::Start => { + widgets + .base_box + .reorder_child_after(&widgets.labeled_item_info, Some(child)); + } + Align::End => { + widgets + .base_box + .reorder_child_after(child, Some(&widgets.labeled_item_info)); + } + _ => unimplemented!(), + } + } + } +} diff --git a/widgets/src/lib.rs b/widgets/src/lib.rs new file mode 100644 index 0000000..ae5dbaa --- /dev/null +++ b/widgets/src/lib.rs @@ -0,0 +1,6 @@ +#[macro_use] +extern crate relm4_macros; +#[macro_use] +extern crate tracker; + +pub mod labeled_item;