]> uap-core.de Git - note.git/commitdiff
add searchbar UI main
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Wed, 28 Jan 2026 19:17:48 +0000 (20:17 +0100)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Wed, 28 Jan 2026 19:17:48 +0000 (20:17 +0100)
application/application.h
application/window.c
ui/gtk/container.c
ui/motif/container.c
ui/ui/container.h
ui/win32/menu.c
ui/win32/menu.h

index 81b5ed4f8fab8794216ef3ebff2dd0ff55323363..c72754272ea495be13c0881cc73b08c8a75b7634 100644 (file)
@@ -42,6 +42,7 @@ extern "C" {
 #define APP_STATE_NOTEBOOK_SELECTED    100
 #define APP_STATE_NOTE_SELECTED        110
 #define APP_STATE_NOTE_HAS_ATTACHMENTS 201
+#define APP_STATE_NOTE_SEARCHBAR       202
     
     
 #define VIEW_FLAGS_NO_BROWSER          1
index ba35fb9bef1e1b525a9dbd008ebce80b3880f2ec..0bac1920c04ae40445cdc17f2d153c1a26706ff1 100644 (file)
@@ -103,7 +103,7 @@ void window_create() {
                         ui_button(obj, .icon = "insert-image", .onclick = action_textnote_insertimg);
                         ui_button(obj, .icon = "insert-link");
                     }
-                    ui_hbox_w(obj, wdata->attachments, .margin = 10) {
+                    ui_hbox_w(obj, wdata->attachments, .margin = 10, .visibility_states = UI_GROUPS(APP_STATE_NOTE_HAS_ATTACHMENTS)) {
                         UIWIDGET sw;
                         ui_scrolledwindow_w(obj, sw, .name = "note_attachments_sw") {
                             ui_itemlist(obj, .varname = "note_attachments", .container = UI_CONTAINER_HBOX, .create_ui = attachment_item, .userdata = wdata);
@@ -115,10 +115,23 @@ void window_create() {
 #if GTK_MAJOR_VERSION >= 4
                     ui_customwidget(obj, editor_gtk4_workaround, wdata, .hfill = TRUE);
 #endif
-                    ui_set_visible(wdata->attachments, FALSE);
-                    ui_widget_set_states(obj->ctx, wdata->attachments, (ui_enablefunc)ui_set_visible, APP_STATE_NOTE_HAS_ATTACHMENTS, -1);
                     wdata->textview = ui_textarea(obj, .varname = "note_text", .vfill = TRUE, .hfill = TRUE, .hexpand = TRUE, .vexpand = TRUE, .colspan = 2, .states = UI_GROUPS(APP_STATE_NOTE_SELECTED), .fill = UI_ON);
                     editor_init_textview(obj, ui_textarea_gettextwidget(wdata->textview));
+                    
+                    ui_grid(obj, .margin = 4, .columnspacing = 4, .rowspacing = 4, .def_hfill = TRUE, .def_vfill = TRUE, .visibility_states = UI_GROUPS(APP_STATE_NOTE_SEARCHBAR)) {
+                        ui_rlabel(obj, .label = "Find");
+                        ui_textfield(obj, .hexpand = TRUE);
+                        ui_button(obj, .label = "Previous");
+                        ui_button(obj, .label = "Next");
+                        ui_checkbox(obj, .label = "Case Sensitive");
+                        ui_checkbox(obj, .label = "Regex");
+                        
+                        ui_newline(obj);
+                        ui_rlabel(obj, .label = "Replace");
+                        ui_textfield(obj, .hexpand = TRUE);
+                        ui_button(obj, .label = "Replace");
+                        ui_button(obj, .label = "Replace All");
+                    }
                 } 
             }
         }
index ad5297ac802ac4f3818f6c2aa65efe8d1eab0d47..6b8b736c7d26974756df9ced5238b3c07a1b243b 100644 (file)
@@ -393,6 +393,11 @@ UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs *args, UiSubContainerType
     UiContainerX *container = ui_box_container(obj, box, type);
     uic_object_push_container(obj, container);
     
+    if(args->visibility_states) {
+        size_t nstates = uic_state_array_size(args->visibility_states);
+        ui_widget_set_visibility_states(obj->ctx, box, args->visibility_states, (int)nstates);
+    }
+    
     return box;
 }
 
@@ -429,6 +434,11 @@ UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) {
     UiContainerX *container = ui_grid_container(obj, grid, args->def_hexpand, args->def_vexpand, args->def_hfill, args->def_vfill);
     uic_object_push_container(obj, container);
     
+    if(args->visibility_states) {
+        size_t nstates = uic_state_array_size(args->visibility_states);
+        ui_widget_set_visibility_states(obj->ctx, grid, args->visibility_states, (int)nstates);
+    }
+    
     return grid;
 }
 
