ui/common/action.c

changeset 1092
0accf125a65f
parent 1066
afe02792303d
--- a/ui/common/action.c	Thu Apr 16 17:41:35 2026 +0200
+++ b/ui/common/action.c	Fri Apr 17 13:21:11 2026 +0200
@@ -49,6 +49,7 @@
     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 @@
         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 @@
     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);
+        }
+    }
+}

mercurial