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);
}
}
--- /dev/null
+/*
+ * 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);
+}
--- /dev/null
+/*
+ * 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 */
+
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;
#include <cx/list.h>
#include <cx/linked_list.h>
+#include "action.h"
+
#ifdef __cplusplus
extern "C" {
#endif
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);
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)
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;
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,
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);
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;
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) {
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;
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);
typedef struct UiMenuItemArgs {
- const char* label;
- const char* icon;
+ const char *label;
+ const char *icon;
ui_callback onclick;
- void* onclickdata;
+ void *onclickdata;
+ const char *action;
+ const char *accelerator;
+ const char *accelerator_text;
- const int* states;
+ const int *states;
} UiMenuItemArgs;
typedef struct UiMenuToggleItemArgs {
- const char* label;
- const char* icon;
+ const char *label;
+ const char *icon;
- const char* varname;
+ const char *varname;
ui_callback onchange;
- void* onchangedata;
+ void *onchangedata;
+ const char *action;
+ const char *accelerator;
+ const char *accelerator_text;
- const int* nstates;
+ const int *nstates;
} UiMenuToggleItemArgs;
typedef struct UiMenuItemListArgs {
- const char* varname;
+ const char *varname;
ui_getvaluefunc getvalue;
ui_callback onselect;
- void* onselectdata;
+ void *onselectdata;
+ const char *action;
UiBool addseparator;
} UiMenuItemListArgs;
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__ })
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;
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;
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*);