@@ -476,6 +486,11 @@ UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args) {
         uic_object_push_container(obj, container);
     }
     
+    if(args->visibility_states) {
+        size_t nstates = uic_state_array_size(args->visibility_states);
+        ui_widget_set_visibility_states(obj->ctx, frame, args->visibility_states, (int)nstates);
+    }
+    
     return frame;
 }
 
@@ -500,6 +515,11 @@ UIEXPORT UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs *args) {
         uic_object_push_container(obj, container);
     }
     
+    if(args->visibility_states) {
+        size_t nstates = uic_state_array_size(args->visibility_states);
+        ui_widget_set_visibility_states(obj->ctx, expander, args->visibility_states, (int)nstates);
+    }
+    
     return expander;
 }
 
@@ -525,6 +545,11 @@ UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs *args) {
         uic_object_push_container(obj, container);
     }
     
+    if(args->visibility_states) {
+        size_t nstates = uic_state_array_size(args->visibility_states);
+        ui_widget_set_visibility_states(obj->ctx, sw, args->visibility_states, (int)nstates);
+    }
+    
     return sw;
 }
 
@@ -814,6 +839,11 @@ UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs *args) {
     UiContainerX *container = ui_tabview_container(obj, widget);
     uic_object_push_container(obj, container);
     
+    if(args->visibility_states) {
+        size_t nstates = uic_state_array_size(args->visibility_states);
+        ui_widget_set_visibility_states(obj->ctx, widget, args->visibility_states, (int)nstates);
+    }
+    
     return widget;
 }
 
index c5c7c4df8f760b24c043234c60ad72400a861d24..d1e05991b7d2375bc34d7945489c22dd7737f04f 100644 (file)
@@ -90,6 +90,11 @@ static UIWIDGET box_create(UiObject *obj, UiContainerArgs *args, UiBoxOrientatio
     UiContainerX *container = ui_box_container(obj, grid, orientation);
     uic_object_push_container(obj, container);
     
+    if(args->visibility_states) {
+        size_t nstates = uic_state_array_size(args->visibility_states);
+        ui_widget_set_visibility_states(obj->ctx, grid, args->visibility_states, (int)nstates);
+    }
+    
     return grid;
 }
 
@@ -171,6 +176,11 @@ UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) {
     UiContainerX *container = ui_grid_container(obj, grid, args->def_hexpand, args->def_vexpand, args->def_hfill, args->def_vfill);
     uic_object_push_container(obj, container);
     
+    if(args->visibility_states) {
+        size_t nstates = uic_state_array_size(args->visibility_states);
+        ui_widget_set_visibility_states(obj->ctx, grid, args->visibility_states, (int)nstates);
+    }
+    
     return grid;
 }
 
@@ -299,6 +309,10 @@ UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args) {
         }
     }
     
+    if(args->visibility_states) {
+        size_t nstates = uic_state_array_size(args->visibility_states);
+        ui_widget_set_visibility_states(obj->ctx, frame, args->visibility_states, (int)nstates);
+    }
     
     return frame;
 }
