Mon, 15 Jun 2026 21:13:05 +0200
change ui_active_states to return also active states from sub-documents
| application/Makefile | file | annotate | diff | comparison | revisions | |
| application/demo_bindings.c | file | annotate | diff | comparison | revisions | |
| application/demo_states.c | file | annotate | diff | comparison | revisions | |
| application/demo_states.h | file | annotate | diff | comparison | revisions | |
| application/main.c | file | annotate | diff | comparison | revisions | |
| ui/common/context.c | file | annotate | diff | comparison | revisions | |
| ui/gtk/text.c | file | annotate | diff | comparison | revisions | |
| ui/ui/toolkit.h | file | annotate | diff | comparison | revisions |
--- a/application/Makefile Sun Jun 14 12:10:34 2026 +0200 +++ b/application/Makefile Mon Jun 15 21:13:05 2026 +0200 @@ -33,11 +33,13 @@ APP_BIN_OBJ = ../build/application/main$(OBJ_EXT) DEMO_BINDINGS_OBJ = ../build/application/demo_bindings$(OBJ_EXT) +DEMO_STATES_OBJ = ../build/application/demo_states$(OBJ_EXT) APP_BIN = ../build/$(BUILD_BIN_DIR)/mk12$(APP_EXT) DEMO_BINDINGS = ../build/$(BUILD_BIN_DIR)/demo_bindings$(APP_EXT) +DEMO_STATES = ../build/$(BUILD_BIN_DIR)/demo_states$(APP_EXT) -all: $(APP_BIN) $(DEMO_BINDINGS) +all: $(APP_BIN) $(DEMO_BINDINGS) $(DEMO_STATES) include $(SYS_MAKEFILE) @@ -46,12 +48,19 @@ $(DEMO_BINDINGS): $(DEMO_BINDINGS_OBJ) $(RES_FILE) $(BUILD_ROOT)/build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)uitk$(LIB_EXT) $(LD) -o $(DEMO_BINDINGS) $(DEMO_BINDINGS_OBJ) $(RES_FILE) $(BUILD_ROOT)/build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)uitk$(LIB_EXT) $(BUILD_ROOT)/build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)ucx$(LIB_EXT) $(LDFLAGS) $(TK_LDFLAGS) + +$(DEMO_STATES): $(DEMO_STATES_OBJ) $(RES_FILE) $(BUILD_ROOT)/build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)uitk$(LIB_EXT) + $(LD) -o $(DEMO_STATES) $(DEMO_STATES_OBJ) $(RES_FILE) $(BUILD_ROOT)/build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)uitk$(LIB_EXT) $(BUILD_ROOT)/build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)ucx$(LIB_EXT) $(LDFLAGS) $(TK_LDFLAGS) FORCE: ../build/application/demo_bindings$(OBJ_EXT): demo_bindings.c \ demo_bindings.h $(CC) -o $@ $(CFLAGS) $(TK_CFLAGS) -c $< + +../build/application/demo_states$(OBJ_EXT): demo_states.c \ + demo_states.h + $(CC) -o $@ $(CFLAGS) $(TK_CFLAGS) -c $< ../build/application/main$(OBJ_EXT): main.c $(CC) -o $@ $(CFLAGS) $(TK_CFLAGS) -c $<
--- a/application/demo_bindings.c Sun Jun 14 12:10:34 2026 +0200 +++ b/application/demo_bindings.c Mon Jun 15 21:13:05 2026 +0200 @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2017 Olaf Wintermann. All rights reserved. + * 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:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/application/demo_states.c Mon Jun 15 21:13:05 2026 +0200 @@ -0,0 +1,162 @@ +/* + * 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 "demo_states.h" + +#include <inttypes.h> + +static void *doc1; +static void *doc2; + +static void doc1_attachment(UiEvent *event, void *userdata) { + if(event->intval) { + printf("attach document 1\n"); + ui_attach_document(event->obj->ctx, doc1); + } else { + printf("detach document 1\n"); + ui_detach_document(event->obj->ctx, doc1); + } +} + +static void doc2_attachment(UiEvent *event, void *userdata) { + UiContext *ctx = ui_document_context(doc1); + if(event->intval) { + printf("attach document 2 to document 1\n"); + ui_attach_document(ctx, doc2); + } else { + printf("detach document 2 from document 1\n"); + ui_detach_document(ctx, doc2); + } +} + +static void doc_enable_state1(UiEvent *event, void *doc) { + UiContext *ctx = ui_document_context(doc); + if(event->intval) { + ui_set_state(ctx, 1); + } else { + ui_unset_state(ctx, 1); + } +} + +static void doc_enable_state2(UiEvent *event, void *doc) { + UiContext *ctx = ui_document_context(doc); + if(event->intval) { + ui_set_state(ctx, 2); + } else { + ui_unset_state(ctx, 2); + } +} + +static void doc_enable_state3(UiEvent *event, void *doc) { + UiContext *ctx = ui_document_context(doc); + if(event->intval) { + ui_set_state(ctx, 3); + } else { + ui_unset_state(ctx, 3); + } +} + +static void doc_enable_state4(UiEvent *event, void *doc) { + UiContext *ctx = ui_document_context(doc); + if(event->intval) { + ui_set_state(ctx, 4); + } else { + ui_unset_state(ctx, 4); + } +} + +static void application_startup(UiEvent *event, void *userdata) { + UiObject *obj = ui_window("States Demo"); + + doc1 = ui_document_new(8); + doc2 = ui_document_new(8); + + ui_hbox(obj, .margin = 10, .spacing = 8) { + ui_button(obj, .label = "State 1", .states = UI_STATES(1)); + ui_button(obj, .label = "State 2", .states = UI_STATES(2)); + ui_button(obj, .label = "State 3", .states = UI_STATES(3)); + ui_button(obj, .label = "State 4", .states = UI_STATES(4)); + ui_button(obj, .label = "State 1,2", .states = UI_STATES(1, 2)); + ui_button(obj, .label = "State 1,2,3", .states = UI_STATES(1, 2, 3)); + ui_button(obj, .label = "State 1,2,3,4", .states = UI_STATES(1, 2, 3, 4)); + } + + ui_frame(obj, .label = "Window", .fill = TRUE, .margin = 10, .subcontainer = UI_CONTAINER_VBOX) { + ui_hbox(obj, .margin = 10, .spacing = 8) { + ui_togglebutton(obj, .label = "Enable 1", .enable_state = 1); + ui_togglebutton(obj, .label = "Enable 2", .enable_state = 2); + ui_togglebutton(obj, .label = "Enable 3", .enable_state = 3); + ui_togglebutton(obj, .label = "Enable 4", .enable_state = 4); + } + + 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_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_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_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_show(obj); +} + + +#ifndef UI_WIN32 + +int main(int argc, char **argv) { + ui_init(NULL, argc, argv); + ui_onstartup(application_startup, NULL); + ui_main(); + return 0; +} + +#else + +int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) { + //ui_init(NULL, argc, argv); + //ui_onstartup(application_startup, NULL); + //ui_main(); + return 0; +} + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/application/demo_states.h Mon Jun 15 21:13:05 2026 +0200 @@ -0,0 +1,46 @@ +/* + * 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 DEMO_STATES_H +#define DEMO_STATES_H + +#include <ui/ui.h> + +#ifdef __cplusplus +extern "C" { +#endif + + + + +#ifdef __cplusplus +} +#endif + +#endif /* DEMO_STATES_H */ +
--- a/application/main.c Sun Jun 14 12:10:34 2026 +0200 +++ b/application/main.c Mon Jun 15 21:13:05 2026 +0200 @@ -726,7 +726,7 @@ ui_button(obj, .label = "Disable Group 2", .onclick = action_group2, .onclickdata = "disable"); ui_newline(obj); - ui_button(obj, .label = "Groups 1,2", .colspan = 2, .states = UI_GROUPS(1, 2)); + ui_button(obj, .label = "Groups 1,2", .colspan = 2, .states = UI_STATES(1, 2)); ui_newline(obj); ui_label(obj, .label = "Label Col 1", .align = UI_ALIGN_LEFT);
--- a/ui/common/context.c Sun Jun 14 12:10:34 2026 +0200 +++ b/ui/common/context.c Mon Jun 15 21:13:05 2026 +0200 @@ -196,6 +196,7 @@ event.document = document; doc_ctx->onattach(&event, doc_ctx->onattachdata); } + uic_check_state_widgets(ui_context_toplevel_parent(ctx)); uic_send_status_change(doc_ctx); } @@ -252,6 +253,7 @@ doc_ctx->ondetach(&event, doc_ctx->ondetachdata); } + uic_check_state_widgets(ui_context_toplevel_parent(ctx)); uic_send_status_change(doc_ctx); ui_document_unref(document); } @@ -651,6 +653,15 @@ return ctx->parent; } +UiContext* ui_context_toplevel_parent(UiContext *ctx) { + if(ctx->obj) { + return ctx; + } else if (ctx->parent) { + return ui_context_toplevel_parent(ctx->parent); + } + return NULL; +} + void ui_set_state(UiContext *ctx, int state) { if(!cxListIndexValid(ctx->states, cxListFind(ctx->states, &state))) { @@ -658,7 +669,7 @@ } // enable/disable group widgets - uic_check_state_widgets(ctx); + uic_check_state_widgets(ui_context_toplevel_parent(ctx)); } void ui_unset_state(UiContext *ctx, int state) { @@ -668,15 +679,39 @@ } // enable/disable group widgets - uic_check_state_widgets(ctx); + uic_check_state_widgets(ui_context_toplevel_parent(ctx)); +} + +typedef struct StatesList { + CX_ARRAY(int, states); +} StatesList; + +static void add_ctx_states(UiContext *ctx, StatesList *states) { + size_t nstates = cxListSize(ctx->states); + int *ctx_states = cxListAt(ctx->states, 0);; + + cx_array_add_array(states->states, ctx_states, nstates); + + CxIterator i = cxListIterator(ctx->documents); + cx_foreach(void *, doc, i) { + UiContext *doc_ctx = ui_document_context(doc); + add_ctx_states(doc_ctx, states); + } } int* ui_active_states(UiContext *ctx, int *nstates) { - *nstates = cxListSize(ctx->states); - return cxListAt(ctx->states, 0); + StatesList states; + cx_array_init(states.states, 32); + add_ctx_states(ctx, &states); + *nstates = (int)states.states.size; + return states.states.data; } void uic_check_state_widgets(UiContext *ctx) { + if(!ctx) { + return; + } + int ngroups = 0; int *groups = ui_active_states(ctx, &ngroups); @@ -702,6 +737,8 @@ free(check); gw->enable(gw->widget, enable); } + + free(groups); } void ui_widget_set_states(UiContext *ctx, UIWIDGET widget, ui_enablefunc enable, ...) {
--- a/ui/gtk/text.c Sun Jun 14 12:10:34 2026 +0200 +++ b/ui/gtk/text.c Mon Jun 15 21:13:05 2026 +0200 @@ -54,9 +54,9 @@ int sel = gtk_text_buffer_get_selection_bounds (buf, &begin, &end); if(sel != textview->last_selection_state) { if(sel) { - ui_set_state(textview->ctx, UI_GROUP_SELECTION); + ui_set_state(textview->ctx, UI_STATE_SELECTION); } else { - ui_unset_state(textview->ctx, UI_GROUP_SELECTION); + ui_unset_state(textview->ctx, UI_STATE_SELECTION); } } textview->last_selection_state = sel;
--- a/ui/ui/toolkit.h Sun Jun 14 12:10:34 2026 +0200 +++ b/ui/ui/toolkit.h Mon Jun 15 21:13:05 2026 +0200 @@ -180,9 +180,9 @@ extern "C" { #endif -#define UI_GROUP_SELECTION 20000 +#define UI_STATE_SELECTION 20000 -#define UI_GROUPS(...) (const int[]){ __VA_ARGS__, -1 } +#define UI_STATES(...) (const int[]){ __VA_ARGS__, -1 } /* public types */ #ifndef __cplusplus @@ -542,6 +542,7 @@ UIEXPORT void ui_context_closefunc(UiContext *ctx, ui_callback fnc, void *udata); UIEXPORT UiContext* ui_context_parent(UiContext *ctx); +UIEXPORT UiContext* ui_context_toplevel_parent(UiContext *ctx); UIEXPORT void ui_object_ref(UiObject *obj); UIEXPORT int ui_object_unref(UiObject *obj);