refactor launcher removing templates

This commit is contained in:
Ashley Wulber 2021-12-31 14:58:26 -05:00
parent 839a4a55d7
commit 7c0cf048ee
10 changed files with 188 additions and 84 deletions

View file

@ -36,4 +36,7 @@ package = "gtk4"
version = "0.3.1"
features = ["v4_4"]
[profile.release]
incremental = true
debug = 1

2
config.toml Normal file
View file

@ -0,0 +1,2 @@
[build]
rustflags = ["-C", "link-arg=-fuse-ld=lld"]

View file

@ -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);

View file

@ -26,20 +26,6 @@ const NUM_LAUNCHER_ITEMS: u8 = 10;
static TX: OnceCell<Sender<Event>> = OnceCell::new();
static X11_CONN: OnceCell<RustConnection> = OnceCell::new();
fn icon_source(icon: &gtk4::Image, source: &Option<pop_launcher::IconSource>) {
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),

View file

@ -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<gtk4::Label>,
#[template_child]
pub description: TemplateChild<gtk4::Label>,
#[template_child]
pub shortcut: TemplateChild<gtk4::Label>,
#[template_child]
pub image: TemplateChild<gtk4::Image>,
#[template_child]
pub categoryimage: TemplateChild<gtk4::Image>,
pub name: Rc<RefCell<gtk4::Label>>,
pub description: Rc<RefCell<gtk4::Label>>,
pub shortcut: Rc<RefCell<gtk4::Label>>,
pub image: Rc<RefCell<gtk4::Image>>,
pub category_image: Rc<RefCell<gtk4::Image>>,
}
#[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<Self>) {
obj.init_template();
}
}
impl ObjectImpl for SearchResultRow {}

View file

@ -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<imp::SearchResultRow>)
@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::<BoxedSearchResult>() {
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));
}
}

View file

@ -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);
}

View file

@ -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<pop_launcher::SearchResult>);
pub fn icon_source(icon: &Rc<RefCell<gtk4::Image>>, source: &Option<pop_launcher::IconSource>) {
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);
}
}
}

View file

@ -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<Entry>,
#[template_child]
pub list_view: TemplateChild<ListView>,
pub entry: OnceCell<Entry>,
pub list_view: OnceCell<ListView>,
pub model: OnceCell<gio::ListStore>,
}
@ -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<Self>) {
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 {}

View file

@ -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::<gtk4::Window>();
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::<gtk4::SingleSelection>()
@ -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));
}
}