From 7c0cf048ee7ea68acc792d8b9163a7faaa061cf4 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Fri, 31 Dec 2021 14:58:26 -0500 Subject: [PATCH] refactor launcher removing templates --- Cargo.toml | 3 + config.toml | 2 + examples/dock/window/mod.rs | 6 +- examples/launcher/main.rs | 14 ---- examples/launcher/search_result_row/imp.rs | 30 ++----- examples/launcher/search_result_row/mod.rs | 98 ++++++++++++++++++++-- examples/launcher/style.css | 15 +++- examples/launcher/utils.rs | 18 ++++ examples/launcher/window/imp.rs | 33 ++------ examples/launcher/window/mod.rs | 53 ++++++++++-- 10 files changed, 188 insertions(+), 84 deletions(-) create mode 100644 config.toml diff --git a/Cargo.toml b/Cargo.toml index 6db2805..82acb0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,4 +36,7 @@ package = "gtk4" version = "0.3.1" features = ["v4_4"] +[profile.release] +incremental = true +debug = 1 diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..f4d28a3 --- /dev/null +++ b/config.toml @@ -0,0 +1,2 @@ +[build] +rustflags = ["-C", "link-arg=-fuse-ld=lld"] diff --git a/examples/dock/window/mod.rs b/examples/dock/window/mod.rs index 93741a5..86eec80 100644 --- a/examples/dock/window/mod.rs +++ b/examples/dock/window/mod.rs @@ -78,8 +78,8 @@ impl Window { Revealer::new(); ..set_reveal_child(true); ..set_valign(Align::Baseline); - ..set_transition_duration(300); - ..set_transition_type(RevealerTransitionType::SlideUp); + ..set_transition_duration(150); + ..set_transition_type(RevealerTransitionType::SwingUp); }; cursor_handle.append(&revealer); @@ -107,7 +107,7 @@ impl Window { dock.append(&separator); let active_app_list_view = cascade! { - ListView::builder().build(); + ListView::default(); ..set_orientation(Orientation::Horizontal); }; dock.append(&active_app_list_view); diff --git a/examples/launcher/main.rs b/examples/launcher/main.rs index f7da4aa..b680f68 100644 --- a/examples/launcher/main.rs +++ b/examples/launcher/main.rs @@ -26,20 +26,6 @@ const NUM_LAUNCHER_ITEMS: u8 = 10; static TX: OnceCell> = OnceCell::new(); static X11_CONN: OnceCell = OnceCell::new(); -fn icon_source(icon: >k4::Image, source: &Option) { - match source { - Some(pop_launcher::IconSource::Name(name)) => { - icon.set_from_icon_name(Some(name)); - } - Some(pop_launcher::IconSource::Mime(content_type)) => { - icon.set_from_gicon(&gio::content_type_get_icon(content_type)); - } - _ => { - icon.set_from_icon_name(None); - } - } -} - pub enum Event { Response(pop_launcher::Response), Search(String), diff --git a/examples/launcher/search_result_row/imp.rs b/examples/launcher/search_result_row/imp.rs index 53dc015..0afa5bc 100644 --- a/examples/launcher/search_result_row/imp.rs +++ b/examples/launcher/search_result_row/imp.rs @@ -1,21 +1,15 @@ use gtk4::glib; -use gtk4::prelude::*; use gtk4::subclass::prelude::*; -use gtk4::CompositeTemplate; +use std::cell::RefCell; +use std::rc::Rc; -#[derive(Debug, Default, CompositeTemplate)] -#[template(file = "application_row.ui")] +#[derive(Debug, Default)] pub struct SearchResultRow { - #[template_child] - pub name: TemplateChild, - #[template_child] - pub description: TemplateChild, - #[template_child] - pub shortcut: TemplateChild, - #[template_child] - pub image: TemplateChild, - #[template_child] - pub categoryimage: TemplateChild, + pub name: Rc>, + pub description: Rc>, + pub shortcut: Rc>, + pub image: Rc>, + pub category_image: Rc>, } #[glib::object_subclass] @@ -23,14 +17,6 @@ impl ObjectSubclass for SearchResultRow { const NAME: &'static str = "SearchResultRow"; type Type = super::SearchResultRow; type ParentType = gtk4::Box; - - fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); - } - - fn instance_init(obj: &glib::subclass::InitializingObject) { - obj.init_template(); - } } impl ObjectImpl for SearchResultRow {} diff --git a/examples/launcher/search_result_row/mod.rs b/examples/launcher/search_result_row/mod.rs index 8e46a09..f86af9a 100644 --- a/examples/launcher/search_result_row/mod.rs +++ b/examples/launcher/search_result_row/mod.rs @@ -1,8 +1,15 @@ -use gtk4::glib; +use cascade::cascade; +use glib; +use gtk4::pango::EllipsizeMode; use gtk4::prelude::*; use gtk4::subclass::prelude::*; +use gtk4::Align; +use gtk4::Box; +use gtk4::Image; +use gtk4::Label; +use gtk4::Orientation; -use crate::icon_source; +use crate::utils::icon_source; use crate::BoxedSearchResult; use crate::SearchResultObject; @@ -10,7 +17,8 @@ mod imp; glib::wrapper! { pub struct SearchResultRow(ObjectSubclass) - @extends gtk4::Widget, gtk4::Box; + @extends gtk4::Widget, gtk4::Box, + @implements gtk4::Accessible, gtk4::Buildable, gtk4::ConstraintTarget, gtk4::Orientable; } impl Default for SearchResultRow { @@ -21,7 +29,75 @@ impl Default for SearchResultRow { impl SearchResultRow { pub fn new() -> Self { - glib::Object::new(&[]).expect("Failed to create SearchResultRow") + let self_ = glib::Object::new(&[]).expect("Failed to create SearchResultRow"); + let imp = imp::SearchResultRow::from_instance(&self_); + + cascade! { + &self_; + ..set_orientation(Orientation::Horizontal); + ..set_spacing(12); + ..set_margin_start(4); + ..set_margin_end(4); + ..set_hexpand(true); + }; + + let category_image = cascade! { + Image::new(); + ..set_pixel_size(24); + }; + self_.append(&category_image); + + let image = cascade! { + Image::new(); + ..set_margin_top(4); + ..set_margin_bottom(4); + ..set_pixel_size(40); + }; + self_.append(&image); + + let text_container = cascade! { + Box::new(Orientation::Vertical, 0); + ..set_halign(Align::Fill); + ..set_hexpand(true); + ..set_margin_top(4); + ..set_margin_end(4); + ..set_margin_bottom(4); + }; + self_.append(&text_container); + + let shortcut = cascade! { + Label::new(None); + ..set_halign(Align::End); + ..set_wrap(false); + ..add_css_class("body"); + }; + self_.append(&shortcut); + + let name = cascade! { + Label::new(None); + ..set_halign(Align::Start); + ..set_ellipsize(EllipsizeMode::End); + ..set_max_width_chars(40); + ..add_css_class("title-4"); + }; + text_container.append(&name); + + let description = cascade! { + Label::new(None); + ..set_halign(Align::Start); + ..set_ellipsize(EllipsizeMode::End); + ..set_max_width_chars(50); + ..add_css_class("body"); + }; + text_container.append(&description); + + imp.category_image.replace(category_image); + imp.image.replace(image); + imp.name.replace(name); + imp.description.replace(description); + imp.shortcut.replace(shortcut); + + self_ } pub fn set_search_result(&self, search_obj: SearchResultObject) { @@ -29,10 +105,13 @@ impl SearchResultRow { if let Ok(search_result) = search_obj.property("data") { if let Ok(search_result) = search_result.get::() { if let Some(search_result) = search_result.0 { - self_.name.set_text(&search_result.name); - self_.description.set_text(&search_result.description); + self_.name.borrow().set_text(&search_result.name); + self_ + .description + .borrow() + .set_text(&search_result.description); icon_source(&self_.image, &search_result.icon); - icon_source(&self_.categoryimage, &search_result.category_icon); + icon_source(&self_.category_image, &search_result.category_icon); } } } @@ -40,6 +119,9 @@ impl SearchResultRow { pub fn set_shortcut(&self, indx: u32) { let self_ = imp::SearchResultRow::from_instance(self); - self_.shortcut.set_text(&format!("Ctrl + {}", indx)); + self_ + .shortcut + .borrow() + .set_text(&format!("Ctrl + {}", indx)); } } diff --git a/examples/launcher/style.css b/examples/launcher/style.css index 5c2ffa4..fa2f125 100644 --- a/examples/launcher/style.css +++ b/examples/launcher/style.css @@ -1,17 +1,24 @@ -row:hover { +listview row:hover { transition: 100ms; background: #888888; + border-radius: 8px; } -row { +listview row { background: #333333; + border-radius: 8px; } listview { background: #333333; } -window { +box.container { background: #333333; - border-radius: 15px; + padding: 12px; + border-radius: 12px; +} + +window { + background: rgba(50, 50, 50, 0.0); } diff --git a/examples/launcher/utils.rs b/examples/launcher/utils.rs index 2be7481..55a4395 100644 --- a/examples/launcher/utils.rs +++ b/examples/launcher/utils.rs @@ -1,3 +1,21 @@ +use std::cell::RefCell; +use std::rc::Rc; + #[derive(Clone, Debug, Default, glib::GBoxed)] #[gboxed(type_name = "BoxedSearchResult")] pub struct BoxedSearchResult(pub Option); + +pub fn icon_source(icon: &Rc>, source: &Option) { + match source { + Some(pop_launcher::IconSource::Name(name)) => { + icon.borrow().set_from_icon_name(Some(name)); + } + Some(pop_launcher::IconSource::Mime(content_type)) => { + icon.borrow() + .set_from_gicon(&gio::content_type_get_icon(content_type)); + } + _ => { + icon.borrow().set_from_icon_name(None); + } + } +} diff --git a/examples/launcher/window/imp.rs b/examples/launcher/window/imp.rs index 0954fcd..9aaa76f 100644 --- a/examples/launcher/window/imp.rs +++ b/examples/launcher/window/imp.rs @@ -1,18 +1,13 @@ -use glib::subclass::InitializingObject; -use gtk4::prelude::*; use gtk4::subclass::prelude::*; use gtk4::{gio, glib}; -use gtk4::{CompositeTemplate, Entry, ListView}; +use gtk4::{Entry, ListView}; use once_cell::sync::OnceCell; // Object holding the state -#[derive(CompositeTemplate, Default)] -#[template(file = "window.ui")] +#[derive(Default)] pub struct Window { - #[template_child] - pub entry: TemplateChild, - #[template_child] - pub list_view: TemplateChild, + pub entry: OnceCell, + pub list_view: OnceCell, pub model: OnceCell, } @@ -23,28 +18,10 @@ impl ObjectSubclass for Window { const NAME: &'static str = "LauncherWindow"; type Type = super::Window; type ParentType = gtk4::ApplicationWindow; - - fn class_init(klass: &mut Self::Class) { - Self::bind_template(klass); - } - - fn instance_init(obj: &InitializingObject) { - obj.init_template(); - } } // Trait shared by all GObjects -impl ObjectImpl for Window { - fn constructed(&self, obj: &Self::Type) { - // Call "constructed" on parent - self.parent_constructed(obj); - - // Setup - obj.setup_model(); - obj.setup_callbacks(); - obj.setup_factory(); - } -} +impl ObjectImpl for Window {} // Trait shared by all widgets impl WidgetImpl for Window {} diff --git a/examples/launcher/window/mod.rs b/examples/launcher/window/mod.rs index 06c1135..e9ef997 100644 --- a/examples/launcher/window/mod.rs +++ b/examples/launcher/window/mod.rs @@ -1,9 +1,14 @@ +use cascade::cascade; use gdk4::Rectangle; use gdk4_x11::X11Display; use gdk4_x11::X11Surface; use glib::Object; use gtk4::prelude::*; use gtk4::subclass::prelude::*; +use gtk4::Box; +use gtk4::Entry; +use gtk4::ListView; +use gtk4::Orientation; use gtk4::{gio, glib}; use gtk4::{Application, SignalListItemFactory}; use postage::prelude::Sink; @@ -32,6 +37,41 @@ const NUM_LAUNCHER_ITEMS: u8 = 9; impl Window { pub fn new(app: &Application) -> Self { let self_: Self = Object::new(&[("application", app)]).expect("Failed to create `Window`."); + let imp = imp::Window::from_instance(&self_); + + cascade! { + &self_; + ..set_width_request(600); + ..set_title(Some("Cosmic Launcher")); + ..set_decorated(false); + ..set_resizable(false); + }; + + let container = cascade! { + Box::new(Orientation::Vertical, 0); + ..add_css_class("container"); + }; + self_.set_child(Some(&container)); + + let entry = cascade! { + Entry::new(); + ..set_margin_bottom(12); + }; + container.append(&entry); + + let list_view = cascade! { + ListView::default(); + ..set_orientation(Orientation::Vertical); + }; + container.append(&list_view); + + imp.entry.set(entry).unwrap(); + imp.list_view.set(list_view).unwrap(); + + // Setup + self_.setup_model(); + self_.setup_callbacks(); + self_.setup_factory(); self_ } @@ -56,7 +96,10 @@ impl Window { imp.model.set(model).expect("Could not set model"); // Wrap model with selection and pass it to the list view - imp.list_view.set_model(Some(&selection_model)); + imp.list_view + .get() + .unwrap() + .set_model(Some(&selection_model)); } fn setup_callbacks(&self) { @@ -64,8 +107,8 @@ impl Window { let imp = imp::Window::from_instance(self); let window = self.clone().upcast::(); let list_view = &imp.list_view; - let entry = &imp.entry; - let lv = list_view.get(); + let entry = &imp.entry.get().unwrap(); + let lv = list_view.get().unwrap(); for i in 1..10 { let action_launchi = gio::SimpleAction::new(&format!("launch{}", i), None); self.add_action(&action_launchi); @@ -90,7 +133,7 @@ impl Window { })); } - let app_selection_model = list_view + let app_selection_model = lv .model() .expect("List view missing selection model") .downcast::() @@ -243,6 +286,6 @@ impl Window { }); // Set the factory of the list view let imp = imp::Window::from_instance(self); - imp.list_view.set_factory(Some(&factory)); + imp.list_view.get().unwrap().set_factory(Some(&factory)); } }