summary history branches tags files
commit:d0c1de8fab19fb496cbbf9309587d44577de57ad
author:Trevor Bentley
committer:Trevor Bentley
date:Mon Jul 10 10:34:28 2017 +0200
parents:29ed314877e3b0f04f0aab136c01ad9bac4e6cb5
scrubber callbacks mostly working
diff --git a/src/osx/mod.rs b/src/osx/mod.rs
line changes: +58/-48
index 8a11d83..7d124cc
--- a/src/osx/mod.rs
+++ b/src/osx/mod.rs
@@ -3,7 +3,7 @@ mod rustnsobject;
 #[cfg(feature = "mac_touchbar")]
 mod touchbar;
 #[cfg(feature = "mac_touchbar")]
-use self::touchbar::{Touchbar, TouchbarTrait};
+use self::touchbar::{Touchbar, TouchbarTrait, TScrubberData};
 #[cfg(not(feature = "mac_touchbar"))]
 struct Touchbar {}
 #[cfg(not(feature = "mac_touchbar"))]
@@ -39,9 +39,13 @@ use self::cocoa::appkit::{NSApp,
 use self::rustnsobject::{NSObj, NSObjTrait, NSObjCallbackTrait};
 
 use std::sync::mpsc::Sender;
+use std::sync::mpsc::channel;
 
 use std::ptr;
+use std::rc::Rc;
 use std::cell::Cell;
+use std::cell::RefCell;
+use std::borrow::BorrowMut;
 use std::ffi::CStr;
 use std::thread::sleep;
 use std::time::Duration;
@@ -68,50 +72,41 @@ pub struct OSXStatusBar {
 
     label: Cell<u64>,
     devices: Vec<String>,
+    scrubber: Rc<Scrubber>,
 }
 
 const ITEMS: &'static [&'static str] = &["a rather longer first one", "one","two","much longer than two","three", "seventeen", "A speaker with a very long name is not an impossible thing."];
 
