summary history branches tags files
commit:f113c6567a0629377badc1b7869cf00a7716dc71
author:Trevor Bentley
committer:Trevor Bentley
date:Sun Aug 6 01:29:06 2017 +0200
parents:5fa0d0eb14639d7ec3d817b9f979906d3f24b4c4
Move volume into submenu on OS X
diff --git a/src/lib.rs b/src/lib.rs
line changes: +4/-2
index cd23921..719c248
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -86,7 +86,8 @@ pub trait TStatusBar {
     fn clear_items(&mut self);
     fn add_separator(&mut self);
     fn add_label(&mut self, label: &str);
-    fn add_item(&mut self, item: &str, callback: NSCallback, selected: bool) -> *mut Object;
+    fn add_submenu(&mut self, label: &str, callback: NSCallback) -> *mut Object;
+    fn add_item(&mut self, menu: Option<*mut Object>,item: &str, callback: NSCallback, selected: bool) -> *mut Object;
     fn add_quit(&mut self, label: &str);
     fn update_item(&mut self, item: *mut Object, label: &str);
     fn sel_item(&mut self, sender: u64);
@@ -105,8 +106,9 @@ impl TStatusBar for DummyStatusBar {
     fn can_redraw(&mut self) -> bool { true }
     fn clear_items(&mut self) {}
     fn add_separator(&mut self) {}
+    fn add_submenu(&mut self, _: &str, _: NSCallback) -> *mut Object { 0 as *mut Object }
     fn add_label(&mut self, _: &str) {}
-    fn add_item(&mut self, _: &str, _: NSCallback, _: bool) -> *mut Object { 0 as *mut Object }
+    fn add_item(&mut self, _: Option<*mut Object>, _: &str, _: NSCallback, _: bool) -> *mut Object{ 0 as *mut Object }
     fn add_quit(&mut self, _: &str) {}
     fn update_item(&mut self, _: *mut Object, _: &str) {}
     fn sel_item(&mut self, _: u64) {}

diff --git a/src/main.rs b/src/main.rs
line changes: +12/-11
index e37b4ed..a26890a
--- a/src/main.rs
+++ b/src/main.rs
@@ -436,12 +436,12 @@ fn reconfig_menu<T: TStatusBar>(status: &mut T) {
         };
         let _ = tx.send(serde_json::to_string(&cmd).unwrap());
     });
-    let _ = status.add_item("Reconfigure Connectr", cb, false);
+    let _ = status.add_item(None, "Reconfigure Connectr", cb, false);
     status.add_separator();
     let cb: NSCallback = Box::new(move |_sender, _tx| {
         let _ = open::that("https://github.com/mrmekon/connectr");
     });
-    let _ = status.add_item("Help!", cb, false);
+    let _ = status.add_item(None, "Help!", cb, false);
     status.add_separator();
     status.add_quit("Exit");
 }
@@ -539,7 +539,7 @@ fn fill_menu<T: TStatusBar>(app: &mut ConnectrApp,
             };
             let _ = tx.send(serde_json::to_string(&cmd).unwrap());
         });
-        app.menu.play = status.add_item(&play_str, cb, false);
+        app.menu.play = status.add_item(None, &play_str, cb, false);
         touchbar.update_play_button(is_playing);
 
         let cb: NSCallback = Box::new(move |sender, tx| {
@@ -550,7 +550,7 @@ fn fill_menu<T: TStatusBar>(app: &mut ConnectrApp,
             };
             let _ = tx.send(serde_json::to_string(&cmd).unwrap());
         });
