]> uap-core.de Git - note.git/commitdiff
handle note selection, load notes when they are selected main
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 24 May 2026 19:06:51 +0000 (21:06 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 24 May 2026 19:06:51 +0000 (21:06 +0200)
20 files changed:
application/src/main.rs
application/src/note.rs [new file with mode: 0644]
application/src/notebook.rs
application/src/window.rs
ui-rs-derive/src/lib.rs
ui-rs/src/ui/application.rs
ui-rs/src/ui/event.rs
ui-rs/src/ui/list.rs
ui-rs/src/ui/toolkit.rs
ui-rs/src/ui/window.rs
ui/common/args.c
ui/common/args.h
ui/common/document.c
ui/gtk/list.c
ui/gtk/list.h
ui/gtk/menu.c
ui/gtk/window.c
ui/ui/list.h
ui/ui/toolkit.h
ui/ui/widget.h

index 9e66688c3cc4795dec51561130d4a3ee227a74db..72eb8aeffe6d9ccf3a736fec6cd35ba8350ac010 100644 (file)
@@ -30,6 +30,7 @@ mod window;
 mod backend;
 mod newnotebook;
 mod notebook;
+mod note;
 
 use std::env;
 use entity::collection::{create_notebook_hierarchy, Node};
diff --git a/application/src/note.rs b/application/src/note.rs
new file mode 100644 (file)
index 0000000..3b1ea08
--- /dev/null
@@ -0,0 +1,21 @@
+use entity::note::NoteType;
+use ui_rs::{ui_actions, UiModel};
+use ui_rs::ui::*;
+
+
+#[derive(UiModel, Default)]
+pub struct Note {
+    pub note_id: i32,
+
+    #[bind("note_type")]
+    pub note_type: UiInteger,
+
+    #[bind("note_text")]
+    pub text: UiText
+}
+
+#[ui_actions]
+impl Note {
+
+
+}
\ No newline at end of file
index 86dd00649fe8c8f9715b4c2b17c9c9819b40d13e..128acfe8cddd51177d6492560b36b07ef7a90c98 100644 (file)
@@ -1,12 +1,15 @@
-use ui_rs::{ui_actions, UiModel};
+use ui_rs::{action, ui_actions, UiModel};
 use ui_rs::ui::*;
 
 use entity::note::Model as Note;
 
 #[derive(UiModel, Default)]
 pub struct Notebook {
+    pub doc_ref: UiDocRef<Notebook>,
     pub collection_id: i32,
 
+    pub selected_note: Option<UiDoc<crate::note::Note>>,
+
     #[bind("notes")]
     pub notes: UiList<Note>
 }
@@ -27,6 +30,43 @@ impl Notebook {
         }
         self.notes.update();
     }
+
+    #[action]
+    pub fn note_selected(&mut self, event: &ActionEvent) {
+        if let (EventType::ListSelection(s)) = event.event_type {
+            if let Some(note) = s.selected_element(self.notes.data()) {
+                // detach the current note
+                if let Some(current) = &self.selected_note {
+                    self.doc_ref.get_doc().unwrap().ctx.detach(current);
+                    self.selected_note = None;
+                }
+
+                // Create the new note
+                let mut note_data: crate::note::Note = Default::default();
+                // TODO: setting the text here is the right thing to do, but for some
+                //       reasons it doesn't work yet. Fix this shit.
+                //note_data.text.set(note.content.as_str());
+
+                // Create the note document object
+                let note_doc = UiDoc::new2(note_data, |n,d| {
+                    // TODO: remove this when toolkit is not that buggy
+                    //       for some reason we have to attach the doc first, before we can
+                    //       set the text
+                    if let Some(mut nb) = self.doc_ref.get_doc() {
+                        nb.ctx.attach(&d);
+                    }
+
+                    n.text.set(note.content.as_str());
+                });
+
+                // Attach the new note
+                if let Some(mut nb) = self.doc_ref.get_doc() {
+                    nb.ctx.attach(&note_doc);
+                    self.selected_note = Some(note_doc);
+                }
+            }
+        }
+    }
 }
 
 pub fn note_getvalue<'a>(elm: &Note, col: i32, _row: i32) -> ListValue<'a> {
index 9d399329c525dc80435888d4ab514c45a0c05d10..8785995142ac8a974c1d0db0bc395a32a1dfac34 100644 (file)
@@ -133,7 +133,9 @@ pub fn create_window(app: &App, ctx: &AppContext<MainWindow>) -> UiObject<MainWi
                             }
 
                             let notebook = Notebook::new(nb.collection_id);
