Tue, 16 Jun 2026 17:29:14 +0200
add ui_suppress_state/ui_unsuppress_state
| application/demo_states.c | file | annotate | diff | comparison | revisions | |
| ui/common/context.c | file | annotate | diff | comparison | revisions | |
| ui/common/context.h | file | annotate | diff | comparison | revisions | |
| ui/ui/toolkit.h | file | annotate | diff | comparison | revisions |
--- a/application/demo_states.c Mon Jun 15 21:16:47 2026 +0200 +++ b/application/demo_states.c Tue Jun 16 17:29:14 2026 +0200 @@ -90,6 +90,42 @@ } } +static void doc_suppress_state1(UiEvent *event, void *doc) { + UiContext *ctx = ui_document_context(doc); + if(event->intval) { + ui_suppress_state(ctx, 1); + } else { + ui_unsuppress_state(ctx, 1); + } +} + +static void doc_suppress_state2(UiEvent *event, void *doc) { + UiContext *ctx = ui_document_context(doc); + if(event->intval) { + ui_suppress_state(ctx, 2); + } else { + ui_unsuppress_state(ctx, 2); + } +} + +static void doc_suppress_state3(UiEvent *event, void *doc) { + UiContext *ctx = ui_document_context(doc); + if(event->intval) { + ui_suppress_state(ctx, 3); + } else { + ui_unsuppress_state(ctx, 3); + } +} + +static void doc_suppress_state4(UiEvent *event, void *doc) { + UiContext *ctx = ui_document_context(doc); + if(event->intval) { + ui_suppress_state(ctx, 4); + } else { + ui_unsuppress_state(ctx, 4); + } +} + static void application_startup(UiEvent *event, void *userdata) { UiObject *obj = ui_window("States Demo"); @@ -117,21 +153,35 @@ ui_frame(obj, .label = "Doc 1", .fill = TRUE, .margin = 10, .padding = 10, .spacing = 10, .subcontainer = UI_CONTAINER_VBOX) { ui_togglebutton(obj, .label = "Attach", .onchange = doc1_attachment); - ui_hbox(obj, .margin = 10, .spacing = 8) { + ui_grid(obj, .margin = 10, .columnspacing = 8, .rowspacing = 8, .def_hfill = TRUE) { ui_togglebutton(obj, .label = "Enable 1", .onchange = doc_enable_state1, .onchangedata = doc1); ui_togglebutton(obj, .label = "Enable 2", .onchange = doc_enable_state2, .onchangedata = doc1); ui_togglebutton(obj, .label = "Enable 3", .onchange = doc_enable_state3, .onchangedata = doc1); ui_togglebutton(obj, .label = "Enable 4", .onchange = doc_enable_state4, .onchangedata = doc1); + + ui_newline(obj); + + ui_togglebutton(obj, .label = "Suppress 1", .onchange = doc_suppress_state1, .onchangedata = doc1); + ui_togglebutton(obj, .label = "Suppress 2", .onchange = doc_suppress_state2, .onchangedata = doc1); + ui_togglebutton(obj, .label = "Suppress 3", .onchange = doc_suppress_state3, .onchangedata = doc1); + ui_togglebutton(obj, .label = "Suppress 4", .onchange = doc_suppress_state4, .onchangedata = doc1); } ui_frame(obj, .label = "Doc 2", .fill = TRUE, .margin = 10, .padding = 10, .spacing = 10, .subcontainer = UI_CONTAINER_VBOX) { ui_togglebutton(obj, .label = "Attach", .onchange = doc2_attachment); - ui_hbox(obj, .margin = 10, .spacing = 8) { + ui_grid(obj, .margin = 10, .columnspacing = 8, .rowspacing = 8, .def_hfill = TRUE) { ui_togglebutton(obj, .label = "Enable 1", .onchange = doc_enable_state1, .onchangedata = doc2); ui_togglebutton(obj, .label = "Enable 2", .onchange = doc_enable_state2, .onchangedata = doc2); ui_togglebutton(obj, .label = "Enable 3", .onchange = doc_enable_state3, .onchangedata = doc2); ui_togglebutton(obj, .label = "Enable 4", .onchange = doc_enable_state4, .onchangedata = doc2); + + ui_newline(obj); + + ui_togglebutton(obj, .label = "Suppress 1", .onchange = doc_suppress_state1, .onchangedata = doc2); + ui_togglebutton(obj, .label = "Suppress 2", .onchange = doc_suppress_state2, .onchangedata = doc2); + ui_togglebutton(obj, .label = "Suppress 3", .onchange = doc_suppress_state3, .onchangedata = doc2); + ui_togglebutton(obj, .label = "Suppress 4", .onchange = doc_suppress_state4, .onchangedata = doc2); } } }
--- a/ui/common/context.c Mon Jun 15 21:16:47 2026 +0200 +++ b/ui/common/context.c Tue Jun 16 17:29:14 2026 +0200 @@ -67,6 +67,8 @@ ctx->state_widgets = cxLinkedListCreate(mp->allocator, sizeof(UiStateWidget)); ctx->states = cxArrayListCreate(mp->allocator, sizeof(int), 32); cxSetCompareFunc(ctx->states, cx_cmp_int); + ctx->suppressed_states = cxArrayListCreate(mp->allocator, sizeof(int), 16); + cxSetCompareFunc(ctx->suppressed_states, cx_cmp_int); ctx->actions = cxHashMapCreate(ctx->allocator, sizeof(UiAction), 8); ctx->action_bindings = cxArrayListCreate(ctx->allocator, sizeof(UiActionBinding), 0); @@ -682,15 +684,39 @@ uic_check_state_widgets(ui_context_toplevel_parent(ctx)); } +void ui_suppress_state(UiContext *ctx, int state) { + if(!cxListIndexValid(ctx->suppressed_states, cxListFind(ctx->suppressed_states, &state))) { + cxListAdd(ctx->suppressed_states, &state); + } + + // enable/disable group widgets + uic_check_state_widgets(ui_context_toplevel_parent(ctx)); +} + +void ui_unsuppress_state(UiContext *ctx, int state) { + int i = cxListFind(ctx->suppressed_states, &state); + if(i != -1) { + cxListRemove(ctx->suppressed_states, i); + } + + // enable/disable group widgets + uic_check_state_widgets(ui_context_toplevel_parent(ctx)); +} + typedef struct StatesList { CX_ARRAY(int, states); + CX_ARRAY(int, suppressed); } StatesList; static void add_ctx_states(UiContext *ctx, StatesList *states) { size_t nstates = cxListSize(ctx->states); - int *ctx_states = cxListAt(ctx->states, 0);; + int *ctx_states = cxListAt(ctx->states, 0); + + size_t nsuppressed = cxListSize(ctx->suppressed_states); + int *ctx_suppressed_states = cxListAt(ctx->suppressed_states, 0); cx_array_add_array(states->states, ctx_states, nstates); + cx_array_add_array(states->suppressed, ctx_suppressed_states, nsuppressed); CxIterator i = cxListIterator(ctx->documents); cx_foreach(void *, doc, i) { @@ -702,7 +728,28 @@ int* ui_active_states(UiContext *ctx, int *nstates) { StatesList states; cx_array_init(states.states, 32); + cx_array_init(states.suppressed, 8); add_ctx_states(ctx, &states); + + // remove suppressed states + for(size_t i=0;i<states.suppressed.size;i++) { + int suppressed = states.suppressed.data[i]; + // important to use ssize_t for the index here + for(ssize_t s=0;s<states.states.size;s++) { + if(states.states.data[s] == suppressed) { + // this state is suppressed + if(s+1 < states.states.size) { + // copy last element to the current position + states.states.data[s] = states.states.data[states.states.size-1]; + // we need to check the current index again + s--; + } + states.states.size--; + } + } + } + + free(states.suppressed.data); *nstates = (int)states.states.size; return states.states.data; } @@ -712,16 +759,16 @@ return; } - int ngroups = 0; - int *groups = ui_active_states(ctx, &ngroups); + int nstates = 0; + int *states = ui_active_states(ctx, &nstates); CxIterator i = cxListIterator(ctx->state_widgets); cx_foreach(UiStateWidget *, gw, i) { char *check = calloc(1, gw->numstates); - for(int i=0;i<ngroups;i++) { + for(int i=0;i<nstates;i++) { for(int k=0;k<gw->numstates;k++) { - if(groups[i] == gw->states[k]) { + if(states[i] == gw->states[k]) { check[k] = 1; } } @@ -738,7 +785,7 @@ gw->enable(gw->widget, enable); } - free(groups); + free(states); } void ui_widget_set_states(UiContext *ctx, UIWIDGET widget, ui_enablefunc enable, ...) {
--- a/ui/common/context.h Mon Jun 15 21:16:47 2026 +0200 +++ b/ui/common/context.h Tue Jun 16 17:29:14 2026 +0200 @@ -75,6 +75,7 @@ CxMap *vars; CxList *states; // int list + CxList *suppressed_states; // int list CxList *state_widgets; // UiGroupWidget list CxMap *actions; // key: action name (string), value: UiAction
--- a/ui/ui/toolkit.h Mon Jun 15 21:16:47 2026 +0200 +++ b/ui/ui/toolkit.h Tue Jun 16 17:29:14 2026 +0200 @@ -624,6 +624,8 @@ UIEXPORT void ui_set_state(UiContext *ctx, int state); UIEXPORT void ui_unset_state(UiContext *ctx, int state); +UIEXPORT void ui_suppress_state(UiContext *ctx, int state); +UIEXPORT void ui_unsuppress_state(UiContext *ctx, int state); UIEXPORT int* ui_active_states(UiContext *ctx, int *nstates); UIEXPORT void* ui_allocator(UiContext *ctx);