-        app.menu.next = status.add_item("Next", cb, false);
+        app.menu.next = status.add_item(None, "Next", cb, false);
 
         let cb: NSCallback = Box::new(move |sender, tx| {
             let cmd = MenuCallbackCommand {
@@ -560,7 +560,7 @@ fn fill_menu<T: TStatusBar>(app: &mut ConnectrApp,
             };
             let _ = tx.send(serde_json::to_string(&cmd).unwrap());
         });
-        app.menu.prev = status.add_item("Previous", cb, false);
+        app.menu.prev = status.add_item(None, "Previous", cb, false);
 
         let cb: NSCallback = Box::new(move |sender, tx| {
             let cmd = MenuCallbackCommand {
@@ -570,7 +570,7 @@ fn fill_menu<T: TStatusBar>(app: &mut ConnectrApp,
             };
             let _ = tx.send(serde_json::to_string(&cmd).unwrap());
         });
-        app.menu.save = status.add_item("Quick-Save", cb, false);
+        app.menu.save = status.add_item(None, "Quick-Save", cb, false);
     }
 
     status.add_label("");
@@ -593,7 +593,7 @@ fn fill_menu<T: TStatusBar>(app: &mut ConnectrApp,
                 let _ = tx.send(serde_json::to_string(&cmd).unwrap());
             });
             let selected = player_state.playing_from_context(&preset.1);
-            let item = status.add_item(&name.clone(), cb, selected);
+            let item = status.add_item(None, &name.clone(), cb, selected);
             app.menu.preset.push(item);
         }
     }
@@ -635,7 +635,7 @@ fn fill_menu<T: TStatusBar>(app: &mut ConnectrApp,
             };
             let _ = tx.send(serde_json::to_string(&cmd).unwrap());
         });
