From 0a91ca0ccd88e8baf50459b45b5a0fe570a7263b Mon Sep 17 00:00:00 2001 From: Jeremy Soller Date: Tue, 16 Nov 2021 11:44:08 -0700 Subject: [PATCH] Render launcher items --- Cargo.toml | 2 +- examples/launcher/main.rs | 91 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 85 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fb70e679..0bcdd55d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" cascade = "1" gdk4 = "0.3.1" gdk4-x11 = "0.3.0" -glib = "0.14.8" +gio = "0.14.8" gtk4 = "0.3.1" x11 = { version = "2", features = ["xlib"] } # examples/launcher diff --git a/examples/launcher/main.rs b/examples/launcher/main.rs index c5f06ce0..f46d4a7d 100644 --- a/examples/launcher/main.rs +++ b/examples/launcher/main.rs @@ -10,6 +10,22 @@ use std::{ use self::ipc::LauncherIpc; mod ipc; +fn icon_source(icon: >k::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); + } + } +} + fn main() { let launcher = Rc::new(RefCell::new( LauncherIpc::new().expect("failed to connect to launcher service") @@ -22,26 +38,87 @@ fn main() { app.connect_activate(move |app| { let window = gtk::ApplicationWindow::builder() .application(app) + .decorated(false) .default_width(480) .default_height(440) .title("Launcher") .build(); - let vbox = gtk::Box::new(gtk::Orientation::Vertical, 4); + let vbox = gtk::Box::new(gtk::Orientation::Vertical, 16); + vbox.set_margin_start(16); + vbox.set_margin_end(16); + vbox.set_margin_top(16); + vbox.set_margin_bottom(16); window.set_child(Some(&vbox)); let search = gtk::Entry::new(); + search.set_placeholder_text(Some(" Type to search apps, or type '?' for more options.")); vbox.append(&search); + let listbox = gtk::ListBox::new(); + vbox.append(&listbox); + { let launcher = launcher.clone(); - search.connect_changed(move |search| { - let response = launcher.borrow_mut().request( - pop_launcher::Request::Search(search.text().to_string()) - ).expect("failed to access launcher service"); + let search_changed = move |search: >k::Entry| { + //TODO: is this the best way to clear a listbox? + while let Some(child) = listbox.last_child() { + listbox.remove(&child); + } - println!("{:?}", response); - }); + let response_res = launcher.borrow_mut().request( + pop_launcher::Request::Search(search.text().to_string()) + ); + + println!("{:#?}", response_res); + + if let Ok(pop_launcher::Response::Update(results)) = response_res { + for (i, result) in results.iter().enumerate() { + // Limit to 9 results + if i >= 9 { continue; } + + let row = gtk::ListBoxRow::new(); + listbox.append(&row); + + // Select first row + if i == 0 { + listbox.select_row(Some(&row)); + } + + let hbox = gtk::Box::new(gtk::Orientation::Horizontal, 8); + hbox.set_margin_start(8); + hbox.set_margin_end(8); + hbox.set_margin_top(8); + hbox.set_margin_bottom(8); + row.set_child(Some(&hbox)); + + let category_icon = gtk::Image::new(); + category_icon.set_pixel_size(16); + icon_source(&category_icon, &result.category_icon); + hbox.append(&category_icon); + + let icon = gtk::Image::new(); + icon.set_pixel_size(32); + icon_source(&icon, &result.icon); + hbox.append(&icon); + + let labels = gtk::Box::new(gtk::Orientation::Vertical, 4); + hbox.append(&labels); + + let name = gtk::Label::new(Some(&result.name)); + name.set_halign(gtk::Align::Start); + labels.append(&name); + + let description = gtk::Label::new(Some(&result.description)); + description.set_halign(gtk::Align::Start); + labels.append(&description); + } + } + }; + + search.connect_changed(search_changed.clone()); + + search_changed(&search); } // Setting the window to dialog type must happen between realize and show. Dialog windows