From: Olaf Wintermann Date: Fri, 17 Apr 2026 12:55:40 +0000 (+0200) Subject: add action parameter to button/toggle builder X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;ds=sidebyside;p=note.git add action parameter to button/toggle builder --- diff --git a/ui-rs/src/ui/button.rs b/ui-rs/src/ui/button.rs index c574590..26dcf4f 100644 --- a/ui-rs/src/ui/button.rs +++ b/ui-rs/src/ui/button.rs @@ -269,6 +269,14 @@ impl<'a, T> ButtonBuilder<'a, T> { self } + pub fn action(&mut self, action: &str) -> &mut Self { + let cstr = CString::new(action).unwrap(); + unsafe { + ui_button_args_set_action(self.args, cstr.as_ptr()); + } + self + } + pub fn visibility_states(&mut self, states: &[i32]) -> &mut Self { unsafe { ui_button_args_set_visibility_states(self.args, states.as_ptr(), states.len() as c_int); @@ -453,6 +461,14 @@ impl<'a, T> ToggleBuilder<'a, T> { self } + pub fn action(&mut self, action: &str) -> &mut Self { + let cstr = CString::new(action).unwrap(); + unsafe { + ui_toggle_args_set_action(self.args, cstr.as_ptr()); + } + self + } + pub fn visibility_states(&mut self, states: &[i32]) -> &mut Self { unsafe { ui_toggle_args_set_visibility_states(self.args, states.as_ptr(), states.len() as c_int); @@ -499,6 +515,7 @@ extern "C" { fn ui_button_args_set_labeltype(args: *mut UiButtonArgs, ltype: c_int); fn ui_button_args_set_onclick(args: *mut UiButtonArgs, callback: UiCallback); fn ui_button_args_set_onclickdata(args: *mut UiButtonArgs, data: *mut c_void); + fn ui_button_args_set_action(args: *mut UiButtonArgs, action: *const c_char); fn ui_button_args_set_states(args: *mut UiButtonArgs, states: *const c_int, numstates: c_int); fn ui_button_args_set_visibility_states(args: *mut UiButtonArgs, states: *const c_int, numstates: c_int); fn ui_button_args_free(args: *mut UiButtonArgs); @@ -525,6 +542,7 @@ extern "C" { fn ui_toggle_args_set_labeltype(args: *mut UiToggleArgs, ltype: c_int); fn ui_toggle_args_set_onchange(args: *mut UiToggleArgs, callback: UiCallback); fn ui_toggle_args_set_onchangedata(args: *mut UiToggleArgs, data: *mut c_void); + fn ui_toggle_args_set_action(args: *mut UiToggleArgs, action: *const c_char); fn ui_toggle_args_set_varname(args: *mut UiToggleArgs, varname: *const c_char); fn ui_toggle_args_set_value(args: *mut UiToggleArgs, ivalue: *mut UiInteger); fn ui_toggle_args_set_enablestate(args: *mut UiToggleArgs, state: c_int); diff --git a/ui/common/action.c b/ui/common/action.c index 9c53b5d..19f5faa 100644 --- a/ui/common/action.c +++ b/ui/common/action.c @@ -49,6 +49,7 @@ void uic_add_action( action.userdata = userdata; action.accelerator = accelerator ? ui_strdup(ctx, accelerator) : NULL; action.accelerator_text = accelerator_text ? ui_strdup(ctx, accelerator_text) : NULL; + action.ctx = ctx; cxMapPut(ctx->actions, name, &action); cxMapRehash(ctx->actions); } @@ -57,8 +58,7 @@ void uic_bind_action( UiContext *ctx, const char *action, void *bind_obj, - ui_action_binding_set_enabled_func set_enabled, - ui_action_binding_set_accelerator_text_func set_accelerator_text) + ui_enablefunc set_enabled) { if(!action) { return; @@ -68,6 +68,76 @@ void uic_bind_action( binding.action = ui_strdup(ctx, action); binding.userdata = bind_obj; binding.set_enabled = set_enabled; - binding.set_accelerator_text = set_accelerator_text; cxListAdd(ctx->action_bindings, &binding); } + +UiAction* uic_resolve_action(UiContext *ctx, const char *action) { + UiAction *a = NULL; + if(ctx->actions) { + a = cxMapGet(ctx->actions, action); + } + // check if any sub-document defines this action + // sub-document actions have precedence, the most specific action will + // be returned + CxIterator i = cxListIterator(ctx->documents); + cx_foreach(void *, doc, i) { + UiContext *doc_ctx = ui_document_context(doc); + UiAction *sub_action = uic_resolve_action(doc_ctx, action); + if(sub_action) { + a = sub_action; + // if one sub-tree has an action, we don't care about other + // subtrees + break; + } + } + + if(!a && ctx->parent) { + // check parents + a = uic_resolve_action_from_parents(ctx, action); + } + + return a; +} + +UiAction* uic_resolve_action_from_parents(UiContext *ctx, const char *action) { + UiContext *parent = ctx->parent; + if(parent == NULL) { + return NULL; + } + if(parent->actions) { + UiAction *a = cxMapGet(parent->actions, action); + if(a) { + return a; + } + } + return uic_resolve_action_from_parents(parent, action); +} + + + +void ui_update_action_bindings(UiContext *ctx) { + CxIterator i = cxListIterator(ctx->action_bindings); + cx_foreach(UiActionBinding*, binding, i) { + UiAction *action = uic_resolve_action(ctx, binding->action); + if(binding->set_enabled) { + binding->set_enabled(binding->userdata, action != NULL); + } + } +} + +void uic_action_callback(UiEvent *event, const char *action_name) { + UiContext *ctx = ui_global_context(); + if(event->obj) { + ctx = event->obj->ctx; + } + + UiAction *action = uic_resolve_action(ctx, action_name); + if(action) { + // override event document: for actions we know that the event is + // for a specific document + event->document = action->ctx->self_doc; + if(action->callback) { + action->callback(event, action->userdata); + } + } +} diff --git a/ui/common/action.h b/ui/common/action.h index a363827..1364635 100644 --- a/ui/common/action.h +++ b/ui/common/action.h @@ -44,14 +44,12 @@ struct UiAction { char *accelerator_text; ui_callback callback; void *userdata; + UiContext *ctx; }; -typedef void (*ui_action_binding_set_enabled_func)(void *bind_obj, UiBool enabled); -typedef void (*ui_action_binding_set_accelerator_text_func)(void *bind_obj, const char *text); struct UiActionBinding { const char *action; - ui_action_binding_set_enabled_func set_enabled; - ui_action_binding_set_accelerator_text_func set_accelerator_text; + ui_enablefunc set_enabled; void *userdata; }; @@ -67,8 +65,13 @@ void uic_bind_action( UiContext *ctx, const char *action, void *bind_obj, - ui_action_binding_set_enabled_func set_enabled, - ui_action_binding_set_accelerator_text_func set_accelerator_text); + ui_enablefunc set_enabled); + +UiAction* uic_resolve_action(UiContext *ctx, const char *action); +UiAction* uic_resolve_action_from_parents(UiContext *ctx, const char *action); + +// action event wrapper +void uic_action_callback(UiEvent *event, const char *action_name); #ifdef __cplusplus } diff --git a/ui/common/args.c b/ui/common/args.c index b6c4f65..ac489bf 100644 --- a/ui/common/args.c +++ b/ui/common/args.c @@ -215,9 +215,14 @@ void ui_menuitem_args_set_onclickdata(UiMenuItemArgs *args, void *onclickdata) { args->onclickdata = onclickdata; } +void ui_menuitem_args_set_action(UiMenuItemArgs *args, const char *action) { + args->action = strdup(action); +} + void ui_menuitem_args_free(UiMenuItemArgs *args) { free((void*)args->label); free((void*)args->icon); + free((void*)args->action); free(args); } @@ -250,10 +255,15 @@ void ui_menutoggleitem_args_set_onchangedata(UiMenuToggleItemArgs *args, void *o args->onchangedata = onclickdata; } +void ui_menutoggleitem_args_set_action(UiMenuToggleItemArgs *args, const char *action) { + args->action = strdup(action); +} + void ui_menutoggleitem_args_free(UiMenuToggleItemArgs *args) { free((void*)args->label); free((void*)args->icon); free((void*)args->varname); + free((void*)args->action); free(args); } @@ -1440,6 +1450,10 @@ void ui_button_args_set_onclickdata(UiButtonArgs *args, void *onclickdata){ args->onclickdata = onclickdata; } +void ui_button_args_set_action(UiButtonArgs *args, const char *action) { + args->action = strdup(action); +} + void ui_button_args_set_states(UiButtonArgs *args, int *states, int numstates) { args->states = calloc(numstates+1, sizeof(int)); memcpy((void*)args->states, states, numstates * sizeof(int)); @@ -1458,6 +1472,7 @@ void ui_button_args_free(UiButtonArgs *args) { free((void*)args->label); free((void*)args->icon); free((void*)args->tooltip); + free((void*)args->action); free((void*)args->states); free((void*)args->visibility_states); free(args); @@ -1558,6 +1573,10 @@ void ui_toggle_args_set_onchangedata(UiToggleArgs *args, void *onchangedata){ args->onchangedata = onchangedata; } +void ui_toggle_args_set_action(UiToggleArgs *args, const char *action) { + args->action = strdup(action); +} + void ui_toggle_args_set_varname(UiToggleArgs *args, const char *varname) { args->varname = strdup(varname); } @@ -1589,6 +1608,7 @@ void ui_toggle_args_free(UiToggleArgs *args) { free((void*)args->icon); free((void*)args->tooltip); free((void*)args->varname); + free((void*)args->action); free((void*)args->states); free((void*)args->visibility_states); free(args); @@ -1688,6 +1708,10 @@ void ui_linkbutton_args_set_onclickdata(UiLinkButtonArgs *args, void *userdata) args->onclickdata = userdata; } +void ui_linkbutton_args_set_action(UiLinkButtonArgs *args, const char *action) { + args->action = strdup(action); +} + void ui_linkbutton_args_set_nofollow(UiLinkButtonArgs *args, UiBool value) { args->nofollow = value; } @@ -1721,6 +1745,7 @@ void ui_linkbutton_args_free(UiLinkButtonArgs *args) { free((void*)args->style_class); free((void*)args->label); free((void*)args->uri); + free((void*)args->action); free((void*)args->varname); free((void*)args->states); free(args); @@ -2286,6 +2311,14 @@ void ui_textfield_args_set_onactivatedata(UiTextFieldArgs *args, void *onactivat args->onactivatedata = onactivatedata; } +void ui_textfield_args_set_onactivate_action(UiTextFieldArgs *args, const char *action) { + args->onactivate_action = strdup(action); +} + +void ui_textfield_args_set_onchange_action(UiTextFieldArgs *args, const char *action) { + args->onchange_action = action; +} + void ui_textfield_args_set_varname(UiTextFieldArgs *args, const char *varname) { args->varname = strdup(varname); } @@ -2310,6 +2343,8 @@ void ui_textfield_args_free(UiTextFieldArgs *args) { free((void*)args->name); free((void*)args->style_class); free((void*)args->varname); + free((void*)args->onactivate_action); + free((void*)args->onchange_action); free((void*)args->states); free((void*)args->visibility_states); free(args); diff --git a/ui/common/args.h b/ui/common/args.h index 5bd93bb..739affb 100644 --- a/ui/common/args.h +++ b/ui/common/args.h @@ -83,6 +83,7 @@ UIEXPORT void ui_menuitem_args_set_label(UiMenuItemArgs *args, const char *label UIEXPORT void ui_menuitem_args_set_icon(UiMenuItemArgs *args, const char *icon); UIEXPORT void ui_menuitem_args_set_onclick(UiMenuItemArgs *args, ui_callback callback); UIEXPORT void ui_menuitem_args_set_onclickdata(UiMenuItemArgs *args, void *onclickdata); +UIEXPORT void ui_menuitem_args_set_action(UiMenuItemArgs *args, const char *action); UIEXPORT void ui_menuitem_args_free(UiMenuItemArgs *args); UIEXPORT UiMenuToggleItemArgs* ui_menutoggleitem_args_new(void); @@ -91,6 +92,7 @@ UIEXPORT void ui_menutoggleitem_args_set_icon(UiMenuToggleItemArgs *args, const UIEXPORT void ui_menutoggleitem_args_set_varname(UiMenuToggleItemArgs *args, const char *varname); UIEXPORT void ui_menutoggleitem_args_set_onchange(UiMenuToggleItemArgs *args, ui_callback callback); UIEXPORT void ui_menutoggleitem_args_set_onchangedata(UiMenuToggleItemArgs *args, void *onchangedata); +UIEXPORT void ui_menutoggleitem_args_set_action(UiMenuToggleItemArgs *args, const char *action); UIEXPORT void ui_menutoggleitem_args_free(UiMenuToggleItemArgs *args); UIEXPORT UiMenuItemListArgs* ui_menuitemlist_args_new(void); @@ -353,6 +355,7 @@ UIEXPORT void ui_button_args_set_tooltip(UiButtonArgs *args, const char *tooltip UIEXPORT void ui_button_args_set_labeltype(UiButtonArgs *args, int labeltype); UIEXPORT void ui_button_args_set_onclick(UiButtonArgs *args, ui_callback callback); UIEXPORT void ui_button_args_set_onclickdata(UiButtonArgs *args, void *onclickdata); +UIEXPORT void ui_button_args_set_action(UiButtonArgs *args, const char *action); UIEXPORT void ui_button_args_set_states(UiButtonArgs *args, int *states, int numstates); UIEXPORT void ui_button_args_set_visibility_states(UiButtonArgs *args, int *states, int numstates); UIEXPORT void ui_button_args_free(UiButtonArgs *args); @@ -379,6 +382,7 @@ UIEXPORT void ui_toggle_args_set_tooltip(UiToggleArgs *args, const char *tooltip UIEXPORT void ui_toggle_args_set_labeltype(UiToggleArgs *args, int labeltype); UIEXPORT void ui_toggle_args_set_onchange(UiToggleArgs *args, ui_callback callback); UIEXPORT void ui_toggle_args_set_onchangedata(UiToggleArgs *args, void *onchangedata); +UIEXPORT void ui_toggle_args_set_action(UiToggleArgs *args, const char *action); UIEXPORT void ui_toggle_args_set_varname(UiToggleArgs *args, const char *varname); UIEXPORT void ui_toggle_args_set_value(UiToggleArgs *args, UiInteger *value); UIEXPORT void ui_toggle_args_set_enablestate(UiToggleArgs *args, int state); @@ -408,6 +412,7 @@ UIEXPORT void ui_linkbutton_args_set_label(UiLinkButtonArgs *args, const char *l UIEXPORT void ui_linkbutton_args_set_uri(UiLinkButtonArgs *args, const char *uri); UIEXPORT void ui_linkbutton_args_set_onclick(UiLinkButtonArgs *args, ui_callback callback); UIEXPORT void ui_linkbutton_args_set_onclickdata(UiLinkButtonArgs *args, void *userdata); +UIEXPORT void ui_linkbutton_args_set_action(UiLinkButtonArgs *args, const char *action); UIEXPORT void ui_linkbutton_args_set_nofollow(UiLinkButtonArgs *args, UiBool value); UIEXPORT void ui_linkbutton_args_set_type(UiLinkButtonArgs *args, UiLinkType type); UIEXPORT void ui_linkbutton_args_set_states(UiLinkButtonArgs *args, int *states, int numstates); @@ -506,6 +511,7 @@ UIEXPORT void ui_textarea_args_set_name(UiTextAreaArgs *args, const char *name); UIEXPORT void ui_textarea_args_set_style_class(UiTextAreaArgs *args, const char *classname); UIEXPORT void ui_textarea_args_set_onchange(UiTextAreaArgs *args, ui_callback callback); UIEXPORT void ui_textarea_args_set_onchangedata(UiTextAreaArgs *args, void *onchangedata); +UIEXPORT void ui_textarea_args_set_action(UiTextAreaArgs *args, const char *action); UIEXPORT void ui_textarea_args_set_varname(UiTextAreaArgs *args, const char *varname); UIEXPORT void ui_textarea_args_set_value(UiTextAreaArgs *args, UiText *value); UIEXPORT void ui_textarea_args_set_states(UiTextAreaArgs *args, int *states, int numstates); @@ -532,6 +538,8 @@ UIEXPORT void ui_textfield_args_set_onchange(UiTextFieldArgs *args, ui_callback UIEXPORT void ui_textfield_args_set_onchangedata(UiTextFieldArgs *args, void *onchangedata); UIEXPORT void ui_textfield_args_set_onactivate(UiTextFieldArgs *args, ui_callback callback); UIEXPORT void ui_textfield_args_set_onactivatedata(UiTextFieldArgs *args, void *onactivatedata); +UIEXPORT void ui_textfield_args_set_onactivate_action(UiTextFieldArgs *args, const char *action); +UIEXPORT void ui_textfield_args_set_onchange_action(UiTextFieldArgs *args, const char *action); UIEXPORT void ui_textfield_args_set_varname(UiTextFieldArgs *args, const char *varname); UIEXPORT void ui_textfield_args_set_value(UiTextFieldArgs *args, UiString *value); UIEXPORT void ui_textfield_args_set_states(UiTextFieldArgs *args, int *states, int numstates); diff --git a/ui/common/context.c b/ui/common/context.c index 6936de9..f729978 100644 --- a/ui/common/context.c +++ b/ui/common/context.c @@ -152,6 +152,8 @@ void uic_context_attach_document(UiContext *ctx, void *document) { var_ctx = var_ctx->parent; } + + ui_update_action_bindings(ctx); } static void uic_context_unbind_vars(UiContext *ctx) { @@ -194,6 +196,8 @@ void uic_context_detach_document(UiContext *ctx, void *document) { UiContext *docctx = ui_document_context(document); uic_context_unbind_vars(docctx); // unbind all doc/subdoc vars from the parent docctx->parent = NULL; + + ui_update_action_bindings(ctx); } void uic_context_detach_all(UiContext *ctx) { @@ -211,6 +215,7 @@ void uic_context_detach_all(UiContext *ctx) { } cxListFree(ls); + ui_update_action_bindings(ctx); } static UiVar* ctx_getvar(UiContext *ctx, CxHashKey key) { diff --git a/ui/common/context.h b/ui/common/context.h index 50f5b44..c2bba8b 100644 --- a/ui/common/context.h +++ b/ui/common/context.h @@ -66,6 +66,9 @@ struct UiContext { const CxAllocator *allocator; CxList *destroy_handler; + // document pointer, if this is a document context + void *self_doc; + void *document; CxList *documents; diff --git a/ui/common/document.c b/ui/common/document.c index 6c6da19..b05d484 100644 --- a/ui/common/document.c +++ b/ui/common/document.c @@ -45,6 +45,7 @@ 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; } diff --git a/ui/common/menu.c b/ui/common/menu.c index b0a5d2e..84d7520 100644 --- a/ui/common/menu.c +++ b/ui/common/menu.c @@ -148,6 +148,7 @@ void ui_menuitem_create(UiMenuItemArgs *args) { item->item.next = NULL; item->item.type = UI_MENU_ITEM; + item->action = nl_strdup(args->action); item->label = nl_strdup(args->label); item->icon = nl_strdup(args->icon); item->userdata = args->onclickdata; diff --git a/ui/common/menu.h b/ui/common/menu.h index 9aea578..f2962ab 100644 --- a/ui/common/menu.h +++ b/ui/common/menu.h @@ -76,6 +76,7 @@ struct UiMenu { struct UiMenuItem { UiMenuItemI item; ui_callback callback; + char *action; char *label; char *icon; void *userdata; diff --git a/ui/gtk/action.c b/ui/gtk/action.c new file mode 100644 index 0000000..80f0a42 --- /dev/null +++ b/ui/gtk/action.c @@ -0,0 +1,53 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "action.h" + +#include +#include + + + +/* ------------------------------ public API ------------------------------ */ + +void ui_add_action(UiContext *ctx, const char *name, ui_callback callback, void *userdata) { + uic_add_action(ctx, name, callback, userdata, NULL, NULL); +} + +void ui_add_action_with_accelerator( + UiContext *ctx, + const char *name, + ui_callback callback, + void *userdata, + const char *accelerator, + const char *accelerator_text) +{ + uic_add_action(ctx, name, callback, userdata, accelerator, accelerator_text); + + // TODO: accelerator +} diff --git a/ui/gtk/action.h b/ui/gtk/action.h new file mode 100644 index 0000000..d13d3de --- /dev/null +++ b/ui/gtk/action.h @@ -0,0 +1,47 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2026 Olaf Wintermann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef ACTION_H +#define ACTION_H + +#include "../ui/toolkit.h" +#include "../common/action.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + + +#ifdef __cplusplus +} +#endif + +#endif /* ACTION_H */ + diff --git a/ui/gtk/menu.c b/ui/gtk/menu.c index 8bfbbbf..c81cd12 100644 --- a/ui/gtk/menu.c +++ b/ui/gtk/menu.c @@ -37,6 +37,7 @@ #include "../common/context.h" #include "../common/menu.h" #include "../common/types.h" +#include "../common/action.h" #include "../ui/properties.h" #include "../ui/window.h" #include "container.h" @@ -590,7 +591,15 @@ void ui_gmenu_add_menuitem(GMenu *parent, int index, UiMenuItemI *item, UiObject cxListFree(groups); } - if(i->callback != NULL) { + if(i->action) { + uic_bind_action(obj->ctx, i->action, action, (ui_enablefunc)action_enable); + UiAction *ui_action = uic_resolve_action(obj->ctx, i->action); + if(!ui_action) { + action_enable(action, FALSE); + } + } + + if(i->callback != NULL || i->action) { UiEventData *event = malloc(sizeof(UiEventData)); event->obj = obj; event->userdata = i->userdata; @@ -598,6 +607,7 @@ void ui_gmenu_add_menuitem(GMenu *parent, int index, UiMenuItemI *item, UiObject event->value = 0; event->customdata = NULL; event->customint = 0; + event->action = i->action ? strdup(i->action) : NULL; g_signal_connect( action, @@ -607,13 +617,13 @@ void ui_gmenu_add_menuitem(GMenu *parent, int index, UiMenuItemI *item, UiObject g_signal_connect( obj->widget, "destroy", - G_CALLBACK(ui_destroy_userdata), + G_CALLBACK(ui_destroy_eventdata), event); } char action_name[32]; snprintf(action_name, 32, "win.%s", item->id); - + g_menu_append(parent, i->label, action_name); } @@ -888,7 +898,12 @@ void ui_activate_event_wrapper(GSimpleAction* self, GVariant* parameter, UiEvent evt.eventdatatype = uic_get_tmp_eventdata_type(); } evt.intval = intval; - event->callback(&evt, event->userdata); + if(event->callback) { + event->callback(&evt, event->userdata); + } + if(event->action) { + uic_action_callback(&evt, event->action); + } uic_set_tmp_eventdata(NULL, 0); } diff --git a/ui/gtk/objs.mk b/ui/gtk/objs.mk index abad5a0..1c79646 100644 --- a/ui/gtk/objs.mk +++ b/ui/gtk/objs.mk @@ -48,6 +48,7 @@ GTKOBJ += dnd.o GTKOBJ += headerbar.o GTKOBJ += webview.o GTKOBJ += widget.o +GTKOBJ += action.o TOOLKITOBJS += $(GTKOBJ:%=$(GTK_OBJPRE)%) TOOLKITSOURCE += $(GTKOBJ:%.o=gtk/%.c) diff --git a/ui/gtk/toolkit.c b/ui/gtk/toolkit.c index e310091..0ad0fe8 100644 --- a/ui/gtk/toolkit.c +++ b/ui/gtk/toolkit.c @@ -313,6 +313,11 @@ void ui_destroy_userdata(GtkWidget *object, void *userdata) { free(userdata); } +void ui_destroy_eventdata(GtkWidget *object, UiEventData *data) { + free(data->action); + free(data); +} + void ui_destroy_vardata(GtkWidget *unused, UiVarEventData *data) { if(data->var) { ui_destroy_boundvar(data->obj->ctx, data->var); diff --git a/ui/gtk/toolkit.h b/ui/gtk/toolkit.h index e16f361..25a48f5 100644 --- a/ui/gtk/toolkit.h +++ b/ui/gtk/toolkit.h @@ -149,6 +149,7 @@ typedef struct UiEventData { int value; int customint; void *customdata; + char *action; } UiEventData; typedef struct UiEventDataExt { @@ -200,6 +201,7 @@ void ui_set_widget_visibility_states(UiContext *ctx, GtkWidget *widget, const in void ui_set_widget_nvisibility_states(UiContext *ctx, GtkWidget *widget, const int *states, size_t ngroups); void ui_destroy_userdata(GtkWidget *object, void *userdata); +void ui_destroy_eventdata(GtkWidget *object, UiEventData *data); void ui_destroy_vardata(GtkWidget *unused, UiVarEventData *data); void ui_destroy_widget_var(GtkWidget *object, UiVar *var); void ui_destroy_boundvar(UiContext *ctx, UiVar *var); diff --git a/ui/ui/button.h b/ui/ui/button.h index c7db396..b9c56c4 100644 --- a/ui/ui/button.h +++ b/ui/ui/button.h @@ -63,7 +63,8 @@ typedef struct UiButtonArgs { const char *tooltip; UiLabelType labeltype; ui_callback onclick; - void *onclickdata; + void *onclickdata; + const char *action; const int *states; const int *visibility_states; @@ -86,18 +87,19 @@ typedef struct UiToggleArgs { const char *name; const char *style_class; - const char *label; - const char *icon; - const char *tooltip; + const char *label; + const char *icon; + const char *tooltip; UiLabelType labeltype; - UiInteger *value; - const char *varname; + UiInteger *value; + const char *varname; ui_callback onchange; - void *onchangedata; - int enable_state; + void *onchangedata; + const char *action; + int enable_state; - const int *states; - const int *visibility_states; + const int *states; + const int *visibility_states; } UiToggleArgs; typedef struct UiLinkButtonArgs { @@ -123,6 +125,7 @@ typedef struct UiLinkButtonArgs { const char *varname; ui_callback onclick; void *onclickdata; + const char *action; UiBool nofollow; UiLinkType type; diff --git a/ui/ui/menu.h b/ui/ui/menu.h index bd5b96b..f659574 100644 --- a/ui/ui/menu.h +++ b/ui/ui/menu.h @@ -39,7 +39,7 @@ extern "C" { typedef struct UiMenuItemArgs { const char *label; const char *icon; - + ui_callback onclick; void *onclickdata; const char *action; diff --git a/ui/ui/text.h b/ui/ui/text.h index ebea880..15f7ced 100644 --- a/ui/ui/text.h +++ b/ui/ui/text.h @@ -58,6 +58,7 @@ typedef struct UiTextAreaArgs { const char *varname; ui_callback onchange; void *onchangedata; + const char *action; const int *states; const int *visibility_states; @@ -87,6 +88,8 @@ typedef struct UiTextFieldArgs { void *onchangedata; ui_callback onactivate; void *onactivatedata; + const char *onactivate_action; + const char *onchange_action; const int *states; const int *visibility_states; @@ -129,6 +132,7 @@ typedef struct UiPathTextFieldArgs { ui_callback onactivate; void *onactivatedata; + const char *action; ui_callback ondragstart; void *ondragstartdata; diff --git a/ui/ui/toolkit.h b/ui/ui/toolkit.h index 76a4e56..cdb75b7 100644 --- a/ui/ui/toolkit.h +++ b/ui/ui/toolkit.h @@ -589,6 +589,16 @@ UIEXPORT void ui_widget_set_states(UiContext *ctx, UIWIDGET widget, ui_enablefun UIEXPORT void ui_widget_set_states2(UiContext *ctx, UIWIDGET widget, ui_enablefunc enable, const int *states, int nstates); UIEXPORT void ui_widget_set_visibility_states(UiContext *ctx, UIWIDGET widget, const int *states, int nstates); +UIEXPORT void ui_add_action(UiContext *ctx, const char *name, ui_callback callback, void *userdata); +UIEXPORT void ui_add_action_with_accelerator( + UiContext *ctx, + const char *name, + ui_callback callback, + void *userdata, + const char *accelerator, + const char *accelerator_text); +UIEXPORT void ui_update_action_bindings(UiContext *ctx); + UIEXPORT void ui_set_state(UiContext *ctx, int state); UIEXPORT void ui_unset_state(UiContext *ctx, int state); UIEXPORT int* ui_active_states(UiContext *ctx, int *nstates);