//! Global GUI state. use app_state::*; use audio::frontend::*; use gtk::DialogExt; use gtk::GtkWindowExt; use gtk::MessageDialogExt; use gtk::WidgetExt; use gtk; use gtk_sys::GTK_RESPONSE_YES; use prefs::*; use std::cell::RefCell; use std::rc::Rc; use support::audio::*; use ui::popup_menu::*; use ui::popup_window::*; use ui::prefs_dialog::*; use ui::tray_icon::*; #[cfg(feature = "notify")] use notif::*; /// The GUI struct mostly describing the main widgets (mostly wrapped) /// the user interacts with. pub struct Gui { _cant_construct: (), /// The tray icon. pub tray_icon: TrayIcon, /// The popup window. pub popup_window: PopupWindow, /// The popup menu. pub popup_menu: PopupMenu, /* prefs_dialog is dynamically created and destroyed */ /// The preferences dialog. pub prefs_dialog: RefCell>, } impl Gui { /// Constructor. The prefs dialog is initialized as `None`. pub fn new( builder_popup_window: gtk::Builder, builder_popup_menu: gtk::Builder, prefs: &Prefs, ) -> Gui { return Gui { _cant_construct: (), tray_icon: TrayIcon::new(prefs).unwrap(), popup_window: PopupWindow::new(builder_popup_window), popup_menu: PopupMenu::new(builder_popup_menu), prefs_dialog: RefCell::new(None), }; } } /// Initialize the GUI system. pub fn init(appstate: Rc>) where T: AudioFrontend + 'static, { { /* "global" audio signal handler */ let apps = appstate.clone(); appstate.audio.connect_handler( Box::new(move |s, u| match (s, u) { (AudioSignal::CardDisconnected, _) => { try_w!(audio_reload( apps.audio.as_ref(), &apps.prefs.borrow(), AudioUser::Unknown, )); } (AudioSignal::CardError, _) => { if run_audio_error_dialog( &apps.gui.popup_menu.menu_window, ) == (GTK_RESPONSE_YES as i32) { try_w!(audio_reload( apps.audio.as_ref(), &apps.prefs.borrow(), AudioUser::Unknown, )); } } _ => (), }), ); } init_tray_icon(appstate.clone()); init_popup_window(appstate.clone()); init_popup_menu(appstate.clone()); init_prefs_callback(appstate.clone()); #[cfg(feature = "notify")] init_notify(appstate.clone()); } /// Used to run a dialog when an audio error occured, suggesting the user /// may reload the audio system either manually or by confirming the dialog /// via the confirmation button. /// /// # Returns /// /// `GTK_RESPONSE_YES` if the user wants to reload the audio system, /// `GTK_RESPONSE_NO` otherwise. fn run_audio_error_dialog(parent: >k::Window) -> i32 { error!( "Connection with audio failed, you probably need to restart pnmixer." ); let dialog = gtk::MessageDialog::new( Some(parent), gtk::DialogFlags::DESTROY_WITH_PARENT, gtk::MessageType::Error, gtk::ButtonsType::YesNo, "Warning: Connection to sound system failed.", ); dialog.set_property_secondary_text(Some( "Do you want to re-initialize the audio connection ? If you do not, you will either need to restart PNMixer or select the 'Reload Audio' option in the right-click menu in order for PNMixer to function.", )); dialog.set_title("PNMixer-rs Error"); let resp = dialog.run(); dialog.destroy(); return resp; }