@@ -469,6 +483,11 @@ UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs *args) {
     
     uic_object_push_container(obj, (UiContainerX*)ct);
     
+    if(args->visibility_states) {
+        size_t nstates = uic_state_array_size(args->visibility_states);
+        ui_widget_set_visibility_states(obj->ctx, form, args->visibility_states, (int)nstates);
+    }
+    
     return form;
 }
 
index dc2aa299ebef95b7e26fc502c1edbb28bd58bffc..e9f3d3deda4e2678d6b233e845c865028a84a3ff 100644 (file)
@@ -82,6 +82,8 @@ typedef struct UiContainerArgs {
     UiBool def_vfill;
     UiBool def_hexpand;
     UiBool def_vexpand;
+    
+    const int *visibility_states;
 } UiContainerArgs;
 
 typedef struct UiFrameArgs {
@@ -112,6 +114,8 @@ typedef struct UiFrameArgs {
 
     const char* label;
     UiBool isexpanded;
+    
+    const int *visibility_states;
 } UiFrameArgs;
 
 typedef struct UiTabViewArgs {
@@ -144,6 +148,8 @@ typedef struct UiTabViewArgs {
     int spacing;
     int columnspacing;
     int rowspacing;
+    
+    const int *visibility_states;
 } UiTabViewArgs;
 
 typedef struct UiHeaderbarArgs {
index 82bcf2b4d742d0f3e1db36f3204d6412351bb78b..16171de222e80b150420633d0d4f8d6c8815cb87 100644 (file)
@@ -49,9 +49,11 @@ HMENU ui_create_main_menu(UiObject *obj) {
     }\r
 \r
     HMENU hMenu = CreateMenu();\r
-    ui_add_menu(hMenu, 0, &menu->item, obj);\r
-\r
-\r
+    while (menu) {\r
+        ui_add_menu(hMenu, 0, &menu->item, obj);\r
+        UiMenuItemI *next = menu->item.next;\r
+        menu = next && next->type == UI_MENU ? (UiMenu*)next : NULL;\r
+    }\r
 \r
     return hMenu;\r
 }\r
@@ -256,10 +258,106 @@ void ui_radioitem_set(UiInteger *i, int64_t value) {
     }\r
 }\r
 \r
+static void menuitem_list_remove_binding(void *obj) {\r
+    UiActiveMenuItemList *ls = obj;\r
+    UiList *list = ls->var->value;\r
+    CxList *bindings = list->obj;\r
+    if(bindings) {\r
+        (void)cxListFindRemove(bindings, obj);\r
+        if(cxListSize(bindings) == 0) {\r
+            cxListFree(bindings);\r
+            list->obj = NULL;\r
+            list->update = NULL;\r
+        }\r
+    }\r
+}\r
+\r
 void ui_add_menu_list(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) {\r
+    UiMenuItemList *il = (UiMenuItemList*)item;\r
+    const CxAllocator *a = obj->ctx->allocator;\r
 \r
+    UiVar *var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST);\r
+    if (!var) {\r
+        return;\r
+    }\r
+\r
+    UiActiveMenuItemList *ls = cxMalloc(\r
+            a,\r
+            sizeof(UiActiveMenuItemList));\r
+    ls->object = obj;\r
+    ls->menu = parent;\r
+    ls->command_ids = cxArrayListCreate(a, sizeof(uint64_t), 16);\r
+    ls->index = pos;\r
+    ls->getvalue = il->getvalue;\r
+    ls->callback = il->callback;\r
+    ls->userdata = il->userdata;\r
+    ls->addseparator = il->addseparator;\r
+    ls->var = var;\r
+\r
+    UiList *list = ls->var->value;\r
+    list->update = ui_menulist_update;\r
+    list->getselection = NULL;\r
+    list->setselection = NULL;\r
+\r
+    // It is possible, that the UiVar is from a global shared context,\r
+    // used by multiple windows. To support this usecase, the list->obj\r
+    // binding object is a list of all connected UiActiveMenuItemList.\r
+    CxList *bindings = list->obj;\r
+    if(!bindings) {\r
+        bindings = cxLinkedListCreate(ls->var->from_ctx->mp->allocator, CX_STORE_POINTERS);\r
+        list->obj = bindings;\r
+    }\r
+    cxListAdd(bindings, ls);\r
+\r
+    // The destruction of the toplevel obj must remove the menulist binding\r
+    uic_context_add_destructor(obj->ctx, menuitem_list_remove_binding, ls);\r
+\r
+    ui_update_menuitem_list(ls);\r
 }\r
 \r
