// update parent
int64_t prev_parent_id = res->parent_id;
if(res->parent_id != nbconfig->root_resource_id) {
- UiListSelection sel = ui_list_getselection(nbconfig->tab1_groups);
- if(sel.count == 0) {
- return; // shouldn't happen, maybe remove this when ui_list_getselectedindex exists
- }
- Resource *parent = ui_list_get(nbconfig->tab1_groups, sel.rows[0]);
+ int sel = ui_list_getselection(nbconfig->tab1_groups);
+ Resource *parent = ui_list_get(nbconfig->tab1_groups, sel);
if(!parent) {
return; //shouldn't happen
}
- ui_listselection_free(sel);
prev_parent_id = res->parent_id;
res->parent_id = parent->resource_id;
}
NotebookConfigDialog *wdata = event->window;
NoteStore *store = note_store_get();
- UiListSelection sel = ui_list_getselection(wdata->tab1_notebooks);
- if(sel.count == 1) {
+ int sel = ui_list_getselection(wdata->tab1_notebooks);
+ if(sel >= 0) {
CxList *list = wdata->notebooks;
- Resource *delete_res = cxListAt(list, sel.rows[0]);
+ Resource *delete_res = cxListAt(list, sel);
note_store_collection_get_size_async(event->obj, delete_res, notebook_count_children_result, delete_res);
}
- ui_listselection_free(sel);
}
Resource* nbconfig_notebooklist_find_prev(NotebookConfigDialog *wdata, Resource *res) {
size_t res_index = cxListFind(nblist, wdata->selected_notebook);
cxListSwap(nblist, prev_index, res_index);
ui_list_update(wdata->tab1_notebooks);
- wdata->valuechange = TRUE;
- ui_list_setselection(wdata->tab1_notebooks, prev_index);
- wdata->valuechange = FALSE;
+ ui_list_setselection2(wdata->tab1_notebooks, prev_index, FALSE);
}
}
size_t res_index = cxListFind(nblist, wdata->selected_notebook);
cxListSwap(nblist, next_index, res_index);
ui_list_update(wdata->tab1_notebooks);
- wdata->valuechange = TRUE;
- ui_list_setselection(wdata->tab1_notebooks, next_index);
- wdata->valuechange = FALSE;
+ ui_list_setselection2(wdata->tab1_notebooks, next_index, FALSE);
}
}
}
}
- wdata->valuechange = TRUE;
- ui_list_setselection(wdata->tab1_notebooks, 0);
- wdata->valuechange = FALSE;
+ ui_list_setselection2(wdata->tab1_notebooks, 0, FALSE);
if(group1) {
nbconfig_load_notebook(wdata, group1);
// add
NoteStore *store = note_store_get();
- UiListSelection sel = ui_list_getselection(wdata->groups);
- if(sel.count == 0) {
- fprintf(stderr, "Error: no group selected\n");
- return; // TODO: error
- }
- Resource *parent = ui_list_get(wdata->groups, sel.rows[0]);
- ui_listselection_free(sel);
+ int sel = ui_list_getselection(wdata->groups);
+ Resource *parent = ui_list_get(wdata->groups, sel);
if(!parent) {
fprintf(stderr, "Error: no parent found\n");
}
- (void) tableViewSelectionDidChange:(NSNotification *) notification {
- if(_onselection) {
+ if(_onselection && ui_selection_events_is_enabled()) {
UiListSelection sel = ui_tableview_selection(_tableview);
UiEvent event;
event.eventdatatype = UI_EVENT_DATA_LIST_ELM;
event.intval = index;
- if(_onselection) {
+ if(_onselection && ui_selection_events_is_enabled()) {
_onselection(&event, _onselectiondata);
}
}
void* ui_list_get(UiList *list, int i) {
- return cxListAt(list->data, i);
+ return i >= 0 ? cxListAt(list->data, i) : NULL;
}
int ui_list_count(UiList *list) {
}
void ui_list_remove(UiList *list, int i) {
- cxListRemove(list->data, i);
+ if(i >= 0) {
+ cxListRemove(list->data, i);
+ }
}
void ui_list_clear(UiList *list) {
}
}
+UIEXPORT void ui_list_set_selection(UiList *list, UiListSelection sel) {
+ if(list->setselection) {
+ list->setselection(list, sel);
+ }
+}
+
void ui_list_addobsv(UiList *list, ui_callback f, void *data) {
list->observers = ui_add_observer(list->observers, f, data);
}
}
-UIEXPORT UiListSelection ui_list_getselection(UiList *list) {
+UIEXPORT int ui_list_getselection(UiList *list) {
+ int selection = -1;
if (list->getselection) {
- return list->getselection(list);
+ UiListSelection sel = list->getselection(list);
+ if(sel.count > 0) {
+ selection = sel.rows[0];
+ }
+ ui_listselection_free(sel);
}
- return (UiListSelection){ 0, NULL };
+ return selection;
}
UIEXPORT void ui_list_setselection(UiList *list, int index) {
+ ui_list_setselection2(list, index, TRUE);
+}
+
+UIEXPORT void ui_list_setselection2(UiList *list, int index, UiBool selection_event) {
if (list->setselection) {
UiListSelection sel = { 0, NULL };
if(index >= 0) {
sel.count = 1;
sel.rows = &index;
}
+ UiBool events = ui_selection_events_is_enabled();
+ if(!selection_event) {
+ ui_selection_events_enable(FALSE);
+ }
list->setselection(list, sel);
+ ui_selection_events_enable(events);
}
}
static int ui_set_op = 0;
static int ui_onchange_events_enabled = TRUE;
+static int ui_selection_events_enabled = TRUE;
void ui_setop_enable(int set) {
ui_set_op = set;
return ui_onchange_events_enabled;
}
+void ui_selection_events_enable(UiBool enable) {
+ ui_selection_events_enabled = enable;
+}
+
+UiBool ui_selection_events_is_enabled(void) {
+ return ui_selection_events_enabled;
+}
+
/* ---------------- List initializers and wrapper functions ---------------- */
void ui_global_list_initializer(ui_list_init_func func, void *userdata) {
+++ /dev/null
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2017 Mike Becker, 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 "ucx_properties.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-UcxProperties *ucx_properties_new() {
- UcxProperties *parser = (UcxProperties*)malloc(
- sizeof(UcxProperties));
- if(!parser) {
- return NULL;
- }
-
- parser->buffer = NULL;
- parser->buflen = 0;
- parser->pos = 0;
- parser->tmp = NULL;
- parser->tmplen = 0;
- parser->tmpcap = 0;
- parser->error = 0;
- parser->delimiter = '=';
- parser->comment1 = '#';
- parser->comment2 = 0;
- parser->comment3 = 0;
-
- return parser;
-}
-
-void ucx_properties_free(UcxProperties *parser) {
- if(parser->tmp) {
- free(parser->tmp);
- }
- free(parser);
-}
-
-void ucx_properties_fill(UcxProperties *parser, char *buf, size_t len) {
- parser->buffer = buf;
- parser->buflen = len;
- parser->pos = 0;
-}
-
-static void parser_tmp_append(UcxProperties *parser, char *buf, size_t len) {
- if(parser->tmpcap - parser->tmplen < len) {
- size_t newcap = parser->tmpcap + len + 64;
- parser->tmp = (char*)realloc(parser->tmp, newcap);
- parser->tmpcap = newcap;
- }
- memcpy(parser->tmp + parser->tmplen, buf, len);
- parser->tmplen += len;
-}
-
-int ucx_properties_next(UcxProperties *parser, cxstring *name, cxstring *value) {
- if(parser->tmplen > 0) {
- char *buf = parser->buffer + parser->pos;
- size_t len = parser->buflen - parser->pos;
- cxstring str = cx_strn(buf, len);
- cxstring nl = cx_strchr(str, '\n');
- if(nl.ptr) {
- size_t newlen = (size_t)(nl.ptr - buf) + 1;
- parser_tmp_append(parser, buf, newlen);
- // the tmp buffer contains exactly one line now
-
- char *orig_buf = parser->buffer;
- size_t orig_len = parser->buflen;
-
- parser->buffer = parser->tmp;
- parser->buflen = parser->tmplen;
- parser->pos = 0;
- parser->tmp = NULL;
- parser->tmpcap = 0;
- parser->tmplen = 0;
- // run ucx_properties_next with the tmp buffer as main buffer
- int ret = ucx_properties_next(parser, name, value);
-
- // restore original buffer
- parser->tmp = parser->buffer;
- parser->buffer = orig_buf;
- parser->buflen = orig_len;
- parser->pos = newlen;
-
- /*
- * if ret == 0 the tmp buffer contained just space or a comment
- * we parse again with the original buffer to get a name/value
- * or a new tmp buffer
- */
- return ret ? ret : ucx_properties_next(parser, name, value);
- } else {
- parser_tmp_append(parser, buf, len);
- return 0;
- }
- } else if(parser->tmp) {
- free(parser->tmp);
- parser->tmp = NULL;
- }
-
- char comment1 = parser->comment1;
- char comment2 = parser->comment2;
- char comment3 = parser->comment3;
- char delimiter = parser->delimiter;
-
- // get one line and parse it
- while(parser->pos < parser->buflen) {
- char *buf = parser->buffer + parser->pos;
- size_t len = parser->buflen - parser->pos;
-
- /*
- * First we check if we have at least one line. We also get indices of
- * delimiter and comment chars
- */
- size_t delimiter_index = 0;
- size_t comment_index = 0;
- int has_comment = 0;
-
- size_t i = 0;
- char c = 0;
- for(;i<len;i++) {
- c = buf[i];
- if(c == comment1 || c == comment2 || c == comment3) {
- if(comment_index == 0) {
- comment_index = i;
- has_comment = 1;
- }
- } else if(c == delimiter) {
- if(delimiter_index == 0 && !has_comment) {
- delimiter_index = i;
- }
- } else if(c == '\n') {
- break;
- }
- }
-
- if(c != '\n') {
- // we don't have enough data for a line
- // store remaining bytes in temporary buffer for next round
- parser->tmpcap = len + 128;
- parser->tmp = (char*)malloc(parser->tmpcap);
- parser->tmplen = len;
- memcpy(parser->tmp, buf, len);
- return 0;
- }
-
- cxstring line = has_comment ? cx_strn(buf, comment_index) : cx_strn(buf, i);
- // check line
- if(delimiter_index == 0) {
- line = cx_strtrim(line);
- if(line.length != 0) {
- parser->error = 1;
- }
- } else {
- cxstring n = cx_strn(buf, delimiter_index);
- cxstring v = cx_strn(
- buf + delimiter_index + 1,
- line.length - delimiter_index - 1);
- n = cx_strtrim(n);
- v = cx_strtrim(v);
- if(n.length != 0 || v.length != 0) {
- *name = n;
- *value = v;
- parser->pos += i + 1;
- return 1;
- } else {
- parser->error = 1;
- }
- }
-
- parser->pos += i + 1;
- }
-
- return 0;
-}
-
-int ucx_properties2map(UcxProperties *parser, CxMap *map) {
- cxstring name;
- cxstring value;
- while(ucx_properties_next(parser, &name, &value)) {
- cxmutstr mutvalue = cx_strdup_a(map->collection.allocator, value);
- if(!mutvalue.ptr) {
- return 1;
- }
- if(cxMapPut(map, cx_hash_key_cxstr(name), mutvalue.ptr)) {
- cxFree(map->collection.allocator, mutvalue.ptr);
- return 1;
- }
- }
- if (parser->error) {
- return parser->error;
- } else {
- return 0;
- }
-}
-
-// buffer size is documented - change doc, when you change bufsize!
-#define UCX_PROPLOAD_BUFSIZE 1024
-int ucx_properties_load(CxMap *map, FILE *file) {
- UcxProperties *parser = ucx_properties_new();
- if(!(parser && map && file)) {
- return 1;
- }
-
- int error = 0;
- size_t r;
- char buf[UCX_PROPLOAD_BUFSIZE];
- while((r = fread(buf, 1, UCX_PROPLOAD_BUFSIZE, file)) != 0) {
- ucx_properties_fill(parser, buf, r);
- error = ucx_properties2map(parser, map);
- if (error) {
- break;
- }
- }
- ucx_properties_free(parser);
- return error;
-}
-
-int ucx_properties_store(CxMap *map, FILE *file) {
- CxMapIterator iter = cxMapIterator(map);
- cxstring value;
- size_t written;
-
- cx_foreach(CxMapEntry *, v, iter) {
- value = cx_str(v->value);
-
- written = 0;
- written += fwrite(v->key->data, 1, v->key->len, file);
- written += fwrite(" = ", 1, 3, file);
- written += fwrite(value.ptr, 1, value.length, file);
- written += fwrite("\n", 1, 1, file);
-
- if (written != v->key->len + value.length + 4) {
- return 1;
- }
- }
-
- return 0;
-}
-
+++ /dev/null
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2017 Mike Becker, 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.
- */
-/**
- * @file properties.h
- *
- * Load / store utilities for properties files.
- *
- * @author Mike Becker
- * @author Olaf Wintermann
- */
-
-#ifndef UCX_PROPERTIES_H
-#define UCX_PROPERTIES_H
-
-#include <cx/hash_map.h>
-#include <cx/string.h>
-
-#include <stdio.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/**
- * UcxProperties object for parsing properties data.
- * Most of the fields are for internal use only. You may configure the
- * properties parser, e.g. by changing the used delimiter or specifying
- * up to three different characters that shall introduce comments.
- */
-typedef struct {
- /**
- * Input buffer (don't set manually).
- * Automatically set by calls to ucx_properties_fill().
- */
- char *buffer;
-
- /**
- * Length of the input buffer (don't set manually).
- * Automatically set by calls to ucx_properties_fill().
- */
- size_t buflen;
-
- /**
- * Current buffer position (don't set manually).
- * Used by ucx_properties_next().
- */
- size_t pos;
-
- /**
- * Internal temporary buffer (don't set manually).
- * Used by ucx_properties_next().
- */
- char *tmp;
-
- /**
- * Internal temporary buffer length (don't set manually).
- * Used by ucx_properties_next().
- */
- size_t tmplen;
-
- /**
- * Internal temporary buffer capacity (don't set manually).
- * Used by ucx_properties_next().
- */
- size_t tmpcap;
-
- /**
- * Parser error code.
- * This is always 0 on success and a nonzero value on syntax errors.
- * The value is set by ucx_properties_next().
- */
- int error;
-
- /**
- * The delimiter that shall be used.
- * This is '=' by default.
- */
- char delimiter;
-
- /**
- * The first comment character.
- * This is '#' by default.
- */
- char comment1;
-
- /**
- * The second comment character.
- * This is not set by default.
- */
- char comment2;
-
- /**
- * The third comment character.
- * This is not set by default.
- */
- char comment3;
-} UcxProperties;
-
-
-/**
- * Constructs a new UcxProperties object.
- * @return a pointer to the new UcxProperties object
- */
-UcxProperties *ucx_properties_new();
-
-/**
- * Destroys a UcxProperties object.
- * @param prop the UcxProperties object to destroy
- */
-void ucx_properties_free(UcxProperties *prop);
-
-/**
- * Sets the input buffer for the properties parser.
- *
- * After calling this function, you may parse the data by calling
- * ucx_properties_next() until it returns 0. The function ucx_properties2map()
- * is a convenience function that reads as much data as possible by using this
- * function.
- *
- *
- * @param prop the UcxProperties object
- * @param buf a pointer to the new buffer
- * @param len the payload length of the buffer
- * @see ucx_properties_next()
- * @see ucx_properties2map()
- */
-void ucx_properties_fill(UcxProperties *prop, char *buf, size_t len);
-
-/**
- * Retrieves the next key/value-pair.
- *
- * This function returns a nonzero value as long as there are key/value-pairs
- * found. If no more key/value-pairs are found, you may refill the input buffer
- * with ucx_properties_fill().
- *
- * <b>Attention:</b> the cxstring.ptr pointers of the output parameters point to
- * memory within the input buffer of the parser and will get invalid some time.
- * If you want long term copies of the key/value-pairs, use sstrdup() after
- * calling this function.
- *
- * @param prop the UcxProperties object
- * @param name a pointer to the cxstring that shall contain the property name
- * @param value a pointer to the cxstring that shall contain the property value
- * @return Nonzero, if a key/value-pair was successfully retrieved
- * @see ucx_properties_fill()
- */
-int ucx_properties_next(UcxProperties *prop, cxstring *name, cxstring *value);
-
-/**
- * Retrieves all available key/value-pairs and puts them into a UcxMap.
- *
- * This is done by successive calls to ucx_properties_next() until no more
- * key/value-pairs can be retrieved.
- *
- * The memory for the map values is allocated by the map's own allocator.
- *
- * @param prop the UcxProperties object
- * @param map the target map
- * @return The UcxProperties.error code (i.e. 0 on success).
- * @see ucx_properties_fill()
- * @see UcxMap.allocator
- */
-int ucx_properties2map(UcxProperties *prop, CxMap *map);
-
-/**
- * Loads a properties file to a UcxMap.
- *
- * This is a convenience function that reads data from an input
- * stream until the end of the stream is reached.
- *
- * @param map the map object to write the key/value-pairs to
- * @param file the <code>FILE*</code> stream to read from
- * @return 0 on success, or a non-zero value on error
- *
- * @see ucx_properties_fill()
- * @see ucx_properties2map()
- */
-int ucx_properties_load(CxMap *map, FILE *file);
-
-/**
- * Stores a UcxMap to a file.
- *
- * The key/value-pairs are written by using the following format:
- *
- * <code>[key] = [value]\\n</code>
- *
- * @param map the map to store
- * @param file the <code>FILE*</code> stream to write to
- * @return 0 on success, or a non-zero value on error
- */
-int ucx_properties_store(CxMap *map, FILE *file);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* UCX_PROPERTIES_H */
-
void ui_listview_selection_changed(GtkSelectionModel* self, guint position, guint n_items, gpointer userdata) {
UiListView *view = userdata;
listview_update_selection(view);
- listview_event(view->onselection, view->onselectiondata, view);
+ if(ui_selection_events_is_enabled()) {
+ listview_event(view->onselection, view->onselectiondata, view);
+ }
}
void ui_dropdown_activate(GtkDropDown* self, gpointer userdata) {
GtkTreeSelection *treeselection,
UiTreeEventData *event)
{
+ if(!ui_selection_events_is_enabled()) {
+ return;
+ }
+
UiListSelection selection = ui_listview_get_selection(treeselection, event);
UiEvent e;
if(args->multiselection) {
view->setSelectionMode(QAbstractItemView::ExtendedSelection);
}
+ if(args->hide_header) {
+ view->setHeaderHidden(true);
+ }
UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST);
}
void ListModel::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) {
+ if(!ui_selection_events_is_enabled()) {
+ return;
+ }
+
UiListSelection sel;
if(listview) {
sel = ui_selection_model_to_selection(listview->selectionModel());
--- /dev/null
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+#
+# Copyright 2012 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.
+#
+
+$(SERVER_OBJPRE)%.o: server/%.c
+ $(CC) -o $@ -c -I../ucx $(CFLAGS) $(SHLIB_CFLAGS) $(TK_CFLAGS) $<
+
+$(UI_LIB): $(OBJ)
+ $(AR) $(ARFLAGS) $(UI_LIB) $(OBJ)
+
+$(UI_SHLIB): $(OBJ)
+ $(CC) -o $(UI_SHLIB) $(LDFLAGS) $(SHLIB_LDFLAGS) $(TK_LDFLAGS) $(OBJ) -L../build/lib -lucx
--- /dev/null
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 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 "args.h"
+
+#include <stdio.h>
+
+#include "toolkit.h"
+#include "../common/utils.h"
+
+void ui_argstr_add_int(CxBuffer *buf, const char *name, int i) {
+ char n[32];
+ snprintf(n, 32, "%i", i);
+
+ cxBufferPutString(buf, "\"");
+ cxBufferPutString(buf, name);
+ cxBufferPutString(buf, "\":");
+ cxBufferPutString(buf, n);
+ cxBufferPutString(buf, ",");
+}
+
+void ui_argstr_add_str(CxBuffer *buf, const char *name, const char *value) {
+ cxmutstr value_escaped = ui_escape_string(cx_str(value));
+ cxBufferPutString(buf, "\"");
+ cxBufferPutString(buf, name);
+ cxBufferPutString(buf, "\":\"");
+ cxBufferPutString(buf, value_escaped.ptr);
+ cxBufferPutString(buf, "\",");
+ if(value != value_escaped.ptr) {
+ free(value_escaped.ptr);
+ }
+}
--- /dev/null
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 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 ARGS_H
+#define ARGS_H
+
+#include <cx/buffer.h>
+#include <cx/string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void ui_argstr_add_int(CxBuffer *buf, const char *name, int i);
+void ui_argstr_add_str(CxBuffer *buf, const char *name, const char *value);
+
+#define UI_STANDARD_ARGS(buf, args) \
+ if(args->fill) cxBufferPutString(buf, "\"fill\":true,"); \
+ if(args->hexpand) cxBufferPutString(buf, "\"hexpand\":true,"); \
+ if(args->vexpand) cxBufferPutString(buf, "\"vexpand\":true,"); \
+ if(args->hfill) cxBufferPutString(buf, "\"hfill\":true,"); \
+ if(args->vfill) cxBufferPutString(buf, "\"vfill\":true,"); \
+ if(args->override_defaults) cxBufferPutString(buf, "\"override_defaults\":true,"); \
+ if(args->margin != 0) ui_argstr_add_int(buf, "margin", args->margin); \
+ if(args->margin_left != 0) ui_argstr_add_int(buf, "margin_left", args->margin_left); \
+ if(args->margin_right != 0) ui_argstr_add_int(buf, "margin_right", args->margin_right); \
+ if(args->margin_top != 0) ui_argstr_add_int(buf, "margin_top", args->margin_top); \
+ if(args->margin_bottom != 0) ui_argstr_add_int(buf, "margin_bottom", args->margin_bottom); \
+ if(args->colspan != 0) ui_argstr_add_int(buf, "colspan", args->colspan); \
+ if(args->rowspan != 0) ui_argstr_add_int(buf, "rowspan", args->rowspan); \
+ if(args->name) ui_argstr_add_str(buf, "name", args->name); \
+ if(args->style_class) ui_argstr_add_str(buf, "style_class", args->style_class)
+
+#define UI_LABEL_ARGS(buf, args) \
+ if(args->label) ui_argstr_add_str(buf, "label", args->label); \
+ if(args->icon) ui_argstr_add_str(buf, "icon", args->icon); \
+ if(args->tooltip) ui_argstr_add_str(buf, "tooltip", args->tooltip)
+
+#define UI_SPACING_ARGS(buf, args) \
+ if(args->spacing != 0) ui_argstr_add_int(buf, "spacing", args->spacing); \
+ if(args->columnspacing != 0) ui_argstr_add_int(buf, "columnspacing", args->columnspacing); \
+ if(args->rowspacing != 0) ui_argstr_add_int(buf, "rowspacing", args->rowspacing)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ARGS_H */
+
--- /dev/null
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 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 "button.h"
+#include <cx/buffer.h>
+#include <cx/printf.h>
+
+#include "args.h"
+#include "container.h"
+#include "widget.h"
+#include "var.h"
+
+cxmutstr ui_button_args_to_string(UiContext *ctx, UiButtonArgs *args) {
+ CxBuffer buf;
+ cxBufferInit(&buf, ctx->allocator, NULL, 256, CX_BUFFER_AUTO_EXTEND | CX_BUFFER_FREE_CONTENTS);
+
+ cxBufferPutString(&buf, "{");
+
+ UI_STANDARD_ARGS(&buf, args);
+ UI_LABEL_ARGS(&buf, args);
+ if(args->labeltype != UI_LABEL_DEFAULT) ui_argstr_add_int(&buf, "labeltype", (int)args->labeltype);
+
+ if(buf.size > 0 && buf.space[buf.size-1] == ',') {
+ buf.space[buf.size-1] = ' ';
+ }
+ cxBufferPutString(&buf, "}");
+ return cx_mutstrn(buf.space, buf.size);
+}
+
+cxmutstr ui_toggle_args_to_string(UiContext *ctx, UiToggleArgs *args, cxmutstr value) {
+ CxBuffer buf;
+ cxBufferInit(&buf, ctx->allocator, NULL, 256, CX_BUFFER_AUTO_EXTEND | CX_BUFFER_FREE_CONTENTS);
+
+ cxBufferPutString(&buf, "{");
+
+ UI_STANDARD_ARGS(&buf, args);
+ UI_LABEL_ARGS(&buf, args);
+ if(value.ptr) ui_argstr_add_str(&buf, "value", value.ptr);
+ if(args->labeltype != UI_LABEL_DEFAULT) ui_argstr_add_int(&buf, "labeltype", (int)args->labeltype);
+
+ if(buf.size > 0 && buf.space[buf.size-1] == ',') {
+ buf.space[buf.size-1] = ' ';
+ }
+ cxBufferPutString(&buf, "}");
+ return cx_mutstrn(buf.space, buf.size);
+}
+
+
+UIWIDGET ui_button_create(UiObject *obj, UiButtonArgs *args) {
+ UiCallbackWidget *widget = cxZalloc(obj->ctx->allocator, sizeof(UiCallbackWidget));
+ widget->widget.obj = obj->widget->obj;
+ widget->widget.type = cx_str("button");
+ widget->widget.args = ui_button_args_to_string(obj->ctx, args);
+ widget->widget.serialize = (ui_serialize_func)ui_button_serialize;
+ widget->callback = args->onclick;
+ widget->userdata = args->onclickdata;
+ ui_reg_widget((UiWidget*)widget);
+
+ UiWidget *parent = obj->container_end->container;
+ cxListAdd(parent->children, widget);
+
+ return (UiWidget*)widget;
+}
+
+cxmutstr ui_button_serialize(UiCallbackWidget *w) {
+ CxBuffer buf;
+ cxBufferInit(&buf, cxDefaultAllocator, NULL, 1024, CX_BUFFER_AUTO_EXTEND | CX_BUFFER_FREE_CONTENTS);
+
+ cxBufferPutString(&buf, "{");
+ ui_serialize_type_obj_id(&w->widget, &buf);
+ cxBufferPutString(&buf, ",\"args\":");
+ cxBufferPutString(&buf, w->widget.args.ptr);
+ if(w->widget.var_id.ptr) {
+ cxBufferPutString(&buf, ",\"value\":\"");
+ cxBufferPutString(&buf, w->widget.var_id.ptr);
+ cxBufferPutString(&buf, "\"");
+ }
+ cxBufferPutString(&buf, "}\n");
+
+ return cx_mutstrn(buf.space, buf.size);
+}
+
+static UIWIDGET togglebutton_create(UiObject *obj, const char *type, UiToggleArgs *args) {
+ cxmutstr var_id = cx_mutstrn(NULL, 0);
+ UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_INTEGER);
+ if(var) {
+ UiInteger *i = var->value;
+ if(!i->obj) {
+ ui_server_bind_int(obj->ctx, i);
+ }
+ var_id = cx_mutstr(i->obj);
+ }
+
+ UiCallbackWidget *widget = cxZalloc(obj->ctx->allocator, sizeof(UiCallbackWidget));
+ widget->widget.obj = obj->widget->obj;
+ widget->widget.type = cx_str(type);
+ widget->widget.args = ui_toggle_args_to_string(obj->ctx, args, var_id);
+ widget->widget.var_id = var_id;
+ widget->widget.var_type = UI_VAR_INTEGER;
+ widget->widget.serialize = (ui_serialize_func)ui_button_serialize;
+ widget->callback = args->onchange;
+ widget->userdata = args->onchangedata;
+ ui_reg_widget((UiWidget*)widget);
+
+ UiWidget *parent = obj->container_end->container;
+ cxListAdd(parent->children, widget);
+
+ return (UiWidget*)widget;
+}
+
+UIWIDGET ui_togglebutton_create(UiObject *obj, UiToggleArgs *args) {
+ return togglebutton_create(obj, "togglebutton", args);
+}
+
+UIWIDGET ui_checkbox_create(UiObject *obj, UiToggleArgs *args) {
+ return togglebutton_create(obj, "checkbox", args);
+}
+
+UIWIDGET ui_switch_create(UiObject *obj, UiToggleArgs *args) {
+ return togglebutton_create(obj, "switch", args);
+}
+
+UIWIDGET ui_radiobutton_create(UiObject *obj, UiToggleArgs *args) {
+ return togglebutton_create(obj, "radiobutton", args);
+}
--- /dev/null
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 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 BUTTON_H
+#define BUTTON_H
+
+#include "toolkit.h"
+
+#include "../ui/button.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+cxmutstr ui_button_args_to_string(UiContext *ctx, UiButtonArgs *args);
+cxmutstr ui_toggle_args_to_string(UiContext *ctx, UiToggleArgs *args, cxmutstr value);
+
+cxmutstr ui_button_serialize(UiCallbackWidget *w);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BUTTON_H */
+
--- /dev/null
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 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 <cx/linked_list.h>
+#include <cx/buffer.h>
+
+#include "container.h"
+#include "widget.h"
+#include "args.h"
+
+void ui_container_begin_close(UiObject *obj) {
+ UiContainerX *ct = obj->container_end;
+ ct->close = 1;
+}
+
+int ui_container_finish(UiObject *obj) {
+ UiContainerX *ct = obj->container_end;
+ if(ct->close) {
+ ui_end_new(obj);
+ return 0;
+ }
+ return 1;
+}
+
+UiContainerX* ui_widget_container(UiWidget *w) {
+ UiContainerX *container = cxZalloc(w->obj->ctx->allocator, sizeof(UiContainerX));
+ container->container = w;
+ return container;
+}
+
+cxmutstr ui_container_args_to_string(UiContext *ctx, UiContainerArgs *args) {
+ CxBuffer buf;
+ cxBufferInit(&buf, ctx->allocator, NULL, 256, CX_BUFFER_AUTO_EXTEND | CX_BUFFER_FREE_CONTENTS);
+
+ cxBufferPutString(&buf, "{");
+
+ UI_STANDARD_ARGS(&buf, args);
+ UI_SPACING_ARGS(&buf, args);
+ if(args->def_hfill) cxBufferPutString(&buf, "\"def_hfill\":true,");
+ if(args->def_vfill) cxBufferPutString(&buf, "\"def_vfill\":true,");
+ if(args->def_hexpand) cxBufferPutString(&buf, "\"def_hexpand\":true,");
+ if(args->def_vexpand) cxBufferPutString(&buf, "\"def_vexpand\":true,");
+
+ if(buf.size > 0 && buf.space[buf.size-1] == ',') {
+ buf.space[buf.size-1] = ' ';
+ }
+ cxBufferPutString(&buf, "}");
+ return cx_mutstrn(buf.space, buf.size);
+}
+
+static UIWIDGET container_create(UiObject *obj, const char *type, UiContainerArgs *args) {
+ const CxAllocator *a = obj->ctx->allocator;
+ UiWidget *widget = cxZalloc(a, sizeof(UiWidget));
+ widget->obj = obj->widget->obj;
+ widget->type = cx_str(type);
+ widget->args = ui_container_args_to_string(obj->ctx, args);
+ widget->children = cxLinkedListCreate(a, CX_STORE_POINTERS);
+ widget->serialize = ui_container_serialize;
+
+ UiWidget *parent = obj->container_end->container;
+ cxListAdd(parent->children, widget);
+
+ uic_object_push_container(obj, ui_widget_container(widget));
+ ui_reg_widget((UiWidget*)widget);
+
+ return widget;
+}
+
+void ui_serialize_children(UiWidget *w, CxBuffer *buf) {
+ size_t numchildren = cxListSize(w->children);
+ if(numchildren > 0) {
+ cxBufferPutString(buf, ",\"children\":[");
+ CxIterator i = cxListIterator(w->children);
+ cx_foreach(UiWidget *, child, i) {
+ cxmutstr child_str = child->serialize(child);
+ cxBufferWrite(child_str.ptr, 1, child_str.length, buf);
+ if(i.index+1 < numchildren) {
+ cxBufferPut(buf, ',');
+ }
+ }
+ cxBufferPutString(buf, "]");
+ }
+}
+
+cxmutstr ui_container_serialize(UiWidget *w) {
+ CxBuffer buf;
+ cxBufferInit(&buf, cxDefaultAllocator, NULL, 1024, CX_BUFFER_AUTO_EXTEND | CX_BUFFER_FREE_CONTENTS);
+
+ cxBufferPutString(&buf, "{");
+ ui_serialize_type_obj_id(w, &buf);
+ cxBufferPutString(&buf, ",\"args\":");
+ cxBufferPutString(&buf, w->args.ptr);
+
+ ui_serialize_children(w, &buf);
+
+ cxBufferPutString(&buf, "}\n");
+
+ return cx_mutstrn(buf.space, buf.size);
+}
+
+UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs *args) {
+ return container_create(obj, "vbox", args);
+}
+
+UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs *args) {
+ return container_create(obj, "hbox", args);
+}
+
+UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) {
+ return container_create(obj, "grid", args);
+}
--- /dev/null
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 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 CONTAINER_H
+#define CONTAINER_H
+
+#include "toolkit.h"
+#include "../common/container.h"
+
+#include <cx/buffer.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UiContainerX* ui_widget_container(UiWidget *w);
+
+cxmutstr ui_container_args_to_string(UiContext *ctx, UiContainerArgs *args);
+
+void ui_serialize_children(UiWidget *w, CxBuffer *buf);
+
+cxmutstr ui_container_serialize(UiWidget *w);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CONTAINER_H */
+
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
- * Copyright 2014 Olaf Wintermann. All rights reserved.
+ * Copyright 2025 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:
* POSSIBILITY OF SUCH DAMAGE.
*/
+#include "image.h"
-#include "stock.h"
-#include "../ui/properties.h"
-
-
-
+void ui_image_ref(UIIMAGE img) {
+
+}
+void ui_image_unref(UIIMAGE img) {
+
+}
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
- * Copyright 2014 Olaf Wintermann. All rights reserved.
+ * Copyright 2025 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:
* POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef STOCK_H
-#define STOCK_H
+#ifndef IMAGE_H
+#define IMAGE_H
-#include "../ui/stock.h"
+#include "../ui/image.h"
-#ifdef __cplusplus
+#ifdef __cplusplus
extern "C" {
#endif
-#ifdef __cplusplus
+
+#ifdef __cplusplus
}
#endif
-#endif /* STOCK_H */
+#endif /* IMAGE_H */
--- /dev/null
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+#
+# Copyright 2012 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.
+#
+
+SERVER_SRC_DIR = ui/server/
+SERVER_OBJPRE = $(OBJ_DIR)$(SERVER_SRC_DIR)
+
+SERVEROBJ = toolkit.o
+SERVEROBJ += widget.o
+SERVEROBJ += args.o
+SERVEROBJ += var.o
+SERVEROBJ += window.o
+SERVEROBJ += container.o
+SERVEROBJ += button.o
+SERVEROBJ += image.o
+
+TOOLKITOBJS += $(SERVEROBJ:%=$(SERVER_OBJPRE)%)
+TOOLKITSOURCE += $(SERVEROBJ:%.o=SERVER/%.c)
--- /dev/null
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+
+#include "toolkit.h"
+
+#include "../common/message.h"
+#include "../common/threadpool.h"
+#include "../common/app.h"
+
+#include <cx/hash_map.h>
+#include <cx/printf.h>
+
+static const char *ui_app_name;
+
+static UiMessageHandler *message_handler;
+
+static ui_callback onstartup;
+static void *onstartupdata;
+
+static UiQueue *event_queue;
+
+static CxMap *srv_obj_map;
+static uint64_t srv_obj_id_counter = 0;
+
+void ui_init(const char *appname, int argc, char **argv) {
+ ui_app_name = appname;
+
+ message_handler = uic_simple_msg_handler(STDIN_FILENO, STDOUT_FILENO, ui_server_message_received);
+
+ srv_obj_map = cxHashMapCreate(NULL, CX_STORE_POINTERS, 16);
+}
+
+const char* ui_appname() {
+ return ui_app_name;
+}
+
+void ui_add_styledata(const char *styledata, int len) {
+ // NOOP
+}
+
+
+void ui_server_message_received(cxstring msg) {
+
+}
+
+void ui_main(void) {
+ uic_simple_msg_handler_start(message_handler);
+ uic_application_startup(NULL);
+ event_queue = ui_queue_create();
+ UiServerEvent *event = NULL;
+ while((event = ui_queue_get_wait(event_queue)) != NULL) {
+ if(event->callback) {
+ event->callback(&event->event, event->userdata);
+ }
+ }
+ ui_queue_free(event_queue);
+}
+
+typedef struct CallMain {
+ UiServerEvent event;
+ ui_threadfunc func;
+ void *data;
+} CallMain;
+
+static void mainthr(UiServerEventData *event, void *userdata) {
+ CallMain *c = userdata;
+ if(c->func) {
+ c->func(c->data);
+ }
+ free(c);
+}
+
+void ui_call_mainthread(ui_threadfunc tf, void* td) {
+ CallMain *c = malloc(sizeof(CallMain));
+ c->func = tf;
+ c->data = td;
+ ui_queue_put(event_queue, c);
+}
+
+void ui_show(UiObject *obj) {
+ if(!obj->widget->sent) {
+ cxmutstr msg = obj->widget->serialize(obj->widget);
+ obj->widget->sent = TRUE;
+ uic_message_send(message_handler, msg);
+ free(msg.ptr);
+ }
+ cxmutstr msg = cx_asprintf("{\"type\":\"show\", \"obj\":\"%s\"}\n", obj->widget->obj->id.ptr);
+ obj->widget->invisible = FALSE;
+ uic_message_send(message_handler, msg);
+ free(msg.ptr);
+}
+
+UiSrvObj* ui_create_server_object(UiContext *ctx) {
+ const CxAllocator *a = ctx->allocator;
+ UiSrvObj *obj = cxZalloc(a, sizeof(UiSrvObj));
+
+ char id[32];
+ snprintf(id, 32, "%" PRIx64, srv_obj_id_counter++);
+ obj->id = cx_strdup_a(a, id);
+ obj->ctx = ctx;
+
+ obj->widgets = cxHashMapCreate(a, CX_STORE_POINTERS, 64);
+
+ return obj;
+}
+
+void ui_reg_widget(UiWidget *widget) {
+ UiSrvObj *obj = widget->obj;
+
+ char id[32];
+ snprintf(id, 32, "%" PRIx64, obj->widget_id_counter++);
+
+ widget->id = cx_strdup_a(widget->obj->ctx->allocator, cx_str(id));
+ cxMapPut(obj->widgets, id, widget);
+}
--- /dev/null
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 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 TOOLKIT_H
+#define TOOLKIT_H
+
+#include <inttypes.h>
+#include "../ui/toolkit.h"
+#include "../common/context.h"
+#include "../common/object.h"
+
+#include <cx/list.h>
+#include <cx/string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct UiSrvObj UiSrvObj;
+
+typedef struct UiServerEvent UiServerEvent;
+typedef struct UiServerEventData UiServerEventData;
+typedef void(*ui_srvevent_func)(UiServerEventData *event, void *userdata);
+
+typedef cxmutstr (*ui_serialize_func)(UiWidget *w);
+
+struct UiServerEventData {
+ UiObject *obj;
+ cxmutstr str;
+ int intvalue;
+};
+
+struct UiServerEvent {
+ UiServerEventData event;
+ ui_srvevent_func callback;
+ void *userdata;
+};
+
+struct UiSrvObj {
+ UiContext *ctx;
+ cxmutstr id;
+
+ CxMap *widgets;
+ uint64_t widget_id_counter;
+};
+
+struct UiWidget {
+ UiSrvObj *obj;
+ cxmutstr id;
+ cxstring type;
+ UiVar *var;
+ cxmutstr var_id;
+ UiVarType var_type;
+ CxList *children;
+ cxmutstr args;
+ UiBool invisible;
+ UiBool disabled;
+ UiBool sent;
+ ui_serialize_func serialize;
+};
+
+typedef struct UiCallbackWidget {
+ UiWidget widget;
+ ui_callback callback;
+ void *userdata;
+} UiCallbackWidget;
+
+void ui_server_message_received(cxstring msg);
+
+UiSrvObj* ui_create_server_object(UiContext *ctx);
+void ui_reg_widget(UiWidget *widget);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TOOLKIT_H */
+
--- /dev/null
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 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 <stdio.h>
+#include <stdlib.h>
+
+#include "toolkit.h"
+
+#include "var.h"
+
+static uint64_t var_counter = 0;
+
+char* ui_generate_var_id(const CxAllocator *a) {
+ char id[32];
+ snprintf(id, 32, "%" PRIx64, var_counter++);
+ return cx_strdup_a(a, id).ptr;
+}
+
+cxmutstr ui_server_bind_int(UiContext *ctx, UiInteger *i) {
+ i->obj = ui_generate_var_id(ctx->allocator);
+ i->get = ui_server_int_get;
+ i->set = ui_server_int_set;
+ return cx_mutstr(i->obj);
+}
+
+cxmutstr ui_server_bind_double(UiContext *ctx, UiDouble *d) {
+ d->obj = ui_generate_var_id(ctx->allocator);
+ d->get = ui_server_double_get;
+ d->set = ui_server_double_set;
+ return cx_mutstr(d->obj);
+}
+
+cxmutstr ui_server_bind_string(UiContext *ctx, UiString *s) {
+ s->obj = ui_generate_var_id(ctx->allocator);
+ s->get = ui_server_string_get;
+ s->set = ui_server_string_set;
+ return cx_mutstr(s->obj);
+}
+
+
+int64_t ui_server_int_get(UiInteger *i) {
+ return 0;
+}
+
+void ui_server_int_set(UiInteger *i, int64_t value) {
+
+}
+
+double ui_server_double_get(UiDouble *d) {
+ return 0;
+}
+
+void ui_server_double_set(UiDouble *d, double value) {
+
+}
+
+char* ui_server_string_get(UiString *s) {
+ return NULL;
+}
+
+void ui_server_string_set(UiString *s, const char *str) {
+
+}
--- /dev/null
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 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 VAR_H
+#define VAR_H
+
+#include "../ui/toolkit.h"
+#include <cx/allocator.h>
+#include <cx/string.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char* ui_generate_var_id(const CxAllocator *a);
+
+cxmutstr ui_server_bind_int(UiContext *ctx, UiInteger *i);
+cxmutstr ui_server_bind_double(UiContext *ctx, UiDouble *d);
+cxmutstr ui_server_bind_string(UiContext *ctx, UiString *s);
+
+int64_t ui_server_int_get(UiInteger *i);
+void ui_server_int_set(UiInteger *i, int64_t value);
+
+double ui_server_double_get(UiDouble *d);
+void ui_server_double_set(UiDouble *d, double value);
+
+char* ui_server_string_get(UiString *s);
+void ui_server_string_set(UiString *s, const char *str);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* VAR_H */
+
--- /dev/null
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 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 <stdio.h>
+
+#include "widget.h"
+#include "toolkit.h"
+
+void ui_serialize_type_obj_id(UiWidget *w, CxBuffer *buf) {
+ cxBufferPutString(buf, "\"type\":\"");
+ cxBufferPutString(buf, w->type.ptr);
+ cxBufferPutString(buf, "\",\"obj\":\"");
+ cxBufferPutString(buf, w->obj->id.ptr);
+ cxBufferPutString(buf, "\",\"id\":\"");
+ cxBufferPutString(buf, w->id.ptr);
+ cxBufferPutString(buf, "\"");
+}
+
+
+void ui_set_enabled(UIWIDGET widget, int enabled) {
+
+}
+
+void ui_set_visible(UIWIDGET widget, int visible) {
+
+}
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
- * Copyright 2014 Olaf Wintermann. All rights reserved.
+ * Copyright 2025 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:
* POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef STOCK_H
-#define STOCK_H
+#ifndef WIDGET_H
+#define WIDGET_H
-#include "../ui/stock.h"
+#include "../ui/widget.h"
+#include <cx/buffer.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
-#endif /* STOCK_H */
+void ui_serialize_type_obj_id(UiWidget *w, CxBuffer *buf);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WIDGET_H */
--- /dev/null
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2025 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 "window.h"
+#include "container.h"
+#include "widget.h"
+
+#include "../common/object.h"
+
+#include <cx/buffer.h>
+
+static UiObject* create_window(const char *title, const char *type, UiBool sidebar) {
+ UiObject *obj = uic_object_new_toplevel();
+ const CxAllocator *a = obj->ctx->allocator;
+
+ UiWindow *window = cxZalloc(a, sizeof(UiWindow));
+ window->widget.obj = ui_create_server_object(obj->ctx);
+ window->widget.type = cx_str(type);
+ window->widget.children = cxLinkedListCreate(a, CX_STORE_POINTERS);
+ window->widget.serialize = (ui_serialize_func)ui_window_serialize;
+ window->widget.invisible = TRUE;
+ window->title = cx_strdup_a(a, title);
+
+ obj->widget = (UiWidget*)window;
+ uic_object_push_container(obj, ui_widget_container((UiWidget*)window));
+ ui_reg_widget(obj->widget);
+
+ return obj;
+}
+
+UiObject *ui_window(const char *title) {
+ return create_window(title, "window", FALSE);
+}
+
+UiObject *ui_sidebar_window(const char *title) {
+ return create_window(title, "sidebar_window", FALSE);
+}
+
+UiObject *ui_splitview_window(const char *title, UiBool sidebar) {
+ return create_window(title, "splitview_window", sidebar);
+}
+
+UiObject *ui_simple_window(const char *title) {
+ return create_window(title, "simple_window", FALSE);
+}
+
+
+cxmutstr ui_window_serialize(UiWindow *w) {
+ CxBuffer buf;
+ cxBufferInit(&buf, NULL, NULL, 1024, CX_BUFFER_AUTO_EXTEND | CX_BUFFER_FREE_CONTENTS);
+
+ cxBufferPutString(&buf, "{");
+ ui_serialize_type_obj_id(&w->widget, &buf);
+
+ if(w->title.ptr) {
+ cxBufferPutString(&buf, ",\"title\":\"");
+ cxBufferWrite(w->title.ptr, 1, w->title.length, &buf);
+ cxBufferPutString(&buf, "\"");
+ }
+
+ ui_serialize_children(&w->widget, &buf);
+
+ cxBufferPutString(&buf, "}\n");
+
+ return cx_mutstrn(buf.space, buf.size);
+}
+
+
/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
- * Copyright 2014 Olaf Wintermann. All rights reserved.
+ * Copyright 2025 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:
* POSSIBILITY OF SUCH DAMAGE.
*/
-#include <stdio.h>
-#include <stdlib.h>
+#ifndef WINDOW_H
+#define WINDOW_H
-#include "stock.h"
-#include "../ui/properties.h"
-#include <cx/hash_map.h>
+#include "../ui/window.h"
+#include "toolkit.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct UiWindow {
+ UiWidget widget;
+ cxmutstr title;
+} UiWindow;
+
+cxmutstr ui_window_serialize(UiWindow *w);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WINDOW_H */
+++ /dev/null
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2017 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 UI_STOCK_H
-#define UI_STOCK_H
-
-#include "toolkit.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-// motif stock ids
-#if UI_MOTIF || UI_COCOA || UI_QT4 || UI_QT5
-
-#define UI_STOCK_NEW "ui.stock.New"
-#define UI_STOCK_OPEN "ui.stock.Open"
-#define UI_STOCK_SAVE "ui.stock.Save"
-#define UI_STOCK_SAVE_AS "ui.stock.SaveAs"
-#define UI_STOCK_REVERT_TO_SAVED "ui.stock.RevertToSaved"
-#define UI_STOCK_GO_BACK "ui.stock.GoBack"
-#define UI_STOCK_GO_FORWARD "ui.stock.GoForward"
-#define UI_STOCK_ADD "ui.stock.Add"
-#define UI_STOCK_CLOSE "ui.stock.Close"
-
-#define UI_STOCK_UNDO "ui.stock.Undo"
-#define UI_STOCK_REDO "ui.stock.Redo"
-#define UI_STOCK_CUT "ui.stock.Cut"
-#define UI_STOCK_COPY "ui.stock.Copy"
-#define UI_STOCK_PASTE "ui.stock.Paste"
-#define UI_STOCK_DELETE "ui.stock.Delete"
-
-#endif
-
-#if UI_GTK2 || UI_GTK3
-
-#define UI_STOCK_NEW GTK_STOCK_NEW
-#define UI_STOCK_OPEN GTK_STOCK_OPEN
-#define UI_STOCK_SAVE GTK_STOCK_SAVE
-#define UI_STOCK_SAVE_AS GTK_STOCK_SAVE_AS
-#define UI_STOCK_REVERT_TO_SAVED GTK_STOCK_REVERT_TO_SAVED
-#define UI_STOCK_UNDO GTK_STOCK_UNDO
-#define UI_STOCK_REDO GTK_STOCK_REDO
-#define UI_STOCK_GO_BACK GTK_STOCK_GO_BACK
-#define UI_STOCK_GO_FORWARD GTK_STOCK_GO_FORWARD
-#define UI_STOCK_ADD GTK_STOCK_ADD
-#define UI_STOCK_CLOSE GTK_STOCK_CLOSE
-
-#define UI_STOCK_UNDO GTK_STOCK_UNDO
-#define UI_STOCK_REDO GTK_STOCK_REDO
-#define UI_STOCK_CUT GTK_STOCK_CUT
-#define UI_STOCK_COPY GTK_STOCK_COPY
-#define UI_STOCK_PASTE GTK_STOCK_PASTE
-#define UI_STOCK_DELETE GTK_STOCK_DELETE
-
-#endif
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* UI_STOCK_H */
-
UIEXPORT void ui_list_update(UiList *list);
UIEXPORT void ui_list_update_row(UiList *list, int row);
UIEXPORT UiListSelection ui_list_get_selection(UiList *list);
+UIEXPORT void ui_list_set_selection(UiList *list, UiListSelection sel);
UIEXPORT void ui_list_addobsv(UiList *list, ui_callback f, void *data);
UIEXPORT void ui_list_notify(UiList *list);
-UIEXPORT UiListSelection ui_list_getselection(UiList *list);
+UIEXPORT int ui_list_getselection(UiList *list);
UIEXPORT void ui_list_setselection(UiList *list, int index);
+UIEXPORT void ui_list_setselection2(UiList *list, int index, UiBool selection_event);
+
+UIEXPORT void ui_listselection_free(UiListSelection selection);
UIEXPORT UiFileList ui_filelist_copy(UiFileList list);
UIEXPORT void ui_filelist_free(UiFileList list);
-UIEXPORT void ui_listselection_free(UiListSelection selection);
-
-
UIEXPORT UiStr ui_str(char *cstr);
UIEXPORT UiStr ui_str_free(char *str, void (*free)(void *v));
UIEXPORT int ui_get_setop(void);
UIEXPORT void ui_onchange_events_enable(UiBool enable);
UIEXPORT UiBool ui_onchange_events_is_enabled(void);
+UIEXPORT void ui_selection_events_enable(UiBool enable);
+UIEXPORT UiBool ui_selection_events_is_enabled(void);
UIEXPORT void ui_global_list_initializer(ui_list_init_func func, void *userdata);
+++ /dev/null
-/*
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright 2017 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 UI_TREE_H
-#define UI_TREE_H
-
-#include "toolkit.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct UiModel UiModel;
-typedef struct UiListCallbacks UiListCallbacks;
-typedef struct UiListDnd UiListDnd;
-
-typedef struct UiListArgs UiListArgs;
-typedef struct UiSourceListArgs UiSourceListArgs;
-
-typedef struct UiSubList UiSubList;
-typedef struct UiSubListItem UiSubListItem;
-
-typedef enum UiModelType {
- UI_STRING = 0,
- UI_STRING_FREE,
- UI_INTEGER,
- UI_ICON,
- UI_ICON_TEXT,
- UI_ICON_TEXT_FREE,
- UI_STRING_EDITABLE,
- UI_BOOL_EDITABLE
-} UiModelType;
-
-typedef struct UiCellValue {
- union {
- const char *string;
- int64_t i;
- UiBool b;
- };
- UiModelType type;
-} UiCellValue;
-
-typedef UiBool (*ui_list_savefunc)(UiList *list, int row, int col, UiCellValue *value, void *userdata);
-
-struct UiModel {
- /*
- * number of columns
- */
- int columns;
-
- /*
- * current allocation size (internal)
- */
- int alloc;
-
- /*
- * array of column types
- * array length is the number of columns
- */
- UiModelType *types;
-
- /*
- * array of column titles
- * array length is the number of columns
- */
- char **titles;
-
- /*
- * array of column size hints
- */
- int *columnsize;
-};
-
-struct UiListCallbacks {
- /*
- * selection callback
- */
- ui_callback activate;
-
- /*
- * cursor callback
- */
- ui_callback selection;
-
- /*
- * userdata for all callbacks
- */
- void *userdata;
-};
-
-struct UiListArgs {
- UiBool fill;
- UiBool hexpand;
- UiBool vexpand;
- UiBool hfill;
- UiBool vfill;
- UiBool override_defaults;
- int margin;
- int margin_left;
- int margin_right;
- int margin_top;
- int margin_bottom;
- int colspan;
- int rowspan;
- int width;
- int height;
-
- const char *name;
- const char *style_class;
- UiList *list;
- const char* varname;
- UiModel *model;
- char **static_elements;
- size_t static_nelm;
- ui_getvaluefunc getvalue;
- ui_getvaluefunc2 getvalue2;
- void *getvalue2data;
- ui_getstylefunc getstyle;
- void *getstyledata;
- ui_callback onactivate;
- void *onactivatedata;
- ui_callback onselection;
- void *onselectiondata;
- ui_callback ondragstart;
- void *ondragstartdata;
- ui_callback ondragcomplete;
- void *ondragcompletedata;
- ui_callback ondrop;
- void *ondropdata;
- UiBool multiselection;
- UiMenuBuilder *contextmenu;
- ui_list_savefunc onsave;
- void *onsavedata;
-
- const int *groups;
-};
-
-typedef void (*ui_sublist_getvalue_func)(UiList *list, void *sublist_userdata, void *rowdata, int index, UiSubListItem *item, void *userdata);
-
-struct UiSubList {
- UiList *value;
- const char *varname;
- const char *header;
- UiBool separator;
- void *userdata;
-};
-
-typedef struct UiSubListEventData {
- UiList *list;
- int sublist_index;
- int row_index;
- void *row_data;
- void *sublist_userdata;
- void *event_data;
-} UiSubListEventData;
-
-/*
- * list item members must be filled by the sublist getvalue func
- * all members must be allocated (by malloc, strdup, ...) the pointer
- * will be passed to free
- */
-struct UiSubListItem {
- char *icon;
- char *label;
- char *button_icon;
- char *button_label;
- UiMenuBuilder *button_menu;
- char *badge;
- void *eventdata;
-};
-
-struct UiSourceListArgs {
- UiBool fill;
- UiBool hexpand;
- UiBool vexpand;
- UiBool hfill;
- UiBool vfill;
- UiBool override_defaults;
- int margin;
- int margin_left;
- int margin_right;
- int margin_top;
- int margin_bottom;
- int colspan;
- int rowspan;
- int width;
- int height;
- const char *name;
- const char *style_class;
-
- const int *groups;
-
- /*
- * static list of sublists
- * a sublist must have a varname or a value
- *
- * the last entry in the list must contain all NULL values or numsublists
- * must contain the number of sublists
- *
- * sublists can be NULL, in which case sublists are dynamically loaded
- * from dynamic_sublist/varname
- */
- UiSubList *sublists;
- /*
- * optional number of sublists
- * if the value is 0, it is assumed, that sublists is null-terminated
- * (last item contains only NULL values)
- */
- size_t numsublists;
-
- /*
- * list value, that contains UiSubList* elements
- */
- UiList *dynamic_sublist;
-
- /*
- * load sublists dynamically from a variable with the specified name
- */
- const char *varname;
-
-
- /*
- * callback for each list item, that should fill all necessary
- * UiSubListItem fields
- */
- ui_sublist_getvalue_func getvalue;
-
- /*
- * getvalue_func userdata
- */
- void *getvaluedata;
-
- /*
- * is a sublist header a selectable item
- */
- UiBool header_is_item;
-
- /*
- * activated when a list item is selected
- */
- ui_callback onactivate;
- void *onactivatedata;
-
- /*
- * activated, when the additional list item button is clicked
- */
- ui_callback onbuttonclick;
- void *onbuttonclickdata;
-
- UiMenuBuilder *contextmenu;
-};
-
-#define UI_SUBLIST(...) (UiSubList){ __VA_ARGS__ }
-#define UI_SUBLISTS(...) (UiSubList[]){ __VA_ARGS__, (UiSubList){NULL,NULL,NULL,0} }
-
-
-/*
- * Creates an UiModel, that specifies columns for a table widget.
- *
- * For each column a column type (UiModelType) and a title string
- * (char*) must be specified. The column list must be terminated
- * with -1.
- *
- * UiModel *model = ui_model(ctx, UI_STRING, "Column 1", UI_STRING, "Column 2", -1);
- */
-UIEXPORT UiModel* ui_model(UiContext *ctx, ...);
-UIEXPORT UiModel* ui_model_new(UiContext *ctx);
-UIEXPORT void ui_model_add_column(UiContext *ctx, UiModel *model, UiModelType type, const char *title, int width);
-UIEXPORT UiModel* ui_model_copy(UiContext *ctx, UiModel* model);
-UIEXPORT void ui_model_free(UiContext *ctx, UiModel *mi);
-
-#define ui_listview(obj, ...) ui_listview_create(obj, &(UiListArgs) { __VA_ARGS__ } )
-#define ui_table(obj, ...) ui_table_create(obj, &(UiListArgs) { __VA_ARGS__ } )
-#define ui_combobox(obj, ...) ui_combobox_create(obj, &(UiListArgs) { __VA_ARGS__ } )
-#define ui_breadcrumbbar(obj, ...) ui_breadcrumbbar_create(obj, &(UiListArgs) { __VA_ARGS__ } )
-#define ui_sourcelist(obj, ...) ui_sourcelist_create(obj, &(UiSourceListArgs) { __VA_ARGS__ } )
-
-UIEXPORT UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args);
-UIEXPORT UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args);
-UIEXPORT UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs *args);
-UIEXPORT UIWIDGET ui_breadcrumbbar_create(UiObject *obj, UiListArgs *args);
-
-UIEXPORT void ui_listview_select(UIWIDGET listview, int index);
-UIEXPORT void ui_combobox_select(UIWIDGET dropdown, int index);
-
-UIEXPORT UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs *args);
-
-UIEXPORT void ui_sublist_item_set_icon(UiSubListItem *item, const char *icon);
-UIEXPORT void ui_sublist_item_set_label(UiSubListItem *item, const char *label);
-UIEXPORT void ui_sublist_item_set_button_icon(UiSubListItem *item, const char *button_icon);
-UIEXPORT void ui_sublist_item_set_button_label(UiSubListItem *item, const char *button_label);
-UIEXPORT void ui_sublist_item_set_button_menu(UiSubListItem *item, UiMenuBuilder *menu);
-UIEXPORT void ui_sublist_item_set_badge(UiSubListItem *item, const char *badge);
-UIEXPORT void ui_sublist_item_set_eventdata(UiSubListItem *item, void *eventdata);
-
-
-
-/*
- * Only relevant for some language bindings
- */
-typedef void(*ui_sourcelist_update_func)(void);
-
-/*
- * The sourcelist update callback is called after any source list
- * sublist update is completed
- */
-UIEXPORT void ui_sourcelist_set_update_callback(ui_sourcelist_update_func cb);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* UI_TREE_H */
-
.enable = w32_widget_default_enable,\r
.show = w32_widget_default_show,\r
.get_preferred_size = ui_listview_get_preferred_size,\r
- .destroy = w32_widget_default_destroy\r
+ .destroy = ui_listview_destroy\r
};\r
\r
static void* strmodel_getvalue(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) {\r
HWND parent = ui_container_get_parent(container);\r
UiLayout layout = UI_ARGS2LAYOUT(args);\r
\r
+ unsigned int noheader = 0;\r
+ if (!table || args->hide_header) {\r
+ noheader = LVS_NOCOLUMNHEADER;\r
+ }\r
HWND hwnd = CreateWindowEx(\r
WS_EX_CLIENTEDGE,\r
WC_LISTVIEW,\r
"",\r
- WS_CHILD | WS_VISIBLE | LVS_REPORT,\r
+ WS_CHILD | WS_VISIBLE | LVS_REPORT | noheader,\r
0, 0, 100, 100,\r
parent,\r
(HMENU)1337,\r
return size;\r
}\r
\r
+void ui_listview_destroy(W32Widget *widget) {\r
+ UiListView *listview = (UiListView*)widget;\r
+ if (listview->model) {\r
+ ui_model_unref(listview->model);\r
+ }\r
+ free(widget);\r
+}\r
+\r
/*\r
* Creates and inserts an LVITEM\r
*\r
\r
int ui_listview_eventproc(W32Widget *widget, HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);\r
W32Size ui_listview_get_preferred_size(W32Widget *widget);\r
+void ui_listview_destroy(W32Widget *widget);\r
\r
void ui_listview_update(UiList *list, int row);\r
UiListSelection ui_listview_getselection_impl(UiList *list);\r