-        let item = status.add_item(&dev.name, cb, dev.is_active);
+        let item = status.add_item(None, &dev.name, cb, dev.is_active);
         if dev.is_active {
             cur_volume_exact = dev.volume_percent.unwrap_or(0);
             cur_volume = match dev.volume_percent {
@@ -651,8 +651,9 @@ fn fill_menu<T: TStatusBar>(app: &mut ConnectrApp,
     info!("");
 
     status.add_label("");
-    status.add_label("Volume:");
+
     status.add_separator();
+    let volume_menu = status.add_submenu("Volume", Box::new(move |_,_| {}));
     {
         let mut i = 0;
         while i <= 100 {
@@ -665,7 +666,7 @@ fn fill_menu<T: TStatusBar>(app: &mut ConnectrApp,
                 };
                 let _ = tx.send(serde_json::to_string(&cmd).unwrap());
             });
-            let item = status.add_item(&vol_str, cb, i == cur_volume);
+            let item = status.add_item(Some(volume_menu), &vol_str, cb, i == cur_volume);
             app.menu.volume.push(item);
             i += 10;
         }
@@ -696,7 +697,7 @@ fn fill_menu<T: TStatusBar>(app: &mut ConnectrApp,
     let cb: NSCallback = Box::new(move |_sender, _tx| {
         let _ = open::that("https://open.spotify.com/search/");
     });
-    let _ = status.add_item("Search Spotify", cb, false);
+    let _ = status.add_item(None, "Search Spotify", cb, false);
 
     status.add_separator();
     status.add_quit("Exit");

diff --git a/src/osx/mod.rs b/src/osx/mod.rs
line changes: +29/-3
index 79f3d0a..e453e41
--- a/src/osx/mod.rs
+++ b/src/osx/mod.rs
@@ -49,7 +49,7 @@ impl TStatusBar for OSXStatusBar {
                 app: nsapp,
                 status_bar_item: status_bar.statusItemWithLength_(NSVariableStatusItemLength),
                 menu_bar: NSMenu::new(nil),
-                object: NSObj::alloc(tx).setup(),
+                object: NSObj::alloc(tx),
             };
 
             // Default mode for menu bar items: blue highlight when selected
@@ -150,7 +150,10 @@ impl TStatusBar for OSXStatusBar {
             self.menu_bar.addItem_(sep);
         }
     }
-    fn add_item(&mut self, item: &str, callback: NSCallback, selected: bool) -> *mut Object {
+    // TODO: whole API should accept menu option.  this whole thing should
+    // be split out into its own recursive menu-builder trait.  this is
+    // horrible.
+    fn add_item(&mut self, menu: Option<*mut Object>,item: &str, callback: NSCallback, selected: bool) -> *mut Object {
         unsafe {
             let txt = NSString::alloc(nil).init_str(item);
             let quit_key = NSString::alloc(nil).init_str("");
@@ -165,11 +168,34 @@ impl TStatusBar for OSXStatusBar {
                 let _: () = msg_send![app_menu_item, setState: 1];
             }
             let item: *mut Object = app_menu_item;
-            self.menu_bar.addItem_(app_menu_item);
+            match menu {
+                Some(menu) => { menu.addItem_(app_menu_item); },
+                None => { self.menu_bar.addItem_(app_menu_item); }
+            }
             let _: () = msg_send![app_menu_item, release];
             item
         }
     }
+    fn add_submenu(&mut self, label: &str, callback: NSCallback) -> *mut Object {
+        unsafe {
+            let submenu = NSMenu::new(nil);
+            let txt = NSString::alloc(nil).init_str(label);
+            let quit_key = NSString::alloc(nil).init_str("");
+            let app_menu_item = NSMenuItem::alloc(nil)
+                .initWithTitle_action_keyEquivalent_(txt,
+                                                     self.object.selector(),
+                                                     quit_key);
+            self.object.add_callback(app_menu_item, callback);
+            let objc = self.object.take_objc();
+            let _: () = msg_send![app_menu_item, setTarget: objc];
+            let _ = msg_send![app_menu_item, setSubmenu: submenu];
+            let _ = msg_send![txt, release];
+            let _ = msg_send![quit_key, release];
+            self.menu_bar.addItem_(app_menu_item);
+            let _ = msg_send![app_menu_item, release];
+            submenu
+        }
+    }
     fn update_item(&mut self, item: *mut Object, label: &str) {
         unsafe {
             let ns_label = NSString::alloc(nil).init_str(label);

diff --git a/src/osx/rustnsobject.rs b/src/osx/rustnsobject.rs
line changes: +1/-9
index 7937861..666b573
--- a/src/osx/rustnsobject.rs
+++ b/src/osx/rustnsobject.rs
@@ -21,13 +21,11 @@ use self::objc_id::Id;
 use self::objc_id::WeakId;
 use self::objc_id::Shared;
 
-use std::sync::mpsc::{channel, Sender, Receiver};
+use std::sync::mpsc::Sender;
 
 pub struct RustWrapperClass {
     pub objc: Id<ObjcSubclass, Shared>,
-    pub value: u64,
     pub cb_fn: Option<Box<Fn(&mut RustWrapperClass, u64)>>,
-    pub channel: (Sender<u32>, Receiver<u32>),
     pub map: BTreeMap<u64, NSCallback>,
     pub tx: Sender<String>,
 }
@@ -51,7 +49,6 @@ impl NSObjCallbackTrait for RustWrapperClass {
 
 pub trait NSObjTrait {
     fn alloc(tx: Sender<String>) -> NSObj;
-    fn setup(self) -> NSObj;
     fn selector(&self) -> Sel;
     fn take_objc(&mut self) -> NSObjc;
     fn add_callback(&mut self, *const Object, NSCallback);
@@ -66,8 +63,6 @@ impl NSObjTrait for NSObj {
         let objc = ObjcSubclass::new().share();
         let rust = Box::new(RustWrapperClass {
             objc: objc,
-            value: 716,
-            channel: channel(),
             map: BTreeMap::<u64,NSCallback>::new(),
             cb_fn: None,
             tx: tx,
@@ -78,9 +73,6 @@ impl NSObjTrait for NSObj {
         }
         return rust
     }
-    fn setup(self) -> NSObj {
-        self
-    }
     fn selector(&self) -> Sel {
         sel!(cb:)
     }