+void ui_menulist_update(UiList *list, int ignored) {\r
+    CxList *bindings = list->obj;\r
+    CxIterator i = cxListIterator(bindings);\r
+    cx_foreach(UiActiveMenuItemList *, ls, i) {\r
+        ui_update_menuitem_list(ls);\r
+    }\r
+}\r
+\r
+void ui_update_menuitem_list(UiActiveMenuItemList *list) {\r
+    UiObject *obj = list->object;\r
+\r
+    UiList *ls;\r
+    if(list->var && list->var->value) {\r
+        ls = list->var->value;\r
+    } else {\r
+        return;\r
+    }\r
+\r
+    CxIterator i = cxListIterator(list->command_ids);\r
+    cx_foreach(uint64_t *, id, i) {\r
+        DeleteMenu(list->menu, *id, MF_BYCOMMAND);\r
+    }\r
+    cxListClear(list->command_ids); // TODO: we could reuse some of the ids\r
+\r
+    ui_getvaluefunc getvalue = list->getvalue;\r
+    void* elm = ui_list_first(ls);\r
+\r
+    int pos = list->index;\r
+    while(elm) {\r
+        char *label = (char*) (getvalue ? getvalue(elm, 0) : elm);\r
+        if (!label) {\r
+            label = "";\r
+        }\r
+\r
+        uint64_t id = ++obj->ctx->command_id_counter;\r
+        InsertMenu(list->menu, pos++, MF_STRING, id, label);\r
+        cxListAdd(list->command_ids, &id);\r
+\r
+        elm = ui_list_next(ls);\r
+    }\r
+}\r
+\r
+\r
 void ui_add_menu_checklist(HMENU parent, int pos, UiMenuItemI *item, UiObject *obj) {\r
 \r
 }\r
index 48b0c5f49f0e3f4c1d63f01e23565590cb013b32..efb5d48ce76a864fb7e0f2c231c618990363ee7d 100644 (file)
@@ -48,6 +48,19 @@ typedef struct UiStateMenuItem {
     UiBool state;\r
 } UiStateMenuItem;\r
 \r
+typedef struct UiActiveMenuItemList UiActiveMenuItemList;\r
+struct UiActiveMenuItemList {\r
+    UiObject         *object;\r
+    HMENU            menu;\r
+    CxList           *command_ids;\r
+    int              index;\r
+    UiVar            *var;\r
+    ui_getvaluefunc  getvalue;\r
+    ui_callback      callback;\r
+    void             *userdata;\r
+    bool             addseparator;\r
+};\r
+\r
 typedef void(*ui_menu_add_f)(HMENU, int, UiMenuItemI*, UiObject*);\r
 \r
 HMENU ui_create_main_menu(UiObject *obj);\r
@@ -67,6 +80,9 @@ void ui_checkitem_set(UiInteger *i, int64_t value);
 int64_t ui_radioitem_get(UiInteger *i);\r
 void ui_radioitem_set(UiInteger *i, int64_t value);\r
 \r
+void ui_menulist_update(UiList *list, int ignored);\r
+void ui_update_menuitem_list(UiActiveMenuItemList *list);\r
+\r
 #ifdef __cplusplus\r
 }\r
 #endif\r