refactor launcher removing templates
This commit is contained in:
parent
839a4a55d7
commit
7c0cf048ee
10 changed files with 188 additions and 84 deletions
|
|
@ -36,4 +36,7 @@ package = "gtk4"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
features = ["v4_4"]
|
features = ["v4_4"]
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
incremental = true
|
||||||
|
debug = 1
|
||||||
|
|
||||||
|
|
|
||||||
2
config.toml
Normal file
2
config.toml
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
[build]
|
||||||
|
rustflags = ["-C", "link-arg=-fuse-ld=lld"]
|
||||||
|
|
@ -78,8 +78,8 @@ impl Window {
|
||||||
Revealer::new();
|
Revealer::new();
|
||||||
..set_reveal_child(true);
|
..set_reveal_child(true);
|
||||||
..set_valign(Align::Baseline);
|
..set_valign(Align::Baseline);
|
||||||
..set_transition_duration(300);
|
..set_transition_duration(150);
|
||||||
..set_transition_type(RevealerTransitionType::SlideUp);
|
..set_transition_type(RevealerTransitionType::SwingUp);
|
||||||
};
|
};
|
||||||
cursor_handle.append(&revealer);
|
cursor_handle.append(&revealer);
|
||||||
|
|
||||||
|
|
@ -107,7 +107,7 @@ impl Window {
|
||||||
dock.append(&separator);
|
dock.append(&separator);
|
||||||
|
|
||||||
let active_app_list_view = cascade! {
|
let active_app_list_view = cascade! {
|
||||||
ListView::builder().build();
|
ListView::default();
|
||||||
..set_orientation(Orientation::Horizontal);
|
..set_orientation(Orientation::Horizontal);
|
||||||
};
|
};
|
||||||
dock.append(&active_app_list_view);
|
dock.append(&active_app_list_view);
|
||||||
|
|
|
||||||
|
|
@ -26,20 +26,6 @@ const NUM_LAUNCHER_ITEMS: u8 = 10;
|
||||||
static TX: OnceCell<Sender<Event>> = OnceCell::new();
|
static TX: OnceCell<Sender<Event>> = OnceCell::new();
|
||||||
static X11_CONN: OnceCell<RustConnection> = OnceCell::new();
|
static X11_CONN: OnceCell<RustConnection> = OnceCell::new();
|
||||||
|
|
||||||
fn icon_source(icon: >k4::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 {
|
pub enum Event {
|
||||||
Response(pop_launcher::Response),
|
Response(pop_launcher::Response),
|
||||||
Search(String),
|
Search(String),
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,15 @@
|
||||||
use gtk4::glib;
|
use gtk4::glib;
|
||||||
use gtk4::prelude::*;
|
|
||||||
use gtk4::subclass::prelude::*;
|
use gtk4::subclass::prelude::*;
|
||||||
use gtk4::CompositeTemplate;
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Debug, Default, CompositeTemplate)]
|
#[derive(Debug, Default)]
|
||||||
#[template(file = "application_row.ui")]
|
|
||||||
pub struct SearchResultRow {
|
pub struct SearchResultRow {
|
||||||
#[template_child]
|
pub name: Rc<RefCell<gtk4::Label>>,
|
||||||
pub name: TemplateChild<gtk4::Label>,
|
pub description: Rc<RefCell<gtk4::Label>>,
|
||||||
#[template_child]
|
pub shortcut: Rc<RefCell<gtk4::Label>>,
|
||||||
pub description: TemplateChild<gtk4::Label>,
|
pub image: Rc<RefCell<gtk4::Image>>,
|
||||||
#[template_child]
|
pub category_image: Rc<RefCell<gtk4::Image>>,
|
||||||
pub shortcut: TemplateChild<gtk4::Label>,
|
|
||||||
#[template_child]
|
|
||||||
pub image: TemplateChild<gtk4::Image>,
|
|
||||||
#[template_child]
|
|
||||||
pub categoryimage: TemplateChild<gtk4::Image>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[glib::object_subclass]
|
#[glib::object_subclass]
|
||||||
|
|
@ -23,14 +17,6 @@ impl ObjectSubclass for SearchResultRow {
|
||||||
const NAME: &'static str = "SearchResultRow";
|
const NAME: &'static str = "SearchResultRow";
|
||||||
type Type = super::SearchResultRow;
|
type Type = super::SearchResultRow;
|
||||||
type ParentType = gtk4::Box;
|
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 {}
|
impl ObjectImpl for SearchResultRow {}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,15 @@
|
||||||
use gtk4::glib;
|
use cascade::cascade;
|
||||||
|
use glib;
|
||||||
|
use gtk4::pango::EllipsizeMode;
|
||||||
use gtk4::prelude::*;
|
use gtk4::prelude::*;
|
||||||
use gtk4::subclass::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::BoxedSearchResult;
|
||||||
use crate::SearchResultObject;
|
use crate::SearchResultObject;
|
||||||
|
|
||||||
|
|
@ -10,7 +17,8 @@ mod imp;
|
||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
pub struct SearchResultRow(ObjectSubclass<imp::SearchResultRow>)
|
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 {
|
impl Default for SearchResultRow {
|
||||||
|
|
@ -21,7 +29,75 @@ impl Default for SearchResultRow {
|
||||||
|
|
||||||
impl SearchResultRow {
|
impl SearchResultRow {
|
||||||
pub fn new() -> Self {
|
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) {
|
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_obj.property("data") {
|
||||||
if let Ok(search_result) = search_result.get::<BoxedSearchResult>() {
|
if let Ok(search_result) = search_result.get::<BoxedSearchResult>() {
|
||||||
if let Some(search_result) = search_result.0 {
|
if let Some(search_result) = search_result.0 {
|
||||||
self_.name.set_text(&search_result.name);
|
self_.name.borrow().set_text(&search_result.name);
|
||||||
self_.description.set_text(&search_result.description);
|
self_
|
||||||
|
.description
|
||||||
|
.borrow()
|
||||||
|
.set_text(&search_result.description);
|
||||||
icon_source(&self_.image, &search_result.icon);
|
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) {
|
pub fn set_shortcut(&self, indx: u32) {
|
||||||
let self_ = imp::SearchResultRow::from_instance(self);
|
let self_ = imp::SearchResultRow::from_instance(self);
|
||||||
self_.shortcut.set_text(&format!("Ctrl + {}", indx));
|
self_
|
||||||
|
.shortcut
|
||||||
|
.borrow()
|
||||||
|
.set_text(&format!("Ctrl + {}", indx));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,24 @@
|
||||||
row:hover {
|
listview row:hover {
|
||||||
transition: 100ms;
|
transition: 100ms;
|
||||||
background: #888888;
|
background: #888888;
|
||||||
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
row {
|
listview row {
|
||||||
background: #333333;
|
background: #333333;
|
||||||
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
listview {
|
listview {
|
||||||
background: #333333;
|
background: #333333;
|
||||||
}
|
}
|
||||||
|
|
||||||
window {
|
box.container {
|
||||||
background: #333333;
|
background: #333333;
|
||||||
border-radius: 15px;
|
padding: 12px;
|
||||||
|
border-radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
window {
|
||||||
|
background: rgba(50, 50, 50, 0.0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,21 @@
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, glib::GBoxed)]
|
#[derive(Clone, Debug, Default, glib::GBoxed)]
|
||||||
#[gboxed(type_name = "BoxedSearchResult")]
|
#[gboxed(type_name = "BoxedSearchResult")]
|
||||||
pub struct BoxedSearchResult(pub Option<pop_launcher::SearchResult>);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,13 @@
|
||||||
use glib::subclass::InitializingObject;
|
|
||||||
use gtk4::prelude::*;
|
|
||||||
use gtk4::subclass::prelude::*;
|
use gtk4::subclass::prelude::*;
|
||||||
use gtk4::{gio, glib};
|
use gtk4::{gio, glib};
|
||||||
use gtk4::{CompositeTemplate, Entry, ListView};
|
use gtk4::{Entry, ListView};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
|
|
||||||
// Object holding the state
|
// Object holding the state
|
||||||
#[derive(CompositeTemplate, Default)]
|
#[derive(Default)]
|
||||||
#[template(file = "window.ui")]
|
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
#[template_child]
|
pub entry: OnceCell<Entry>,
|
||||||
pub entry: TemplateChild<Entry>,
|
pub list_view: OnceCell<ListView>,
|
||||||
#[template_child]
|
|
||||||
pub list_view: TemplateChild<ListView>,
|
|
||||||
pub model: OnceCell<gio::ListStore>,
|
pub model: OnceCell<gio::ListStore>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -23,28 +18,10 @@ impl ObjectSubclass for Window {
|
||||||
const NAME: &'static str = "LauncherWindow";
|
const NAME: &'static str = "LauncherWindow";
|
||||||
type Type = super::Window;
|
type Type = super::Window;
|
||||||
type ParentType = gtk4::ApplicationWindow;
|
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
|
// Trait shared by all GObjects
|
||||||
impl ObjectImpl for Window {
|
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trait shared by all widgets
|
// Trait shared by all widgets
|
||||||
impl WidgetImpl for Window {}
|
impl WidgetImpl for Window {}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,14 @@
|
||||||
|
use cascade::cascade;
|
||||||
use gdk4::Rectangle;
|
use gdk4::Rectangle;
|
||||||
use gdk4_x11::X11Display;
|
use gdk4_x11::X11Display;
|
||||||
use gdk4_x11::X11Surface;
|
use gdk4_x11::X11Surface;
|
||||||
use glib::Object;
|
use glib::Object;
|
||||||
use gtk4::prelude::*;
|
use gtk4::prelude::*;
|
||||||
use gtk4::subclass::prelude::*;
|
use gtk4::subclass::prelude::*;
|
||||||
|
use gtk4::Box;
|
||||||
|
use gtk4::Entry;
|
||||||
|
use gtk4::ListView;
|
||||||
|
use gtk4::Orientation;
|
||||||
use gtk4::{gio, glib};
|
use gtk4::{gio, glib};
|
||||||
use gtk4::{Application, SignalListItemFactory};
|
use gtk4::{Application, SignalListItemFactory};
|
||||||
use postage::prelude::Sink;
|
use postage::prelude::Sink;
|
||||||
|
|
@ -32,6 +37,41 @@ const NUM_LAUNCHER_ITEMS: u8 = 9;
|
||||||
impl Window {
|
impl Window {
|
||||||
pub fn new(app: &Application) -> Self {
|
pub fn new(app: &Application) -> Self {
|
||||||
let self_: Self = Object::new(&[("application", app)]).expect("Failed to create `Window`.");
|
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_
|
self_
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -56,7 +96,10 @@ impl Window {
|
||||||
|
|
||||||
imp.model.set(model).expect("Could not set model");
|
imp.model.set(model).expect("Could not set model");
|
||||||
// Wrap model with selection and pass it to the list view
|
// 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) {
|
fn setup_callbacks(&self) {
|
||||||
|
|
@ -64,8 +107,8 @@ impl Window {
|
||||||
let imp = imp::Window::from_instance(self);
|
let imp = imp::Window::from_instance(self);
|
||||||
let window = self.clone().upcast::<gtk4::Window>();
|
let window = self.clone().upcast::<gtk4::Window>();
|
||||||
let list_view = &imp.list_view;
|
let list_view = &imp.list_view;
|
||||||
let entry = &imp.entry;
|
let entry = &imp.entry.get().unwrap();
|
||||||
let lv = list_view.get();
|
let lv = list_view.get().unwrap();
|
||||||
for i in 1..10 {
|
for i in 1..10 {
|
||||||
let action_launchi = gio::SimpleAction::new(&format!("launch{}", i), None);
|
let action_launchi = gio::SimpleAction::new(&format!("launch{}", i), None);
|
||||||
self.add_action(&action_launchi);
|
self.add_action(&action_launchi);
|
||||||
|
|
@ -90,7 +133,7 @@ impl Window {
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
let app_selection_model = list_view
|
let app_selection_model = lv
|
||||||
.model()
|
.model()
|
||||||
.expect("List view missing selection model")
|
.expect("List view missing selection model")
|
||||||
.downcast::<gtk4::SingleSelection>()
|
.downcast::<gtk4::SingleSelection>()
|
||||||
|
|
@ -243,6 +286,6 @@ impl Window {
|
||||||
});
|
});
|
||||||
// Set the factory of the list view
|
// Set the factory of the list view
|
||||||
let imp = imp::Window::from_instance(self);
|
let imp = imp::Window::from_instance(self);
|
||||||
imp.list_view.set_factory(Some(&factory));
|
imp.list_view.get().unwrap().set_factory(Some(&factory));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue