]> uap-core.de Git - note.git/commitdiff
add menus
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Fri, 24 Apr 2026 11:24:23 +0000 (13:24 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Fri, 24 Apr 2026 11:24:23 +0000 (13:24 +0200)
19 files changed:
application/src/main.rs
ui-rs/src/ui/ffi.rs
ui-rs/src/ui/list.rs
ui-rs/src/ui/menu.rs [new file with mode: 0644]
ui-rs/src/ui/mod.rs
ui-rs/src/ui/toolkit.rs
ui/common/args.c
ui/common/args.h
ui/common/menu.c
ui/common/menu.h
ui/gtk/menu.c
ui/gtk/menu.h
ui/motif/menu.c
ui/motif/menu.h
ui/qt/menu.cpp
ui/qt/menu.h
ui/qt/toolkit.cpp
ui/qt/toolkit.h
ui/ui/menu.h

index bb42ca5f1dcd7c334afcc4e5d1fbc24b625a7b92..e9f90ff83badda7c05adab163174ce219be76f4b 100644 (file)
@@ -68,6 +68,10 @@ fn create_window(app: &AppContext<TestData>) {
 
 impl Application<TestData> for App {
     fn on_startup(&mut self, app: &AppContext<TestData>) {
+        app.menu("File", |menu| {
+            menu.item("Open").create();
+        });
+
         create_window(app);
     }
 }
index 5a19f5bfb897cb8877f1b420e296a6950ad1de65..de01035bebea962490309300b00f47918f1cc2b8 100644 (file)
@@ -149,4 +149,19 @@ pub struct UiModel {
 #[repr(C)]
 pub struct UiSubList {
     _private: [u8; 0],
-}
\ No newline at end of file
+}
+
+#[repr(C)]
+pub struct UiMenuItemArgs {
+    _private: [u8; 0],
+}
+
+#[repr(C)]
+pub struct UiMenuToggleItemArgs {
+    _private: [u8; 0],
+}
+
+#[repr(C)]
+pub struct UiMenuItemListArgs {
+    _private: [u8; 0],
+}
index cc1648eaa4a425810f27a10c225badd95be66fba..996ad9016356e5fed07001d311ae9ae0656d381b 100644 (file)
@@ -731,9 +731,9 @@ impl<E> Drop for SubList<E> {
 
 /* ------------------------------- getvalue func wrapper -------------------------------- */
 
-type GetValueFunc = extern "C" fn(list: *const ffi::UiList, elm_ptr: *const c_void, row: i32, col: i32, wrapper: *const c_void, free: *mut bool) -> *mut c_void;
+pub type GetValueFunc = extern "C" fn(list: *const ffi::UiList, elm_ptr: *const c_void, row: i32, col: i32, wrapper: *const c_void, free: *mut bool) -> *mut c_void;
 
-struct GetValueWrapper<'a, T> {
+pub struct GetValueWrapper<'a, T> {
     callback: Box<dyn Fn(&T, i32, i32) -> ListValue<'a>>,
     is_table: bool
 }
diff --git a/ui-rs/src/ui/menu.rs b/ui-rs/src/ui/menu.rs
new file mode 100644 (file)
index 0000000..a92b6e1
--- /dev/null
@@ -0,0 +1,241 @@
+#![allow(dead_code)]
+
+use std::ffi::{c_char, c_int, c_void, CString};
+use std::marker::PhantomData;
+use crate::ui::{event, ffi, toolkit, AppContext, EventWrapper, GetValueFunc, ToggleButtonCreate, UiActions, UiContext, UiModel};
+use crate::ui::ffi::{UiCallback, UiMenuItemArgs, UiMenuItemListArgs, UiMenuToggleItemArgs, UiObject, UiToggleArgs};
+
+impl<T: UiModel + UiActions> AppContext<T> {
+    pub fn menu<F>(&self, title: &str, f: F)
+    where F: FnOnce(&mut Menu<T>) {
+        let cstr = CString::new(title).unwrap();
+        unsafe {
+            ui_menu_create(cstr.as_ptr());
+            let mut menu = Menu::<T> {
+                ctx: toolkit::ui_global_context(),
+                _marker: PhantomData
+            };
+            f(&mut menu);
+            ui_menu_end();
+        }
+    }
+}
+
+pub struct Menu<T: UiModel + UiActions> {
+    ctx: *mut ffi::UiContext,
+    _marker: PhantomData<T>,
+}
+
+impl<T: UiModel + UiActions> Menu<T> {
+    pub fn item(&self, label: &str) -> MenuItemBuilder<T> {
+        let args = unsafe {
+            let a = ui_menuitem_args_new();
+            let cstr = CString::new(label).unwrap();
+            ui_menuitem_args_set_label(a, cstr.as_ptr());
+            a
+        };
+        MenuItemBuilder::<T> {
+            args: args,
+            ctx: self.ctx,
+            _marker: PhantomData,
+        }
+    }
+
+    pub fn toggleitem(&self, label: &str) -> MenuToggleItemBuilder<T> {
+        let args = unsafe {
+            let a = ui_menutoggleitem_args_new();
+            let cstr = CString::new(label).unwrap();
+            ui_menutoggleitem_args_set_label(a, cstr.as_ptr());
+            a
+        };
+        MenuToggleItemBuilder::<T> {
+            args: args,
+            ctx: self.ctx,
+            create: ui_menu_toggleitem_create,
+            _marker: PhantomData,
+        }
+    }
+
+    pub fn radioitem(&self, label: &str) -> MenuToggleItemBuilder<T> {
+        let args = unsafe {
+            let a = ui_menutoggleitem_args_new();
+            let cstr = CString::new(label).unwrap();
+            ui_menutoggleitem_args_set_label(a, cstr.as_ptr());
+            a
+        };
+        MenuToggleItemBuilder::<T> {
+            args: args,
+            ctx: self.ctx,
+            create: ui_menu_radioitem_create,
+            _marker: PhantomData,
+        }
+    }
+
+    pub fn separator(&self) {
+        unsafe {
+            ui_menuseparator();
+        }
+    }
+
+    pub fn menu<F>(&self, title: &str, f: F)
+    where F: FnOnce(&mut Menu<T>) {
+        let cstr = CString::new(title).unwrap();
+        unsafe {
+            ui_menu_create(cstr.as_ptr());
+            let mut menu = Menu::<T> {
+                ctx: toolkit::ui_global_context(),
+                _marker: PhantomData
+            };
+            f(&mut menu);
+            ui_menu_end();
+        }
+    }
+}
+
+pub struct MenuItemBuilder<T: UiModel + UiActions> {
+    args: *mut UiMenuItemArgs,
+    ctx: *mut ffi::UiContext,
+    _marker: PhantomData<T>,
+}
+
+pub struct MenuToggleItemBuilder<T: UiModel + UiActions> {
+    args: *mut UiMenuToggleItemArgs,
+    ctx: *mut ffi::UiContext,
+    create: ToggleItemCreate,
+    _marker: PhantomData<T>,
+}
+
+pub type ToggleItemCreate = unsafe extern "C" fn(*const UiMenuToggleItemArgs);
+
+impl<T: UiModel + UiActions> MenuItemBuilder<T> {
+    pub fn create(&mut self) {
+        unsafe {
+            ui_menuitem_create(self.args);
+        }
+    }
+    pub fn icon(&mut self, icon: &str) -> &mut Self {
+        unsafe {
+            let cstr = CString::new(icon).unwrap();
+            ui_menuitem_args_set_icon(self.args, cstr.as_ptr());
+        }
+        self
+    }
+
+    pub fn action(&mut self, action: &str) -> &mut Self {
+        unsafe {
+            let cstr = CString::new(action).unwrap();
+            ui_menuitem_args_set_action(self.args, cstr.as_ptr());
+        }
+        self
+    }
+
+    pub fn onclick<F>(&mut self, f: F) -> &mut Self
+    where F: FnMut(&mut event::Event<T>) + 'static {
+        let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+        let mut ctx = UiContext { ptr: self.ctx };
+        let ptr = ctx.reg_box(wrapper);
+        unsafe {
+            ui_menuitem_args_set_onclick(self.args, Some(event::event_wrapper::<T>));
+            ui_menuitem_args_set_onclickdata(self.args, ptr as *mut c_void);
+        }
+        self
+    }
+}
+
+impl<T: UiModel + UiActions> Drop for MenuItemBuilder<T> {
+    fn drop(&mut self) {
+        unsafe {
+            ui_menuitem_args_free(self.args);
+        }
+    }
+}
+
+impl<T: UiModel + UiActions> MenuToggleItemBuilder<T> {
+    pub fn create(&mut self) {
+        unsafe {
+            (self.create)(self.args);
+        }
+    }
+    pub fn icon(&mut self, icon: &str) -> &mut Self {
+        unsafe {
+            let cstr = CString::new(icon).unwrap();
+            ui_menutoggleitem_args_set_icon(self.args, cstr.as_ptr());
+        }
+        self
+    }
+
+    pub fn varname(&mut self, varname: &str) -> &mut Self {
+        unsafe {
+            let cstr = CString::new(varname).unwrap();
+            ui_menutoggleitem_args_set_varname(self.args, cstr.as_ptr());
+        }
+        self
+    }
+
+    pub fn action(&mut self, action: &str) -> &mut Self {
+        unsafe {
+            let cstr = CString::new(action).unwrap();
+            ui_menutoggleitem_args_set_action(self.args, cstr.as_ptr());
+        }
+        self
+    }
+
+    pub fn onchange<F>(&mut self, f: F) -> &mut Self
+    where F: FnMut(&mut event::Event<T>) + 'static {
+        let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+        let mut ctx = UiContext { ptr: self.ctx };
+        let ptr = ctx.reg_box(wrapper);
+        unsafe {
+            ui_menutoggleitem_args_set_onchange(self.args, Some(event::event_wrapper::<T>));
+            ui_menutoggleitem_args_set_onchangedata(self.args, ptr as *mut c_void);
+        }
+        self
+    }
+}
+
+impl<T: UiModel + UiActions> Drop for MenuToggleItemBuilder<T> {
+    fn drop(&mut self) {
+        unsafe {
+            ui_menutoggleitem_args_free(self.args);
+        }
+    }
+}
+
+extern "C" {
+    fn ui_menu_create(label: *const c_char);
+    fn ui_menuitem_create(args: *const UiMenuItemArgs);
+    fn ui_menu_toggleitem_create(args: *const UiMenuToggleItemArgs);
+    fn ui_menu_radioitem_create(args: *const UiMenuToggleItemArgs);
+    fn ui_menuseparator();
+    fn ui_menu_itemlist_create(args: *const UiMenuItemListArgs);
+    fn ui_menu_toggleitemlist_create(args: *const UiMenuItemListArgs);
+    fn ui_menu_radioitemlist_create(args: *const UiMenuItemListArgs);
+    fn ui_menu_end();
+
+    fn ui_menuitem_args_new() -> *mut UiMenuItemArgs;
+    fn ui_menuitem_args_set_label(args: *mut UiMenuItemArgs, label: *const c_char);
+    fn ui_menuitem_args_set_icon(args: *mut UiMenuItemArgs, icon: *const c_char);
+    fn ui_menuitem_args_set_action(args: *mut UiMenuItemArgs, action: *const c_char);
+    fn ui_menuitem_args_set_onclick(args: *mut UiMenuItemArgs, onclick: UiCallback);
+    fn ui_menuitem_args_set_onclickdata(args: *mut UiMenuItemArgs, data: *mut c_void);
+    fn ui_menuitem_args_free(args: *mut UiMenuItemArgs);
+
+    fn ui_menutoggleitem_args_new() -> *mut UiMenuToggleItemArgs;
+    fn ui_menutoggleitem_args_set_label(args: *mut UiMenuToggleItemArgs, label: *const c_char);
+    fn ui_menutoggleitem_args_set_icon(args: *mut UiMenuToggleItemArgs, icon: *const c_char);
+    fn ui_menutoggleitem_args_set_varname(args: *mut UiMenuToggleItemArgs, varname: *const c_char);
+    fn ui_menutoggleitem_args_set_action(args: *mut UiMenuToggleItemArgs, action: *const c_char);
+    fn ui_menutoggleitem_args_set_onchange(args: *mut UiMenuToggleItemArgs, onclick: UiCallback);
+    fn ui_menutoggleitem_args_set_onchangedata(args: *mut UiMenuToggleItemArgs, data: *mut c_void);
+    fn ui_menutoggleitem_args_free(args: *mut UiMenuToggleItemArgs);
+
+    fn ui_menuitemlist_args_new() -> *mut UiMenuItemListArgs;
+    fn ui_menuitemlist_args_set_varname(args: *mut UiMenuItemListArgs, varname: *const c_char);
+    fn ui_menuitemlist_args_set_getvalue2(args: *mut UiMenuItemListArgs, f: GetValueFunc);
+    fn ui_menuitemlist_args_set_getvaluedata(args: *mut UiMenuItemListArgs, data: *mut c_void);
+
+    fn ui_menuitemlist_args_set_onselect(args: *mut UiMenuItemListArgs, onclick: UiCallback);
+    fn ui_menuitemlist_args_set_onselectdata(args: *mut UiMenuItemListArgs, data: *mut c_void);
+    fn ui_menuitemlist_args_set_addseparator(args: *mut UiMenuItemListArgs, value: c_int);
+    fn ui_menuitemlist_args_free(args: *mut UiMenuItemListArgs);
+}
index 5451bac9a8322c9d264fa7109dc48123fab8c96e..e608b3acea1dd2d6bcc2c5fe305c5babdbc45085 100644 (file)
@@ -8,6 +8,7 @@ mod widget;
 mod text;
 pub mod event;
 pub mod list;
