use std::{cell::Cell, rc::Rc, path::Path}; use appindicator3::{Indicator, prelude::AppIndicatorExt, IndicatorStatus, IndicatorCategory}; use gdk::gio::Icon; use gtk::{prelude::*, MenuItem}; const CAN_HAZ_LABEL: bool = true; fn image_menu_item(icon: &str, label: &str) -> gtk::MenuItem{ let g_box = gtk::Box::new(gtk::Orientation::Horizontal, 6); let icon = gtk::Image::from_gicon(&Icon::for_string(icon).unwrap(), gtk::IconSize::Menu); let label = gtk::Label::new(Some(label)); let menu_item = gtk::MenuItem::new(); g_box.add(&icon); g_box.add(&label); menu_item.add(&g_box); menu_item.show_all(); menu_item } fn item_clicked(item: &MenuItem) { println!("{} clicked!", item.label().unwrap()); } fn append_submenu (parent: >k::MenuItem) { let menu = gtk::Menu::new(); let mi = gtk::MenuItem::with_label("Sub 1"); mi.connect_activate(item_clicked); menu.append(&mi); let prev_mi = mi; let mi = gtk::MenuItem::with_label("Sub 2"); mi.connect_activate(glib::clone!(@weak prev_mi => move |_| { toggle_sensitivity(&prev_mi.upcast::()); })); menu.append(&mi); let mi = gtk::MenuItem::with_label("Sub 3"); mi.connect_activate(item_clicked); menu.append(&mi); menu.show_all(); parent.set_submenu(Some(&menu)); } fn toggle_sensitivity (widget: >k::Widget) { widget.set_sensitive(!widget.is_sensitive()); } fn main() -> Result<(), glib::BoolError> { let icon_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("examples"); gtk::init()?; let can_haz_label = Rc::new(Cell::new(CAN_HAZ_LABEL)); let mut percentage = 0.0; let indicator = Indicator::new("example-simple-client", "indicator-messages", IndicatorCategory::ApplicationStatus); indicator.set_icon_theme_path(icon_path.to_str().unwrap()); indicator.set_status(IndicatorStatus::Active); indicator.set_attention_icon_full("indicator-messages-new", "Messages Icon Highlighted"); indicator.set_label("1%", "100%"); indicator.set_title(Some("Test Indicator")); indicator.connect_scroll_event(|_, delta, direction| { println!("Got scroll event! delta: {}, direction: {}", delta, direction); }); indicator.connect_label_notify(move |ind|{ if let Some(label) = ind.label() { println!("Label changed! {}", label); } }); glib::timeout_add_seconds_local(1, glib::clone!(@weak indicator, @weak can_haz_label => @default-return glib::ControlFlow::Break, move || { percentage = (percentage + 1.0) % 100.0; if can_haz_label.get() { let percentstr = format!("{:.2}", percentage + 1.0); indicator.set_label(&percentstr, "100%"); } else { indicator.set_label("", ""); } glib::ControlFlow::Continue })); let menu = gtk::Menu::new(); let item = gtk::CheckMenuItem::with_label("1"); item.connect_activate(|item| { item_clicked(item.upcast_ref::()) }); menu.append(&item); item.show(); let item = gtk::RadioMenuItem::with_label("2"); item.connect_activate(|item| { item_clicked(item.upcast_ref::()) }); menu.append(&item); item.show(); let item = gtk::MenuItem::with_label("3"); append_submenu(&item); menu.append(&item); item.show(); let toggle = gtk::MenuItem::with_label("Toggle 3"); toggle.connect_activate( |item| { toggle_sensitivity(item.upcast_ref::()); }); menu.append(&toggle); toggle.show(); let image = image_menu_item("gtk-new", "Icon"); image.connect_activate(|item| { let g_box = item.child().unwrap().downcast::().unwrap(); for ref item in g_box.children() { if let Some(image) = item.downcast_ref::() { image.set_from_gicon(&Icon::for_string("gtk-open").unwrap(), gtk::IconSize::Menu); } } }); menu.append(&image); image.show(); let item = gtk::MenuItem::with_label("Get Attention"); let active_flag = Rc::new(Cell::new(false)); item.connect_activate(glib::clone!(@weak indicator, @weak active_flag => move |item| { if active_flag.get() { indicator.set_status(IndicatorStatus::Attention); item.set_label("I'm okay now"); active_flag.set(false); } else { indicator.set_status(IndicatorStatus::Active); item.set_label("Get Attention"); active_flag.set(true); } })); menu.append(&item); item.show(); indicator.set_secondary_activate_target(Some(&item)); let item = gtk::MenuItem::with_label("Hide label"); item.connect_activate(glib::clone!(@weak can_haz_label => move |item| { can_haz_label.set(!can_haz_label.get()); if can_haz_label.get() { item.set_label("Hide label"); } else { item.set_label("Show label"); } })); menu.append(&item); item.show(); let item = gtk::CheckMenuItem::with_label("Switch Icon"); item.connect_activate(glib::clone!(@weak indicator => move |item| { if item.is_active() { indicator.set_icon_full("simple-client-test-icon", "Client Icon") } else { indicator.set_icon_full("indicator-messages", "Messages Icon") } })); menu.append(&item); item.show(); indicator.set_menu(Some(&menu)); gtk::main(); Ok(()) }