};
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");
}
};
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| {
};
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 {
};
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 {
};
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("");
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);
}
}
};
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 {
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 {
};
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;
}
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");
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
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("");
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);
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>,
}
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);
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,
}
return rust
}
- fn setup(self) -> NSObj {
- self
- }
fn selector(&self) -> Sel {
sel!(cb:)
}