+mod menu;
 
 pub use toolkit::*;
 pub use event::*;
index db1a072f5abb9cb90964cf984eabbe9b46c9dc62..31c4f25fd5014efa1bec3da00f5d831f7a74f787 100644 (file)
@@ -547,6 +547,7 @@ pub unsafe fn ui_list_get<'a, T>(list: *const ffi::UiList, index: usize) -> Opti
 
 extern "C" {
     fn ui_init(appname: *const c_char, argc: c_int, argv: *const *const c_char);
+    pub fn ui_global_context() -> *mut ffi::UiContext;
 
     fn ui_document_new(size: usize) -> *mut c_void;
     fn ui_document_ref(doc: *mut c_void);
index ac489bf942f5defd2d86a8019677de56779131b4..07cbb2b95a20898ed97c750137f834dd3788e152 100644 (file)
@@ -283,6 +283,14 @@ void ui_menuitemlist_args_set_getvalue(UiMenuItemListArgs *args, ui_getvaluefunc
     args->getvalue = func;
 }
 
+void ui_menuitemlist_args_set_getvalue2(UiMenuItemListArgs *args, ui_getvaluefunc2 func) {
+    args->getvalue2 = func;
+}
+
+void ui_menuitemlist_args_set_getvaluedata(UiMenuItemListArgs *args, void *data) {
+    args->getvaluedata = data;
+}
+
 void ui_menuitemlist_args_set_onselect(UiMenuItemListArgs *args, ui_callback callback) {
     args->onselect = callback;
 }
index 739affbdd4bbfd3cc4cd7e87d1929258b92ed8cf..f7c73a8b5dd86a0a2a4740e46768854d1e3eca09 100644 (file)
@@ -98,6 +98,8 @@ UIEXPORT void ui_menutoggleitem_args_free(UiMenuToggleItemArgs *args);
 UIEXPORT UiMenuItemListArgs* ui_menuitemlist_args_new(void);
 UIEXPORT void ui_menuitemlist_args_set_varname(UiMenuItemListArgs *args, const char *varname);
 UIEXPORT void ui_menuitemlist_args_set_getvalue(UiMenuItemListArgs *args, ui_getvaluefunc func);
+UIEXPORT void ui_menuitemlist_args_set_getvalue2(UiMenuItemListArgs *args, ui_getvaluefunc2 func);
+UIEXPORT void ui_menuitemlist_args_set_getvaluedata(UiMenuItemListArgs *args, void *data);
 UIEXPORT void ui_menuitemlist_args_set_onselect(UiMenuItemListArgs *args, ui_callback callback);
 UIEXPORT void ui_menuitemlist_args_set_onselectdata(UiMenuItemListArgs *args, void *data);
 UIEXPORT void ui_menuitemlist_args_set_addseparator(UiMenuItemListArgs *args, UiBool value);
index 84d75204318f7f9c59bfecf049a6f9b2a4a4313f..83eb2589e238701b32fbcdf5d1e2ac53e0ecbf6a 100644 (file)
@@ -44,6 +44,17 @@ static int menu_item_counter = 0;
 static void *tmp_eventdata;
 static int tmp_eventdata_type;
 
+
+static void* getvalue_wrapper(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) {
+    ui_getvaluefunc getvalue = (ui_getvaluefunc)userdata;
+    return getvalue(elm, col);
+}
+
+static void* str_getvalue(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) {
+    return elm;
+}
+
+
 void uic_set_tmp_eventdata(void *eventdata, int type) {
     tmp_eventdata = eventdata;
     tmp_eventdata_type = type;
@@ -208,7 +219,15 @@ void ui_menu_itemlist_create(UiMenuItemListArgs *args) {
     item->item.prev = NULL;
     item->item.next = NULL;
     item->item.type = UI_MENU_ITEM_LIST;
-    item->getvalue = args->getvalue;
+    if(args->getvalue2) {
+        item->getvalue = args->getvalue2;
+        item->getvaluedata = args->getvaluedata;
+    } else if(args->getvalue) {
+        item->getvalue = getvalue_wrapper;
+        item->getvaluedata = (void*)args->getvalue;
+    } else {
+        item->getvalue = str_getvalue;
+    }
     item->callback = args->onselect;
     item->userdata = args->onselectdata;
     item->varname = nl_strdup(args->varname);
@@ -223,6 +242,15 @@ void ui_menu_checkitemlist_create(UiMenuItemListArgs *args) {
     item->item.prev = NULL;
     item->item.next = NULL;
     item->item.type = UI_MENU_CHECKITEM_LIST;
+    if(args->getvalue2) {
+        item->getvalue = args->getvalue2;
+        item->getvaluedata = args->getvaluedata;
+    } else if(args->getvalue) {
+        item->getvalue = getvalue_wrapper;
+        item->getvaluedata = (void*)args->getvalue;
+    } else {
+        item->getvalue = str_getvalue;
+    }
     item->callback = args->onselect;
     item->userdata = args->onselectdata;
     item->varname = nl_strdup(args->varname);
@@ -236,6 +264,15 @@ void ui_menu_radioitemlist_create(UiMenuItemListArgs *args) {
     item->item.prev = NULL;
     item->item.next = NULL;
     item->item.type = UI_MENU_RADIOITEM_LIST;
+    if(args->getvalue2) {
+        item->getvalue = args->getvalue2;
+        item->getvaluedata = args->getvaluedata;
+    } else if(args->getvalue) {
+        item->getvalue = getvalue_wrapper;
+        item->getvaluedata = (void*)args->getvalue;
+    } else {
+        item->getvalue = str_getvalue;
+    }
     item->callback = args->onselect;
     item->userdata = args->onselectdata;
     item->varname = nl_strdup(args->varname);
index f2962abc1a07b17f5fe23b27f2a03101f9a6f95d..510e504f100f1fa0a6a5466fbc7e67aede2848d4 100644 (file)
@@ -107,12 +107,13 @@ struct UiMenuRadioItem {
 };
 
 struct UiMenuItemList {
-    UiMenuItemI     item;
-    ui_getvaluefunc getvalue;
-    ui_callback     callback;
-    void            *userdata;
-    char            *varname;
-    UiBool          addseparator;
+    UiMenuItemI      item;
+    ui_getvaluefunc2 getvalue;
+    void             *getvaluedata;
+    ui_callback      callback;
+    void             *userdata;
+    char             *varname;
+    UiBool           addseparator;
 };
 
 
index c81cd123696aaa64a30356756ff952bc598e5970..3653034f9b0ca6f802bb562a87af95dec41a6869 100644 (file)
@@ -277,6 +277,7 @@ void add_menuitem_list_widget(GtkWidget *p, int index, UiMenuItemI *item, UiObje
     ls->index = index;
     ls->oldcount = 0;
     ls->getvalue = il->getvalue;
+    ls->getvaluedata = il->getvaluedata;
     
     UiVar* var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST);
     //UiVar* var = uic_create_var(obj->ctx, il->varname, UI_VAR_LIST);
@@ -340,10 +341,13 @@ void ui_update_menuitem_list(UiActiveMenuItemList *list) {
         gtk_widget_show(widget);
     }
     
-    ui_getvaluefunc getvalue = list->getvalue;
+    ui_getvaluefunc2 getvalue = list->getvalue;
+    void *getvaluedata = list->getvaluedata;
     int i = 1;
+    int row = 0;
     while(elm) {
-        char *label = (char*) (getvalue ? getvalue(elm, 0) : elm);
+        UiBool freeResult = FALSE;
+        char *label = (char*) (getvalue ? getvalue(ls, elm, row, 0, getvaluedata, &freeResult) : elm);
         
         GtkWidget *widget = gtk_menu_item_new_with_label(label);
         gtk_menu_shell_insert(list->menu, widget, list->index + i);
@@ -372,6 +376,11 @@ void ui_update_menuitem_list(UiActiveMenuItemList *list) {
         
         elm = ui_list_next(ls);
         i++;
+        row++;
+        
+        if(freeResult) {
+            free(label);
+        }
     }
     
     list->oldcount = i;
@@ -825,6 +834,7 @@ void ui_gmenu_add_menuitem_list(GMenu *p, int index, UiMenuItemI *item, UiObject
     ls->index = index;
     ls->oldcount = 0;
     ls->getvalue = il->getvalue;
+    ls->getvaluedata = il->getvalue;
     
     GSimpleAction *action = g_simple_action_new(item->id, g_variant_type_new("i"));
     g_action_map_add_action(obj->ctx->action_map, G_ACTION(action));
@@ -943,11 +953,13 @@ void ui_update_gmenu_item_list(UiActiveGMenuItemList *list) {
     UiList *ls = list->var->value;
     
     // add list items
-    ui_getvaluefunc getvalue = list->getvalue;
+    ui_getvaluefunc2 getvalue = list->getvalue;
+    void *getvaluedata = list->getvaluedata;
     int i = 0;
     void* elm = ui_list_first(ls);
     while(elm) {
-        char *label = (char*) (getvalue ? getvalue(elm, 0) : elm);
+        UiBool freeResult = FALSE;
+        char *label = (char*) (getvalue ? getvalue(ls, elm, i, 0, getvaluedata, &freeResult) : elm);
         
         GMenuItem *item = g_menu_item_new(label, NULL);
         GVariant *v = g_variant_new("i", i);
@@ -957,6 +969,10 @@ void ui_update_gmenu_item_list(UiActiveGMenuItemList *list) {
         
         elm = ui_list_next(ls);
         i++;
+        
+        if(freeResult) {
+            free(label);
+        }
     }
     
     list->oldcount = i;
index 4cfa419d81e176d30f12b3612d1767043165e95a..d113f336f1b193a317aa27cef715803b583004c3 100644 (file)
@@ -56,7 +56,8 @@ struct UiActiveMenuItemList {
     int              index;
     int              oldcount;
     UiVar            *var;
-    ui_getvaluefunc  getvalue;
+    ui_getvaluefunc2 getvalue;
+    void             *getvaluedata;
     ui_callback      callback;
     void             *userdata;
 };
@@ -95,7 +96,8 @@ struct UiActiveGMenuItemList {
     int              index;
     int              oldcount;
     UiVar            *var;
-    ui_getvaluefunc  getvalue;
+    ui_getvaluefunc2 getvalue;
+    void             *getvaluedata;
     ui_callback      callback;
     void             *userdata;
 };
index 6d935a9ac5075c25504b8d2fdb8f182158cc2017..d3e62395a9895c7c8560249cd7cd64a9a158aa55 100644 (file)
@@ -302,11 +302,14 @@ void ui_update_menuitem_list(UiActiveMenuItemList *list) {
         i++;
     }
     
-    ui_getvaluefunc getvalue = list->getvalue;
+    int row = 0;
+    ui_getvaluefunc2 getvalue = list->getvalue;
+    void *getvaluedata = list->getvaluedata;
     int pos = list->index;
     while(elm) {
         n = 0;
-        char *label = (char*) (getvalue ? getvalue(elm, 0) : elm);
+        UiBool freeResult = FALSE;
+        char *label = (char*) (getvalue ? getvalue(ls, elm, row, 0, getvaluedata, &freeResult) : elm);
         if(label) {
             s = XmStringCreateLocalized(label);
             XtSetArg(args[n], XmNlabelString, s); n++;
@@ -341,7 +344,12 @@ void ui_update_menuitem_list(UiActiveMenuItemList *list) {
                     eventdata);
         }
         
+        if(freeResult) {
+            free(label);
+        }
+        
         elm = ui_list_next(ls);
+        row++;
         i++;
     }
     
index 4c40d797ff596e88f0dcdb6287a20b5deefcf9fb..9ab72b4e61eb13a4d473a57b7a1a9249ffd4f603 100644 (file)
@@ -44,7 +44,8 @@ struct UiActiveMenuItemList {
     int              index;
     int              oldcount;
     UiVar            *var;
-    ui_getvaluefunc  getvalue;
+    ui_getvaluefunc2 getvalue;
+    void             *getvaluedata;
     ui_callback      callback;
     void             *userdata;
     bool             addseparator;
index f391753ce0f49af04c4e6fa6d9d912fc1229b536..081bb524cf01b58c508d7b90e120b7bce868a986 100644 (file)
@@ -71,7 +71,7 @@ void add_menu_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj) {
     add_menu_items(menu, i, m, obj);
 }
 
-static UiAction* create_action(
+static UiQAction* create_action(
         UiObject *obj,
         const char *icon,
         const char *label,
@@ -80,7 +80,7 @@ static UiAction* create_action(
         int *states)
 {
     QString str = QString::fromUtf8(label);
-    UiAction *action = new UiAction(obj, str, callback, userdata);
+    UiQAction *action = new UiQAction(obj, str, callback, userdata);
     if(icon) {
         action->setIcon(QIcon::fromTheme(icon));
         action->setIconVisibleInMenu(true);
@@ -97,7 +97,7 @@ static UiAction* create_action(
 
 void add_menuitem_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj) {
     UiMenuItem *it = (UiMenuItem*)item;
-    UiAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->states);
+    UiQAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->states);
     parent->addAction(action);
     QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger()));
 }
@@ -109,7 +109,7 @@ void add_menuseparator_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject
 void add_checkitem_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj) {
     UiMenuCheckItem *it = (UiMenuCheckItem*)item;
     
-    UiAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->states);
+    UiQAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->states);
     parent->addAction(action);
     action->setCheckable(true);
     action->prepare_event = ui_checkableaction_prepare_event;
@@ -129,7 +129,7 @@ void add_checkitem_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj
 void add_radioitem_widget(QMenu *parent, int index, UiMenuItemI *item, UiObject *obj) {
     UiMenuRadioItem *it = (UiMenuRadioItem*)item;
     
-    UiAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->states);
+    UiQAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->states);
     parent->addAction(action);
     action->setCheckable(true);
     action->prepare_event = ui_actiongroup_prepare_event;
@@ -152,7 +152,7 @@ void add_radioitem_widget(QMenu *parent, int index, UiMenuItemI *item, UiObject
     action->var;
 }
 
-void ui_actiongroup_prepare_event(UiEvent *event, UiAction *action) {
+void ui_actiongroup_prepare_event(UiEvent *event, UiQAction *action) {
     if(action->var) {
         UiInteger *value = (UiInteger*)action->var->value;
         event->eventdata = value;
@@ -214,7 +214,7 @@ void ui_add_menus(UiObject *obj, QMainWindow *window) {
     }
 }
 
-void ui_checkableaction_prepare_event(UiEvent *event, UiAction *action) {
+void ui_checkableaction_prepare_event(UiEvent *event, UiQAction *action) {
     if(action->var) {
         event->eventdata = action->var->value;
         event->eventdatatype = UI_EVENT_DATA_INTEGER_VALUE;
@@ -223,13 +223,13 @@ void ui_checkableaction_prepare_event(UiEvent *event, UiAction *action) {
 }
 
 int64_t ui_checkableaction_get(UiInteger *value) {
-    UiAction *action= (UiAction*)value->obj;
+    UiQAction *action= (UiQAction*)value->obj;
     value->value = action->isChecked();
     return value->value;
 }
 
 void ui_checkableaction_set(UiInteger *value, int64_t i) {
-    UiAction *action = (UiAction*)value->obj;
+    UiQAction *action = (UiQAction*)value->obj;
     value->value = i;
     if(i != 0) {
         action->setChecked((bool)i);
index 9903ae07396149c37c388c91eae8f48826ef3bb0..21079c514a483795a47b1f78296b557ffce9a24a 100644 (file)
@@ -51,11 +51,11 @@ void add_radioitem_widget(QMenu *parent, int index, UiMenuItemI *item, UiObject
 void add_checkitemnv_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj);
 void add_menuitem_list_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj);
 
-void ui_checkableaction_prepare_event(UiEvent *event, UiAction *action);
+void ui_checkableaction_prepare_event(UiEvent *event, UiQAction *action);
 int64_t ui_checkableaction_get(UiInteger *value);
 void ui_checkableaction_set(UiInteger *value, int64_t i);
 
-void ui_actiongroup_prepare_event(UiEvent *event, UiAction *action);
+void ui_actiongroup_prepare_event(UiEvent *event, UiQAction *action);
 int64_t ui_actiongroup_get(UiInteger *value);
 void ui_actiongroup_set(UiInteger *value, int64_t i);
 
index cc5f656bad1cb4f683dc1bab749b1f02ac53b664..ed764740058575b1d193b6ebd9d1775e895c5518 100644 (file)
@@ -146,17 +146,17 @@ void UiEventWrapper::destroy() {
 
 /* --------------------- Implemtation UiAction --------------------- */
 
-UiAction::UiAction(UiObject *obj, QString &label, ui_callback f, void *userdata) : QAction(label, NULL) {
+UiQAction::UiQAction(UiObject *obj, QString &label, ui_callback f, void *userdata) : QAction(label, NULL) {
     this->obj = obj;
     this->callback = f;
     this->userdata = userdata;
 }
 
-UiAction::~UiAction() {
+UiQAction::~UiQAction() {
     // TODO: unbind var
 }
 
-void UiAction::trigger() {
+void UiQAction::trigger() {
     if(!callback) {
         return;
     }
@@ -178,7 +178,7 @@ void UiAction::trigger() {
 }
 
 // ui_enablefunc for UiAction
-void ui_action_enable(UiAction *action, int enable) {
+void ui_action_enable(UiQAction *action, int enable) {
     action->setEnabled((bool)enable);
 }
 
index 1db8df722231c78cc8912961b4bbd57813c07da4..6108596b240e0611160b645ff764bcf9db7541ec 100644 (file)
@@ -63,11 +63,11 @@ public slots:
     void destroy();
 };
 
-class UiAction;
+class UiQAction;
 
-typedef void (*ui_prepare_action_event_func)(UiEvent *event, UiAction *action);
+typedef void (*ui_prepare_action_event_func)(UiEvent *event, UiQAction *action);
 
-class UiAction : public QAction {
+class UiQAction : public QAction {
     Q_OBJECT
             
     UiObject *obj;
@@ -83,14 +83,14 @@ public:
     int customvalue1 = 0;
     int customvalue2 = 0;
     
-    UiAction(UiObject *obj, QString &label, ui_callback f, void *userdata);
-    ~UiAction();
+    UiQAction(UiObject *obj, QString &label, ui_callback f, void *userdata);
+    ~UiQAction();
     
 private slots:
     void trigger();
 };
 
-void ui_action_enable(UiAction *action, int enable);
+void ui_action_enable(UiQAction *action, int enable);
 
 #endif /* TOOLKIT_H */
 
index f659574a2c405cb7120d4f8ed28657c03152ead9..5ad8776419ddbc73c3c44794dd9faaa799efb264 100644 (file)
@@ -66,6 +66,8 @@ typedef struct UiMenuToggleItemArgs {
 typedef struct UiMenuItemListArgs {
        const char *varname;
        ui_getvaluefunc getvalue;
+        ui_getvaluefunc2 getvalue2;
+        void *getvaluedata;
        ui_callback onselect;
        void *onselectdata;
         const char *action;