]> uap-core.de Git - note.git/commitdiff
note_search scrolls to the found text main
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 1 Feb 2026 17:36:32 +0000 (18:36 +0100)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 1 Feb 2026 17:36:32 +0000 (18:36 +0100)
13 files changed:
application/note.c
ui/common/action.c [new file with mode: 0644]
ui/common/action.h [new file with mode: 0644]
ui/common/context.c
ui/common/context.h
ui/common/objs.mk
ui/common/types.c
ui/gtk/text.c
ui/gtk/text.h
ui/ui/menu.h
ui/ui/text.h
ui/ui/toolbar.h
ui/ui/toolkit.h

index b64fe855abb28bd1b83af88cc731e6388d4efa14..e23d53f4954385b5362bdbff82fc7463910e2828 100644 (file)
@@ -408,6 +408,7 @@ static void note_search(NoteModel *note, bool backwards) {
     if(text_search(text, searchstr, pos, backwards, regex, cs, &begin, &end)) {
         note->text->setposition(note->text, end);
         note->text->setselection(note->text, begin, end);
+        note->text->showposition(note->text, begin);
     }
 }
 
diff --git a/ui/common/action.c b/ui/common/action.c
new file mode 100644 (file)
index 0000000..9c53b5d
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * 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 "context.h"
+
+#include <cx/string.h>
+
+void uic_add_action(
+        UiContext *ctx,
+        const char *name,
+        ui_callback callback,
+        void *userdata,
+        const char *accelerator,
+        const char *accelerator_text)
+{
+    if(!name) {
+        return;
+    }
+    
+    UiAction action;
+    action.name = ui_strdup(ctx, name);
+    action.callback = callback;
+    action.userdata = userdata;
+    action.accelerator = accelerator ? ui_strdup(ctx, accelerator) : NULL;
+    action.accelerator_text = accelerator_text ? ui_strdup(ctx, accelerator_text) : NULL;
+    cxMapPut(ctx->actions, name, &action);
+    cxMapRehash(ctx->actions);
+}
+
+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)
+{
+    if(!action) {
+        return;
+    }
+    
+    UiActionBinding binding;
+    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);
+}
diff --git a/ui/common/action.h b/ui/common/action.h
new file mode 100644 (file)
index 0000000..a363827
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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 UIC_ACTION_H
+#define UIC_ACTION_H
+
+#include "../ui/toolkit.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct UiAction        UiAction;
+typedef struct UiActionBinding UiActionBinding;
+
+struct UiAction {
+    char *name;
+    char *accelerator;
+    char *accelerator_text;
+    ui_callback callback;
+    void *userdata;
+};
+
+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;
+    void *userdata;
+};
+
+void uic_add_action(
+        UiContext *ctx,
+        const char *name,
+        ui_callback callback,
+        void *userdata,
+        const char *accelerator,
+        const char *accelerator_text);
+
+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);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UIC_ACTION_H */
+
index 4909d9360b53a589fa22034ed54e4b27ac675aad..3e7abfc0cf47e10d78bd2b57065f5f42c3b1f508 100644 (file)
@@ -68,6 +68,9 @@ UiContext* uic_context(UiObject *toplevel, CxMempool *mp) {
     ctx->states = cxArrayListCreate(mp->allocator, sizeof(int), 32);
     cxSetCompareFunc(ctx->states, cx_cmp_int);
     
+    ctx->actions = cxHashMapCreate(ctx->allocator, sizeof(UiAction), 8);
+    ctx->action_bindings = cxArrayListCreate(ctx->allocator, sizeof(UiActionBinding), 0);
+    
     ctx->attach_document = uic_context_attach_document;
     ctx->detach_document2 = uic_context_detach_document;
     
index 9a73efabe0f489fee5669d3ba46e1f29a5eafa1c..de804818de35418ee6118d0172d5bdceafe05cfa 100644 (file)
@@ -36,6 +36,8 @@
 #include <cx/list.h>
 #include <cx/linked_list.h>
 
+#include "action.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -72,6 +74,9 @@ struct UiContext {
     CxList        *states; // int list
     CxList        *state_widgets; // UiGroupWidget list
     
+    CxMap         *actions; // key: action name (string), value: UiAction
+    CxList        *action_bindings; // UiActionBinding list
+    
     void (*attach_document)(UiContext *ctx, void *document);
     void (*detach_document2)(UiContext *ctx, void *document); 
     
index e69125caa6865580629a16a70b5cf06e5ce2eea5..2ce73a5d7e14c3b2e7e5abc78d358fa80db7010e 100644 (file)
@@ -32,6 +32,7 @@ COMMON_OBJPRE = $(OBJ_DIR)$(COMMON_SRC_DIR)
 COMMON_OBJ = context$(OBJ_EXT)
 COMMON_OBJ += document$(OBJ_EXT)
 COMMON_OBJ += object$(OBJ_EXT)
+COMMON_OBJ += action$(OBJ_EXT)
 COMMON_OBJ += container$(OBJ_EXT)
 COMMON_OBJ += types$(OBJ_EXT)
 COMMON_OBJ += app$(OBJ_EXT)
index 67e122589c3fc8ebb728866077c6c9fd5df5b779..38e6b6c1a04939c56c8ff131cbd94805bda3c7cb 100644 (file)
@@ -678,6 +678,7 @@ void uic_text_copy(UiText *from, UiText *to) {
     to->insert = from->insert;
     to->setposition = from->setposition;
     to->position = from->position;
+    to->showposition = from->showposition;
     to->setselection = from->setselection;
     to->selection = from->selection;
     to->length = from->length;
index 36f25b9595bf4a6781c4a9aea3fe4f4a64913d9c..fd355ee06c7e19dfb1dc0badadf4797fb5edaf4d 100644 (file)
@@ -131,6 +131,7 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) {
     uitext->onchangedata = args->onchangedata;
     
     g_object_set_data(G_OBJECT(text_area), "ui_textarea", uitext);
+    g_object_set_data(G_OBJECT(text_area), "ui_textarea_widget", text_area);
     
     g_signal_connect(
                 text_area,
@@ -144,6 +145,7 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) {
             GTK_POLICY_AUTOMATIC,
             GTK_POLICY_AUTOMATIC); // GTK_POLICY_ALWAYS  
     SCROLLEDWINDOW_SET_CHILD(scroll_area, text_area);
+    g_object_set_data(G_OBJECT(scroll_area), "ui_textarea_widget", text_area);
     
     ui_widget_size_request(scroll_area, args->width, args->height);
     
@@ -186,6 +188,7 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) {
         value->insert = ui_textarea_insert;
         value->setposition = ui_textarea_setposition;
         value->position = ui_textarea_position;
+        value->showposition = ui_textarea_showposition;
         value->setselection = ui_textarea_setselection;
         value->selection = ui_textarea_selection;
         value->length = ui_textarea_length;
@@ -211,8 +214,21 @@ void ui_textarea_destroy(GtkWidget *object, UiTextArea *textarea) {
     free(textarea);
 }
 
+void ui_textarea_scroll_to(UIWIDGET textarea, int pos) {
+    GtkWidget *widget = ui_textarea_gettextwidget(textarea);
+    if(!widget) {
+        fprintf(stderr, "Error: ui_textarea_scroll_to: widget is not a textarea\n");
+    }
+    GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
+    
+    GtkTextIter offset;
+    gtk_text_buffer_get_iter_at_offset(buf, &offset, pos);
+    
+    gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(widget), &offset, 0.2, FALSE, 0, 0);
+}
+
 UIWIDGET ui_textarea_gettextwidget(UIWIDGET textarea) {
-    return SCROLLEDWINDOW_GET_CHILD(textarea);
+    return g_object_get_data(G_OBJECT(textarea), "ui_textarea_widget");
 }
 
 void ui_textarea_save(UiText *text) {
@@ -296,6 +312,10 @@ int ui_textarea_position(UiText *text) {
     return text->pos;
 }
 
+void ui_textarea_showposition(UiText *text, int pos) {
+    ui_textarea_scroll_to(text->obj, pos);
+}
+
 void ui_textarea_setselection(UiText *text, int begin, int end) {
     GtkTextBuffer *buf = text->data1;
     GtkTextIter ib;
index 701ed7f9f111d114b02386b0907132be3ee4e89f..a976cbc32d6bf46c56e68057c9ca197b66df0d48 100644 (file)
@@ -120,6 +120,7 @@ char* ui_textarea_getsubstr(UiText *text, int begin, int end);
 void ui_textarea_insert(UiText *text, int pos, char *str);
 void ui_textarea_setposition(UiText *text, int pos);
 int ui_textarea_position(UiText *text);
+void ui_textarea_showposition(UiText *text, int pos);
 void ui_textarea_setselection(UiText *text, int begin, int end);
 void ui_textarea_selection(UiText *text, int *begin, int *end);
 int ui_textarea_length(UiText *text);
index 43cca7e7f6ab80e39a945356b0c8db06fb320f9e..bd5b96b6a5d320ebe88263255808af01eaf378df 100644 (file)
@@ -37,31 +37,38 @@ extern "C" {
 
 
 typedef struct UiMenuItemArgs {
-       const charlabel;
-       const charicon;
+       const char *label;
+       const char *icon;
 
        ui_callback onclick;
-       void* onclickdata;
+       void *onclickdata;
+        const char *action;
+        const char *accelerator;
+        const char *accelerator_text;
 
-       const intstates;
+       const int *states;
 } UiMenuItemArgs;
 
 typedef struct UiMenuToggleItemArgs {
-       const charlabel;
-       const charicon;
+       const char *label;
+       const char *icon;
 
-       const charvarname;
+       const char *varname;
        ui_callback onchange;
-       void* onchangedata;
+       void *onchangedata;
+        const char *action;
+        const char *accelerator;
+        const char *accelerator_text;
 
-       const intnstates;
+       const int *nstates;
 } UiMenuToggleItemArgs;
 
 typedef struct UiMenuItemListArgs {
-       const charvarname;
+       const char *varname;
        ui_getvaluefunc getvalue;
        ui_callback onselect;
-       void* onselectdata;
+       void *onselectdata;
+        const char *action;
         UiBool addseparator;
 } UiMenuItemListArgs;
 
index 9fed6b823d40e01d8f81634953b3952faf07b81a..ebea880d84bc0c4c7df1b75155cf8dd27df593dc 100644 (file)
@@ -149,6 +149,8 @@ UIEXPORT UIWIDGET ui_textarea_gettextwidget(UIWIDGET textarea);
 UIEXPORT void ui_text_undo(UiText *value);
 UIEXPORT void ui_text_redo(UiText *value);
 
+UIEXPORT void ui_textarea_scroll_to(UIWIDGET textarea, int pos);
+
 #define ui_textfield(obj, ...) ui_textfield_create(obj, &(UiTextFieldArgs) { __VA_ARGS__ })
 #define ui_frameless_textfield(obj, ...) ui_frameless_field_create(obj, &(UiTextFieldArgs) { __VA_ARGS__ })
 #define ui_passwordfield(obj, ...) ui_passwordfield_create(obj, &(UiTextFieldArgs) { __VA_ARGS__ })
index 2e230df495810275d9a65fc0313a5ff40e05224e..29319ecb9172235af0e7e7b2722e8bedb8c40c94 100644 (file)
@@ -42,7 +42,10 @@ typedef struct UiToolbarItemArgs {
     const char *tooltip;
 
     ui_callback onclick;
-    void* onclickdata;
+    void *onclickdata;
+    const char *action;
+    const char *accelerator;
+    const char *accelerator_text;
 
     const int *states;
     const int *visibility_states;
@@ -56,6 +59,9 @@ typedef struct UiToolbarToggleItemArgs {
     const char *varname;
     ui_callback onchange;
     void *onchangedata;
+    const char *action;
+    const char *accelerator;
+    const char *accelerator_text;
 
     const int *states;
     const int *visibility_states;
index 9d230734380cb7c3a92dec06b95eedd7d62250ee..9fbc6586f5dc1ab6aad42009973a4571ec13ab7c 100644 (file)
@@ -395,6 +395,7 @@ struct UiText {
     void  (*insert)(UiText*, int, char*);
     void  (*setposition)(UiText*,int);
     int   (*position)(UiText*);
+    void  (*showposition)(UiText*, int);
     void  (*setselection)(UiText*, int, int); /* text, begin, end */
     void  (*selection)(UiText*, int*, int*); /* text, begin, end */
     int   (*length)(UiText*);