-fn scrub_count(context: *const u32, item: touchbar::ItemId) -> u32 {
-    info!("MOD GOT SCRUBBER COUNT REQUEST");
-    let context = context as *const OSXStatusBar;
-    unsafe {
-        (*context).devices.len() as u32
-    } 
+struct Scrubber {
+    devices: RefCell<Vec<String>>,
+    touch_tx: Sender<(touchbar::ItemId,u32)>,
 }
-fn scrub_text(context: *const u32, item: touchbar::ItemId, idx: u32) -> String {
-    let context = context as *const OSXStatusBar;
-    unsafe {
+
+impl TScrubberData for Scrubber {
+    fn count(&self, item: touchbar::ItemId) -> u32 {
+        let dev = self.devices.borrow();
+        let len = (*dev).len();
+        info!("MOD GOT SCRUBBER COUNT REQUEST {}", len);
+        self.devices.borrow().len() as u32
+    }
+    fn text(&self, item: touchbar::ItemId, idx: u32) -> String {
         info!("MOD GOT SCRUBBER TEXT REQUEST {}", idx);
-        //"froop".to_string()
-        (*context).devices[idx as usize].to_string()
+        self.devices.borrow()[idx as usize].to_string()
     }
-}
-fn scrub_width(context: *const u32, item: touchbar::ItemId, idx: u32) -> u32 {
-    info!("scrub_width {} {:?}", idx, context);
-    // 10px per character + some padding seems to work nicely for the default
-    // font.  no idea what it's like on other machines.  does the touchbar
-    // font change? ¯\_(ツ)_/¯
-    unsafe {
-        let context = context as *const OSXStatusBar;
-        info!("context: {:?}", context);
-        let context: &OSXStatusBar = &*context;
-        info!("get len");
-        let devices: &Vec<String> = &context.devices;
-        info!("got devices");
-        info!("devices ptr: {:?}", devices as *const Vec<String>);
-        info!("devices len: {}", devices.len());
-        info!("{:?}", devices);
-        let ref s = (*context).devices[idx as usize];
-        info!("get string {}", s);
-        let len = s.len() as u32;
-        info!("got len {}", len);
+    fn width(&self, item: touchbar::ItemId, idx: u32) -> u32 {
+        info!("scrub_width {}", idx);
+        // 10px per character + some padding seems to work nicely for the default
+        // font.  no idea what it's like on other machines.  does the touchbar
+        // font change? ¯\_(ツ)_/¯
+        let len = self.devices.borrow()[idx as usize].len() as u32;
         let width = len * 8 + 20;
         info!("Width for {}: {}", len, width);
         width
     }
-}
-fn scrub_touch(context: *const u32, item: touchbar::ItemId, idx: u32) {
+    fn touch(&self, item: touchbar::ItemId, idx: u32) {
+        info!("scrub touch: {}", idx);
+        self.touch_tx.send((item, idx));
+    }
 }
 
 impl TStatusBar for OSXStatusBar {
@@ -120,8 +115,17 @@ impl TStatusBar for OSXStatusBar {
         let mut bar;
         unsafe {
             let app = NSApp();
+            let (touch_tx,touch_rx) = channel::<(touchbar::ItemId,u32)>();
             let status_bar = NSStatusBar::systemStatusBar(nil);
             let date_cls = Class::get("NSDate").unwrap();
+            let scrubber = Rc::new(Scrubber {
+                devices: RefCell::new(vec!["one".to_string(), "two".to_string(),
+                                           "a little bit longer one".to_string(),
+                                           "three".to_string(),
+                                           "this one is really quite a bit longer than the others".to_string()]),
+                //Vec::<String>::new(),
+                touch_tx: touch_tx,
+            });
             bar = OSXStatusBar {
                 app: app,
                 status_bar_item: status_bar.statusItemWithLength_(NSVariableStatusItemLength),
@@ -134,6 +138,7 @@ impl TStatusBar for OSXStatusBar {
                 run_date: msg_send![date_cls, distantPast],
                 label: Cell::new(0),
                 devices: Vec::new(),
+                scrubber: scrubber.clone(),
             };
             // Don't become foreground app on launch
             bar.app.setActivationPolicy_(NSApplicationActivationPolicyAccessory);
@@ -197,9 +202,6 @@ impl TStatusBar for OSXStatusBar {
             let b3id = bar.touchbar.create_button(nil, text, Box::new(move |_| {}));
             bar.touchbar.add_items_to_bar(popid, vec![b3id]);
 
-            let l1id = bar.touchbar.create_label();
-            bar.label.set(l1id);
-
             for item in ITEMS {
                 bar.devices.push(item.to_string());
             }
@@ -207,14 +209,22 @@ impl TStatusBar for OSXStatusBar {
             info!("devices: {:?}", (&bar.devices) as *const Vec<String>);
             let bar_ptr = &bar as *const OSXStatusBar as *const u32;
             info!("bar ptr: {:?}", bar_ptr);
+            //let testfn: Box<FnMut()> = Box::new(bar.test);
+            let scrubber1 = scrubber.clone();
+            let scrubber2 = scrubber.clone();
+            let scrubber3 = scrubber.clone();
+            let scrubber4 = scrubber.clone();
             let s1id = bar.touchbar.create_text_scrubber(
-                bar_ptr,
-                scrub_count,
-                scrub_text,
-                scrub_width,
-                scrub_touch);
+                Box::new(move |s|   { scrubber1.count(s) }),
+                Box::new(move |s,i| { scrubber2.text(s,i) }),
+                Box::new(move |s,i| { scrubber3.width(s,i) }),
+                Box::new(move |s,i| { scrubber4.touch(s,i) }),
+            );
             bar.touchbar.select_scrubber_item(s1id, 1);
 
+            let l1id = bar.touchbar.create_label();
+            bar.label.set(s1id);
+
             //bar.touchbar.add_items_to_bar(barid, vec![b1id, b2id, p1id]);
             bar.touchbar.add_items_to_bar(barid, vec![b1id, b2id, p1id, l1id, s1id]);
             bar.touchbar.set_bar_as_root(barid);
@@ -223,16 +233,16 @@ impl TStatusBar for OSXStatusBar {
             bar.touchbar.enable();
         }
         bar
-    }
+    }    
     fn touchbar(&mut self) {
         info!("Touchbar fucker!");
-        info!("devices: {:?}", (&self.devices) as *const Vec<String>);
-        let bar_ptr = self as *const OSXStatusBar as *const u32;
-        info!("bar ptr: {:?}", bar_ptr);
 
+        self.scrubber.devices.borrow_mut().push("a new device!".to_string());
+        let l1id = self.label.get();
+        //self.touchbar.select_scrubber_item(l1id, 0);
+        self.touchbar.refresh_scrubber(l1id);
+        //self.touchbar.update_label(l1id);
         unsafe {
-            let l1id = self.label.get();
-            self.touchbar.update_label(l1id);
 
             //let barid = self.touchbar.create_bar();
             //let text = NSString::alloc(nil).init_str("hi1");

diff --git a/src/osx/touchbar.rs b/src/osx/touchbar.rs
line changes: +43/-12
index b642500..c823931
--- a/src/osx/touchbar.rs
+++ b/src/osx/touchbar.rs
@@ -40,12 +40,22 @@ fn print_nsstring(str: *mut Object) {
     }
 }
 
+pub trait TScrubberData {
+    fn count(&self, item: ItemId) -> u32;
+    fn text(&self, item: ItemId, idx: u32) -> String;
+    fn width(&self, item: ItemId, idx: u32) -> u32;
+    fn touch(&self, item: ItemId, idx: u32);
+}
+
+//use std::rc::Rc;
+
 struct Scrubber {
+    //struct Scrubber<T> where T: TScrubberData {
+    //data: Rc<T>,
     count_cb: ScrubberCountFn,
     text_cb: ScrubberTextFn,
     width_cb: ScrubberWidthFn,
     touch_cb: ScrubberTouchFn,
-    context: *const u32,
     _item: ItemId,
     _scrubber: ItemId,
     _ident: Ident,
@@ -72,19 +82,25 @@ pub trait TouchbarTrait {
     fn create_label(&mut self) -> ItemId;
     fn update_label(&mut self, label_id: ItemId);
     fn create_text_scrubber(&mut self,
-                            context: *const u32,
                             count_fn: ScrubberCountFn,
                             text_fn: ScrubberTextFn,
                             width_fn: ScrubberWidthFn,
                             touch_fn: ScrubberTouchFn) -> ItemId;
     fn select_scrubber_item(&mut self, scrub_id: ItemId, index: u32);
+    fn refresh_scrubber(&mut self, scrub_id: ItemId);
     fn create_button(&mut self, image: *mut Object, text: *mut Object, cb: ButtonCb) -> ItemId;
 }
 
-pub type ScrubberCountFn = fn(*const u32, ItemId) -> u32;
-pub type ScrubberTextFn = fn(*const u32, ItemId, u32) -> String;
-pub type ScrubberWidthFn = fn(*const u32, ItemId, u32) -> u32;
-pub type ScrubberTouchFn = fn(*const u32, ItemId, u32);
+//pub type ScrubberCountFn = fn(*const u32, ItemId) -> u32;
+//pub type ScrubberTextFn = fn(*const u32, ItemId, u32) -> String;
+//pub type ScrubberWidthFn = fn(*const u32, ItemId, u32) -> u32;
+//pub type ScrubberTouchFn = fn(*const u32, ItemId, u32);
+
+pub type ScrubberCountFn = Box<Fn(ItemId) -> u32>;
+pub type ScrubberTextFn = Box<Fn(ItemId, u32) -> String>;
+pub type ScrubberWidthFn = Box<Fn(ItemId, u32) -> u32>;
+pub type ScrubberTouchFn = Box<Fn(ItemId, u32)>;
+
 
 impl RustTouchbarDelegateWrapper {
     fn generate_ident(&mut self) -> u64 {
@@ -235,7 +251,6 @@ impl TouchbarTrait for Touchbar {
         }
     }
     fn create_text_scrubber(&mut self,
-                            context: *const u32,
                             count_fn: ScrubberCountFn,
                             text_fn: ScrubberTextFn,
                             width_fn: ScrubberWidthFn,
@@ -271,7 +286,6 @@ impl TouchbarTrait for Touchbar {
                 count_cb: count_fn,
                 width_cb: width_fn,
                 touch_cb: touch_fn,
-                context: context,
                 _ident: ident as u64,
                 _item: item as u64,
                 _scrubber: scrubber as u64,
@@ -287,6 +301,15 @@ impl TouchbarTrait for Touchbar {
             let _:() = msg_send![scrubber, setSelectedIndex: index];
         }
     }
+    fn refresh_scrubber(&mut self, scrub_id: ItemId) {
+        unsafe {
+            let item = scrub_id as *mut Object;
+            let scrubber: *mut Object = msg_send![item, view];
+            //let layout: *mut Object = msg_send![scrubber, scrubberLayout];
+            //let _:() = msg_send![layout, invalidateLayout];
+            let _:() = msg_send![scrubber, reloadData];
+        }
+    }
     fn create_button(&mut self, image: *mut Object, text: *mut Object, cb: ButtonCb) -> ItemId {
         unsafe {
             let ident = self.generate_ident();
@@ -377,7 +400,7 @@ impl INSObject for ObjcAppDelegate {
                     let scrubber = scrub as *mut Object;
                     let scrub_struct = wrapper.scrubber_obj_map.get(&scrub).unwrap();
                     let item = scrub_struct._item;
-                    (scrub_struct.count_cb)(scrub_struct.context, item)
+                    (scrub_struct.count_cb)(item)
                 }
             }
             extern fn objc_scrubber_view_for_item_at_index(this: &mut Object, _cmd: Sel,
@@ -392,7 +415,7 @@ impl INSObject for ObjcAppDelegate {
                     let ident = scrub_struct._ident as *mut Object;
                     let view: *mut Object = msg_send![scrubber,
                                                       makeItemWithIdentifier:ident owner:nil];
-                    let text = (scrub_struct.text_cb)(scrub_struct.context, item, idx);
+                    let text = (scrub_struct.text_cb)(item, idx);
                     let text_field: *mut Object = msg_send![view, textField];
                     let objc_text: *mut Object = NSString::alloc(nil).init_str(&text);
                     let _:() = msg_send![text_field, setStringValue: objc_text];
@@ -410,13 +433,21 @@ impl INSObject for ObjcAppDelegate {
                     let scrub_struct = wrapper.scrubber_obj_map.get(&scrub).unwrap();
                     let item = scrub_struct._item;
                     info!("scrubber item size call CB");
-                    let width = (scrub_struct.width_cb)(scrub_struct.context, item, idx);
+                    let width = (scrub_struct.width_cb)(item, idx);
                     NSSize::new(width as f64, 30.)
                 }
             }
             extern fn objc_scrubber_did_select_item_at_index(this: &mut Object, _cmd: Sel,
-                                                             _scrub: u64, _idx: u32) {
+                                                             scrub: u64, idx: u32) {
                 info!("scrubber selected");
+                unsafe {
+                    let ptr: u64 = *this.get_ivar("_rust_wrapper");
+                    let wrapper = &mut *(ptr as *mut RustTouchbarDelegateWrapper);
+                    let scrubber = scrub as *mut Object;
+                    let scrub_struct = wrapper.scrubber_obj_map.get(&scrub).unwrap();
+                    let item = scrub_struct._item;
+                    (scrub_struct.touch_cb)(item, idx);
+                }
             }
             extern fn objc_popbar(this: &mut Object, _cmd: Sel, sender: u64) {
                 info!("Popbar push: {}", sender as u64);