#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
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);
#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");
+ }
}
}
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
}
}
+ 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;
}
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;
}
UiBool def_vfill;
UiBool def_hexpand;
UiBool def_vexpand;
+
+ const int *visibility_states;
} UiContainerArgs;
typedef struct UiFrameArgs {
const char* label;
UiBool isexpanded;
+
+ const int *visibility_states;
} UiFrameArgs;
typedef struct UiTabViewArgs {
int spacing;
int columnspacing;
int rowspacing;
+
+ const int *visibility_states;
} UiTabViewArgs;
typedef struct UiHeaderbarArgs {
}\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
}\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
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
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