-                            let doc = UiDoc::new(notebook);
+                            let doc = UiDoc::new2(notebook, |notebook, doc| {
+                                notebook.doc_ref = doc.doc_ref();
+                            });
                             let proxy = doc.doc_proxy();
                             e.data.backend.get_notes(nb.collection_id, |result|{
                                 proxy.call_mainthread(|nb| {
@@ -166,6 +168,7 @@ pub fn create_window(app: &App, ctx: &AppContext<MainWindow>) -> UiObject<MainWi
                 .model(&model)
                 .fill(true)
                 .getvalue(note_getvalue)
+                .onselection_action(("note_selected"))
                 .create();
         });
 
@@ -177,11 +180,12 @@ pub fn create_window(app: &App, ctx: &AppContext<MainWindow>) -> UiObject<MainWi
                     b.varname("note_type");
                 },
                 |tabview| {
-                    tabview.tab("empty", |_obj| {});
+                    //tabview.tab("empty", |_obj| {});
 
                     tabview.tab("textnote", |obj| {
                         obj.textarea(|b|{
                            b.fill(true);
+                            b.varname("note_text");
                         });
                     });
                 });
index 51f043c1e69a7d177214fc60f0884b7c32c99f12..03fc8f283f53607ca1fb63562d13050d34c3c232 100644 (file)
@@ -170,7 +170,7 @@ pub fn ui_actions(_attr: TokenStream, item: TokenStream) -> TokenStream {
     let expanded = quote! {
         #impl_block
         impl UiActions for #self_ty {
-            fn init_actions(&mut self, ctx: &mut UiContext) {
+            fn init_actions(&mut self, ctx: &UiContext) {
                 unsafe {
                     #(
                         ctx.add_action(
index 7fccda44f9eab00dfbac1180b38235b6c466031e..df3aee089dcd55eb471eb4e1550b15f5e1c9cc4e 100644 (file)
@@ -53,7 +53,7 @@ impl UiModel for NoAppData {
 }
 
 impl UiActions for NoAppData {
-    fn init_actions(&mut self, _ctx: &mut UiContext) {}
+    fn init_actions(&mut self, _ctx: &UiContext) {}
 }
 
 extern "C" {
index 1ba0850b1d266ffea474e6dedeb2fb70a5ceab7c..7536e3fc1174fc88ff71de821950a6c008cc4439 100644 (file)
@@ -93,7 +93,7 @@ fn get_event_data(e: *const ffi::UiEvent) -> EventTypeData {
         }
         5 => {
             let t: *mut ffi::UiText = ptr.cast();
-            EventTypeData::TextValue( UiText { ptr: t } )
+            EventTypeData::TextValue( UiText::from_ptr(t) )
         }
         6 => {
             let d: *mut ffi::UiDouble = ptr.cast();
index 1bb73b71e36652ae90f66f5941b293749c9f57db..11a9cc143d4123283a2a1bfcf153d04724553044 100644 (file)
@@ -322,6 +322,14 @@ impl<'a, T, E> ListViewBuilder<'a, T, E> {
         }
         self
     }
+    
+    pub fn onactivate_action(&mut self, action: &str) -> &mut Self {
+        let cstr = CString::new(action).unwrap();
+        unsafe {
+            ui_list_args_set_onactivate_action(self.args, cstr.as_ptr());
+        }
+        self
+    }
 
     pub fn onselection<F>(&mut self, f: F) -> &mut Self
     where F: FnMut(&mut event::Event<T>) + 'static {
@@ -334,6 +342,14 @@ impl<'a, T, E> ListViewBuilder<'a, T, E> {
         self
     }
 
+    pub fn onselection_action(&mut self, action: &str) -> &mut Self {
+        let cstr = CString::new(action).unwrap();
+        unsafe {
+            ui_list_args_set_onselection_action(self.args, cstr.as_ptr());
+        }
+        self
+    }
+
     pub fn multiselection(&mut self, value: bool) -> &mut Self {
         unsafe {
             ui_list_args_set_multiselection(self.args, value as c_int);
@@ -543,6 +559,14 @@ impl<'a, T, E> TableViewBuilder<'a, T, E> {
         }
         self
     }
+    
+    pub fn onactivate_action(&mut self, action: &str) -> &mut Self {
+        let cstr = CString::new(action).unwrap();
+        unsafe {
+            ui_list_args_set_onactivate_action(self.args, cstr.as_ptr());
+        }
+        self
+    }
 
     pub fn onselection<F>(&mut self, f: F) -> &mut Self
     where F: FnMut(&mut event::Event<T>) + 'static {
@@ -555,6 +579,14 @@ impl<'a, T, E> TableViewBuilder<'a, T, E> {
         self
     }
 
+    pub fn onselection_action(&mut self, action: &str) -> &mut Self {
+        let cstr = CString::new(action).unwrap();
+        unsafe {
+            ui_list_args_set_onselection_action(self.args, cstr.as_ptr());
+        }
+        self
+    }
+    
     pub fn multiselection(&mut self, value: bool) -> &mut Self {
         unsafe {
             ui_list_args_set_multiselection(self.args, value as c_int);
@@ -981,8 +1013,10 @@ extern "C" {
     fn ui_list_args_set_style_class(args: *mut UiListArgs, classname: *const c_char);
     fn ui_list_args_set_onactivate(args: *mut UiListArgs, callback: UiCallback);
     fn ui_list_args_set_onactivatedata(args: *mut UiListArgs, data: *mut c_void);
+    fn ui_list_args_set_onactivate_action(args: *mut UiListArgs, action: *const c_char);
     fn ui_list_args_set_onselection(args: *mut UiListArgs, callback: UiCallback);
     fn ui_list_args_set_onselectiondata(args: *mut UiListArgs, data: *mut c_void);
+    fn ui_list_args_set_onselection_action(args: *mut UiListArgs, action: *const c_char);
     fn ui_list_args_set_varname(args: *mut UiListArgs, varname: *const c_char);
     fn ui_list_args_set_value(args: *mut UiListArgs, ivalue: *mut UiList);
     fn ui_list_args_set_model(args: *mut UiListArgs, model: *mut ffi::UiModel);
index b8718330a0dd467ec4c8878737cd716b62e29f04..937cbc2660546c5212856897b4a9d278f4b62aa0 100644 (file)
@@ -90,13 +90,14 @@ impl UiContext {
         ls
     }
 
-    pub unsafe fn add_action<T, F>(&mut self, name: &str, f: F)
+    pub unsafe fn add_action<T, F>(&self, name: &str, f: F)
     where F: FnMut(&mut T, &event::ActionEvent) + 'static {
         // if this is a document context, use the document pointer as target
         // otherwise it is a UiObject context, in that case we use the window_data as target
         let doc_ptr = ui_context_document(self.ptr) as *mut T;
         let target_ptr = if !doc_ptr.is_null() {
-            doc_ptr
+            let doc_storage: *mut *mut T = doc_ptr.cast();
+            *doc_storage
         } else {
             let obj_ptr = ui_context_obj(self.ptr);
             assert!(!obj_ptr.is_null());
@@ -166,14 +167,23 @@ impl<T: UiModel + UiActions> UiDoc<T> {
     }
 
     pub fn new(mut data: T) -> UiDoc<T> {
+        UiDoc::new2(data, |_,_| {})
+    }
+    
+    pub fn new2<F>(mut data: T, init: F) -> UiDoc<T>
+    where F: FnOnce(&mut T, &UiDoc<T>) {
         unsafe {
             let doc = ui_document_new(mem::size_of::<*mut T>());
             let ctx = UiContext::from_ptr(ui_document_context(doc));
-            data.init(&ctx);
             let data_ptr = ctx.reg_box(Box::new(data)); // returns *mut T
             let doc_storage: *mut *mut T = doc.cast();
             *doc_storage = data_ptr;
-            UiDoc::<T> { ctx: ctx, ptr: doc, _marker: PhantomData }
+            let doc_ref = &mut *data_ptr;
+            doc_ref.init(&ctx);
+            doc_ref.init_actions(&ctx);
+            let doc_handle = UiDoc::<T> { ctx: ctx, ptr: doc, _marker: PhantomData };
+            init(doc_ref, &doc_handle);
+            doc_handle
         }
     }
 
@@ -243,7 +253,7 @@ pub trait UiModel {
 }
 
 pub trait UiActions {
-    fn init_actions(&mut self, _ctx: &mut UiContext) {}
+    fn init_actions(&mut self, _ctx: &UiContext) {}
 }
 
 
@@ -482,7 +492,8 @@ impl<T: UiModel + UiActions> Drop for UiDocProxy<T> {
 
 
 pub struct UiText {
-    pub ptr: *mut ffi::UiText
+    pub ptr: *mut ffi::UiText,
+    value: Option<String>
 }
 
 pub struct UiString {
@@ -524,10 +535,20 @@ macro_rules! value_default_impl {
     };
 }
 
+macro_rules! value_default_impl2 {
+    ($type_name:ident) => {
+        impl Default for $type_name {
+            fn default() -> Self {
+                Self { ptr: std::ptr::null_mut(), value: None }
+            }
+        }
+    };
+}
+
 value_default_impl!(UiInteger);
 value_default_impl!(UiDouble);
 value_default_impl!(UiString);
-value_default_impl!(UiText);
+value_default_impl2!(UiText);
 
 impl<T> Default for UiList<T> {
     fn default() -> Self {
@@ -565,12 +586,19 @@ pub fn app_init(appname: &str) {
 }
 
 impl UiText {
+    pub fn from_ptr(ptr: *mut ffi::UiText) -> Self {
+        UiText { ptr, value: None }
+    }
+
     pub fn init(&mut self, ctx: &UiContext, name: Option<&str>) {
         let c_string = name.map(|n| CString::new(n).unwrap());
         let c_str = c_string.as_ref().map_or(std::ptr::null(), |s| s.as_ptr());
         unsafe {
             self.ptr = ui_text_new(ctx.ptr, c_str);
         }
+        if let Some(s) = self.value.take() {
+            self.set(&s);
+        }
     }
 
     pub fn get(&self) -> String {
@@ -583,9 +611,13 @@ impl UiText {
     }
 
     pub fn set(&mut self, value: &str) {
-        let cstr = CString::new(value).unwrap();
-        unsafe {
-            ui_text_set(self.ptr, cstr.as_ptr());
+        if self.ptr.is_null() {
+            self.value = Some(value.to_owned());
+        } else {
+            let cstr = CString::new(value).unwrap();
+            unsafe {
+                ui_text_set(self.ptr, cstr.as_ptr());
+            }
         }
     }
 
@@ -828,6 +860,20 @@ impl ListSelection {
         }
         sel
     }
+
+    pub fn selected_element<'a, T>(&self, data: &'a Vec<T>) -> Option<&'a T> {
+        unsafe {
+            let count = ui_list_selection_get_count(self.ptr);
+            if count == 1 {
+                let sel = ui_list_selection_get_rows(self.ptr);
+                let index = *sel;
+                if index >= 0 {
+                    return data.get(index as usize);
+                }
+            }
+        }
+        None
+    }
 }
 
 
index a2cabfdfb3b0fdbfe0c11ae13df8495808d6bbca..1c6a43708a2aae722e205816d1d2728c8710d56b 100644 (file)
@@ -115,7 +115,7 @@ where F: FnOnce(&mut toolkit::UiObject<T>, &mut T) {
 
     // init view model
     wdata.init(&obj.ctx);
-    wdata.init_actions(&mut obj.ctx);
+    wdata.init_actions(&obj.ctx);
     unsafe {
         ui_update_action_bindings(obj.ctx.ptr);
     }
index 54ce54c53c194799e288f5e45bd4254c84081384..602ee164b7c4f540c0ac267a535737e12dcd5369 100644 (file)
@@ -1887,6 +1887,10 @@ void ui_list_args_set_onactivatedata(UiListArgs *args, void *userdata) {
     args->onactivatedata = userdata;
 }
 
+void ui_list_args_set_onactivate_action(UiListArgs *args, const char *action) {
+    args->onactivate_action = strdup(action);
+}
+
 void ui_list_args_set_onselection(UiListArgs *args, ui_callback callback) {
     args->onselection = callback;
 }
@@ -1895,6 +1899,10 @@ void ui_list_args_set_onselectiondata(UiListArgs *args, void *userdata) {
     args->onselectiondata = userdata;
 }
 
+void ui_list_args_set_onselection_action(UiListArgs *args, const char *action) {
+    args->onselection_action = strdup(action);
+}
+
 void ui_list_args_set_ondragstart(UiListArgs *args, ui_callback callback) {
     args->ondragstart = callback;
 }
@@ -1903,6 +1911,10 @@ void ui_list_args_set_ondragstartdata(UiListArgs *args, void *userdata) {
     args->ondragstartdata = userdata;
 }
 
+void ui_list_args_set_ondragstart_action(UiListArgs *args, const char *action) {
+    args->ondragstart_action = strdup(action);
+}
+
 void ui_list_args_set_ondragcomplete(UiListArgs *args, ui_callback callback) {
     args->ondragcomplete = callback;
 }
@@ -1911,6 +1923,10 @@ void ui_list_args_set_ondragcompletedata(UiListArgs *args, void *userdata) {
     args->ondragcompletedata = userdata;
 }
 
+void ui_list_args_set_ondragcomplete_action(UiListArgs *args, const char *action) {
+    args->ondragcomplete_action = strdup(action);
+}
+
 void ui_list_args_set_ondrop(UiListArgs *args, ui_callback callback) {
     args->ondrop = callback;
 }
@@ -1919,6 +1935,10 @@ void ui_list_args_set_ondropdata(UiListArgs *args, void *userdata) {
     args->ondropdata = userdata;
 }
 
+void ui_list_args_set_ondrop_action(UiListArgs *args, const char *action) {
+    args->ondrop_action = strdup(action);
+}
+
 void ui_list_args_set_onsave(UiListArgs *args, ui_list_savefunc onsave) {
     args->onsave = onsave;
 }
@@ -1951,6 +1971,11 @@ void ui_list_args_free(UiListArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
     free((void*)args->varname);
+    free((void*)args->onactivate_action);
+    free((void*)args->onselection_action);
+    free((void*)args->ondragstart_action);
+    free((void*)args->ondragcomplete_action);
+    free((void*)args->ondrop_action);
     if(args->static_elements) {
         for(int i=0;i<args->static_nelm;i++) {
             free(args->static_elements[i]);
index 726dca17af6ad40897b9f0df51c94fb9284567a8..2639ac9aa9a13ff9714872983dc46f8dadff72e1 100644 (file)
@@ -450,14 +450,19 @@ UIEXPORT void ui_list_args_set_getstyle_func(UiListArgs *args, ui_getstylefunc g
 UIEXPORT void ui_list_args_set_getstyle_data(UiListArgs *args, void *userdata);
 UIEXPORT void ui_list_args_set_onactivate(UiListArgs *args, ui_callback callback);
 UIEXPORT void ui_list_args_set_onactivatedata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_onactivate_action(UiListArgs *args, const char *action);
 UIEXPORT void ui_list_args_set_onselection(UiListArgs *args, ui_callback callback);
 UIEXPORT void ui_list_args_set_onselectiondata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_onselection_action(UiListArgs *args, const char *action);
 UIEXPORT void ui_list_args_set_ondragstart(UiListArgs *args, ui_callback callback);
 UIEXPORT void ui_list_args_set_ondragstartdata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_ondragstart_action(UiListArgs *args, const char *action);
 UIEXPORT void ui_list_args_set_ondragcomplete(UiListArgs *args, ui_callback callback);
 UIEXPORT void ui_list_args_set_ondragcompletedata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_ondragcomplete_action(UiListArgs *args, const char *action);
 UIEXPORT void ui_list_args_set_ondrop(UiListArgs *args, ui_callback callback);
 UIEXPORT void ui_list_args_set_ondropdata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_ondrop_action(UiListArgs *args, const char *action);
 UIEXPORT void ui_list_args_set_onsave(UiListArgs *args, ui_list_savefunc onsave);
 UIEXPORT void ui_list_args_set_onsavedata(UiListArgs *args, void *userdata);
 UIEXPORT void ui_list_args_set_multiselection(UiListArgs *args, UiBool multiselection);
index b4c9402fab01685bc6773e51d21ac5a59ea13c29..0dc20f80a6d985bf7c3e526a768bc025f276ea95 100644 (file)
@@ -45,8 +45,8 @@ void* ui_document_new(size_t size) {
     
     UiDoc *document = cxCalloc(a, sizeof(UiDoc) + size, 1);
     document->ctx = ctx;
-    ctx->self_doc = document;
-    return &document->doc;
+    ctx->self_doc = &document->doc;
+    return ctx->self_doc;
 }
 
 void ui_document_destroy(void *doc) {
index f3a3895465a342f3360858ab4a9a30ec1ae5e4ae..3ae0b656733c08ed04d0488a34d55627d207a3af 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "../common/context.h"
 #include "../common/object.h"
+#include "../common/action.h"
 #include "container.h"
 
 #include <cx/array_list.h>
@@ -83,14 +84,19 @@ static UiListView* create_listview(UiObject *obj, UiListArgs *args) {
     tableview->multiselection = args->multiselection;
     tableview->onactivate = args->onactivate;
     tableview->onactivatedata = args->onactivatedata;
+    tableview->onactivate_action = args->onactivate_action ? strdup(args->onactivate_action) : NULL;
     tableview->onselection = args->onselection;
     tableview->onselectiondata = args->onselectiondata;
+    tableview->onselection_action = args->onselection_action ? strdup(args->onselection_action) : NULL;
     tableview->ondragstart = args->ondragstart;
     tableview->ondragstartdata = args->ondragstartdata;
+    tableview->ondragstart_action = args->ondragstart_action ? strdup(args->ondragstart_action) : NULL;
     tableview->ondragcomplete = args->ondragcomplete;
     tableview->ondragcompletedata = args->ondragcompletedata;
+    tableview->ondragcomplete_action = args->ondragcomplete_action ? strdup(args->ondragcomplete_action) : NULL;
     tableview->ondrop = args->ondrop;
     tableview->ondropdata = args->ondropdata;
+    tableview->ondrop_action = args->ondrop_action ? strdup(args->ondrop_action) : NULL;
     tableview->selection.count = 0;
     tableview->selection.rows = NULL;
     tableview->current_row = -1;
@@ -508,7 +514,7 @@ UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args) {
     }
     
     // event handling
-    if(args->onactivate) {
+    if(args->onactivate || args->onactivate_action) {
         // columnview and listview can use the same callback function, because
         // the first parameter (which is technically a different pointer type)
         // is ignored
@@ -806,7 +812,7 @@ static UiListSelection selectionmodel_get_selection(GtkSelectionModel *model) {
     return sel;
 }
 
-static void listview_event(ui_callback cb, void *cbdata, UiListView *view) {
+static void listview_event(ui_callback cb, void *cbdata, const char *action, UiListView *view) {
     UiEvent event;
     event.obj = view->obj;
     event.document = event.obj->ctx->document;
@@ -818,6 +824,10 @@ static void listview_event(ui_callback cb, void *cbdata, UiListView *view) {
     if(cb) {
         cb(&event, cbdata);
     }
+    
+    if(action) {
+        uic_action_callback(&event, action);
+    }
 }
 
 static void listview_update_selection(UiListView *view) {
@@ -868,14 +878,14 @@ void ui_columnview_activate(void *ignore, guint position, gpointer userdata) {
     if(view->selection.count == 0) {
         listview_update_selection(view);
     }
-    listview_event(view->onactivate, view->onactivatedata, view);
+    listview_event(view->onactivate, view->onactivatedata, view->onactivate_action, view);
 }
 
 void ui_listview_selection_changed(GtkSelectionModel* self, guint position, guint n_items, gpointer userdata) {
     UiListView *view = userdata;
     listview_update_selection(view);
     if(ui_selection_events_is_enabled()) {
-        listview_event(view->onselection, view->onselectiondata, view);
+        listview_event(view->onselection, view->onselectiondata, view->onselection_action, view);
     }
 }
 
@@ -2171,6 +2181,11 @@ void ui_table_dragdest_a(UIWIDGET tablewidget, int actions, char **targets, int
 */
 
 void ui_listview_destroy(GtkWidget *w, UiListView *v) {
+    free(v->onactivate_action);
+    free(v->onselection_action);
+    free(v->ondragstart_action);
+    free(v->ondragcomplete_action);
+    free(v->ondrop_action);
     //gtk_tree_view_set_model(GTK_TREE_VIEW(w), NULL);
     if(v->var) {
         ui_destroy_boundvar(v->obj->ctx, v->var);
index e7beb0e79e2861bbcef9e316b04513a3b6b7baec..d73ae560b96b7bc49ff02f2f5931b639f3c7740b 100644 (file)
@@ -81,14 +81,19 @@ struct UiListView {
 #endif
     ui_callback       onactivate;
     void              *onactivatedata;
+    char              *onactivate_action;
     ui_callback       onselection;
     void              *onselectiondata;
+    char              *onselection_action;
     ui_callback       ondragstart;
     void              *ondragstartdata;
+    char              *ondragstart_action;
     ui_callback       ondragcomplete;
     void              *ondragcompletedata;
+    char              *ondragcomplete_action;
     ui_callback       ondrop;
     void              *ondropdata;
+    char              *ondrop_action;
     ui_list_savefunc  onsave;
     void              *onsavedata;
     UiListSelection   selection;
index 3653034f9b0ca6f802bb562a87af95dec41a6869..5ce909d057c9dfb12ea6348cbf434b80787f68c7 100644 (file)
@@ -677,7 +677,7 @@ static void stateful_action_notify_group(UiMenuRadioGroup *group, UiInteger *i)
     
     CxIterator iter = cxListIterator(group->callbacks);
     cx_foreach(UiCallbackData *, cb, iter) {
-        event.intval = intval == iter.index;
+        event.intval = intval-1 == iter.index;
         if(cb->callback) {
             cb->callback(&event, cb->userdata);
         }
@@ -801,7 +801,7 @@ void ui_gmenu_add_radioitem(GMenu *parent, int index, UiMenuItemI *item, UiObjec
     cxListAdd(group->callbacks, &cb);
     
     
-    cxmutstr action_name = cx_asprintf("win.%s::%d", i->varname, (int)item_index);
+    cxmutstr action_name = cx_asprintf("win.%s::%d", i->varname, (int)item_index+1);
     g_menu_append(parent, i->label, action_name.ptr);
     free(action_name.ptr);
 }
index 5b74b575e34510629c0cfac9f87d9f16fe0d40d2..8c54114993490e388122048ac07e8d27f72911a9 100644 (file)
@@ -126,7 +126,9 @@ gboolean ui_window_close_request(UiObject *obj) {
 #endif
         return TRUE;
     } else {
+        // this cleans up any widget references from the context
         uic_context_prepare_close(obj->ctx);
+        ui_window_widget_destroy(obj);
         return FALSE;
     }
 }
index 06fe345396dfdc53e463982053c7c811585e60b7..35de753c60a999004adbab48655f055e0e1f09e9 100644 (file)
@@ -166,14 +166,19 @@ struct UiListArgs {
     void *getstyledata;
     ui_callback onactivate;
     void *onactivatedata;
+    const char *onactivate_action;
     ui_callback onselection;
     void *onselectiondata;
+    const char *onselection_action;
     ui_callback ondragstart;
     void *ondragstartdata;
+    const char *ondragstart_action;
     ui_callback ondragcomplete;
     void *ondragcompletedata;
+    const char *ondragcomplete_action;
     ui_callback ondrop;
     void *ondropdata;
+    const char *ondrop_action;
     UiBool multiselection;
     UiBool hide_header;
     UiMenuBuilder *contextmenu;
index 7f09f9007d48222b69a93be58ad24d3bb7f2a70b..61ddfff7663e70f0226dd6998384688c2d6262ae 100644 (file)
@@ -47,6 +47,7 @@ typedef void* UIMENU;   // NSMenu*
 
 #include <gtk/gtk.h>
 #define UIWIDGET GtkWidget*
+#define UIWINDOW void*
 
 #if UI_GTK2 || UI_GTK3
 #define UIMENU   GtkMenu*
@@ -83,6 +84,7 @@ typedef void* UIMENU;   // NSMenu*
 
 #include <Xm/XmAll.h> 
 #define UIWIDGET Widget
+#define UIWINDOW void*
 #define UIMENU   Widget
 
 
@@ -154,6 +156,13 @@ typedef struct UiWidget UiWidget;
 #define UIWINDOW UiWidget*
 #define UIMENU   void*
 
+#else
+
+#define UI_GENERIC
+#define UIWIDGET void*
+#define UIWINDOW void*
+#define UIMENU   void*
+
 #endif
 
 #ifndef TRUE
@@ -270,12 +279,10 @@ struct UiObject {
      */
     UIWIDGET    widget;
 
-#if defined(UI_COCOA) || defined(UI_WINUI)
     /*
      * native window object 
      */
     UIWINDOW    wobj;
-#endif
     
     /*
      * user window data
@@ -289,7 +296,6 @@ struct UiObject {
     
     /*
      * container list
-     * TODO: remove old UiContainer and rename UiContainerX to UiContainer
      */
     UiContainer *container_begin;
     UiContainer *container_end;
index 40503baa2fb88e61111eced55a096b768f5a4bc5..62c5c6341d6e9f65008a080826f9e7a0e12c4757 100644 (file)
@@ -52,6 +52,8 @@ typedef struct UiWidgetArgs {
     const char *style_class;
 } UiWidgetArgs;
 
+#ifndef UI_GENERIC
+
 #ifdef UI_GTK
 typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs *args, void *userdata);
 #elif defined(UI_QT)
@@ -71,6 +73,7 @@ UIEXPORT UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func cre
 
 #define ui_customwidget(obj, create_widget, userdata, ...) ui_customwidget_create(obj, create_widget, userdata, &(UiWidgetArgs) { __VA_ARGS__ })
 
+#endif
 
 UIEXPORT UIWIDGET ui_separator_create(UiObject *obj, UiWidgetArgs *args);