]> uap-core.de Git - note.git/commitdiff
simplify list selections in nbconfig.c
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 25 Jan 2026 11:11:59 +0000 (12:11 +0100)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Sun, 25 Jan 2026 11:11:59 +0000 (12:11 +0100)
33 files changed:
application/nbconfig.c
application/window.c
ui/cocoa/ListDelegate.m
ui/cocoa/list.m
ui/common/types.c
ui/common/ucx_properties.c [deleted file]
ui/common/ucx_properties.h [deleted file]
ui/gtk/list.c
ui/qt/list.cpp
ui/qt/model.cpp
ui/server/Makefile [new file with mode: 0644]
ui/server/args.c [new file with mode: 0644]
ui/server/args.h [new file with mode: 0644]
ui/server/button.c [new file with mode: 0644]
ui/server/button.h [new file with mode: 0644]
ui/server/container.c [new file with mode: 0644]
ui/server/container.h [new file with mode: 0644]
ui/server/image.c [moved from ui/qt/stock.cpp with 89% similarity]
ui/server/image.h [moved from ui/motif/stock.h with 89% similarity]
ui/server/objs.mk [new file with mode: 0644]
ui/server/toolkit.c [new file with mode: 0644]
ui/server/toolkit.h [new file with mode: 0644]
ui/server/var.c [new file with mode: 0644]
ui/server/var.h [new file with mode: 0644]
ui/server/widget.c [new file with mode: 0644]
ui/server/widget.h [moved from ui/qt/stock.h with 82% similarity]
ui/server/window.c [new file with mode: 0644]
ui/server/window.h [moved from ui/motif/stock.c with 79% similarity]
ui/ui/stock.h [deleted file]
ui/ui/toolkit.h
ui/ui/tree.h [deleted file]
ui/win32/list.c
ui/win32/list.h

index 792b28689b506c0f77717d29a02c5f461a33f4db..ce688380e4f55afe08e6cf7f990854eb5d71adbd 100644 (file)
@@ -178,15 +178,11 @@ void nbconfig_notebook_save(NotebookConfigDialog *nbconfig) {
     // 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;
     }
@@ -393,13 +389,12 @@ static void nbconfig_notebooklist_delete(UiEvent *event, void *userdata) {
     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) {
@@ -452,9 +447,7 @@ static void nbconfig_notebooklist_move_up(UiEvent *event, void *userdata) {
         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);
     }
 }
 
@@ -475,9 +468,7 @@ static void nbconfig_notebooklist_move_down(UiEvent *event, void *userdata) {
         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);
     }
 }
 
@@ -679,9 +670,7 @@ void notebook_config_dialog(void) {
         }
     }
     
-    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);
index 53cc0f3ca7ee512eb85881b905de372b07da1641..ba35fb9bef1e1b525a9dbd008ebce80b3880f2ec 100644 (file)
@@ -307,13 +307,8 @@ static void action_nnd_button(UiEvent *event, void *userdata) {
         // 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");
index 7e15f3d7a768bcced3dfdd52645d57ed7208cbda..9d80a7abc3112f455463e187be9df82394cd2bce 100644 (file)
@@ -59,7 +59,7 @@
 }
 
 - (void) tableViewSelectionDidChange:(NSNotification *) notification {
-    if(_onselection) {
+    if(_onselection && ui_selection_events_is_enabled()) {
         UiListSelection sel = ui_tableview_selection(_tableview);
         
         UiEvent  event;
index 5e72e9243a868c276d5d34e021eec0209f4bbf3b..97e9e4e8471395e54a316d4d316ddb807352874c 100644 (file)
@@ -263,7 +263,7 @@ void ui_tableview_setselection(UiList *list, UiListSelection selection) {
     event.eventdatatype = UI_EVENT_DATA_LIST_ELM;
     event.intval = index;
     
-    if(_onselection) {
+    if(_onselection && ui_selection_events_is_enabled()) {
         _onselection(&event, _onselectiondata);
     }
     
index 2f65c16083d8fe68c40c80b399593ee1f321ff8b..32cb180e716e128563f74b409b6459ec5b5d19e5 100644 (file)
@@ -153,7 +153,7 @@ void* ui_list_next(UiList *list) {
 }
 
 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) {
@@ -169,7 +169,9 @@ void ui_list_prepend(UiList *list, void *data) {
 }
 
 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) {
@@ -196,6 +198,12 @@ UiListSelection ui_list_get_selection(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);
 }
@@ -789,21 +797,35 @@ void uic_generic_unbind(UiGeneric *g) {
 }
 
 
-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);
     }
 }
 
@@ -870,6 +892,7 @@ void uic_list_register_observer_destructor(UiContext *ctx, UiList *list, UiObser
 
 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;
@@ -887,6 +910,14 @@ UiBool ui_onchange_events_is_enabled(void) {
     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) {
diff --git a/ui/common/ucx_properties.c b/ui/common/ucx_properties.c
deleted file mode 100644 (file)
index 21e9341..0000000
+++ /dev/null
@@ -1,263 +0,0 @@
-/*
- * 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;
-}
-
diff --git a/ui/common/ucx_properties.h b/ui/common/ucx_properties.h
deleted file mode 100644 (file)
index cfb4359..0000000
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * 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 */
-
index 3914bf2accfb731e9de6a6d3132ee233466c92cd..f3a3895465a342f3360858ab4a9a30ec1ae5e4ae 100644 (file)
@@ -874,7 +874,9 @@ void ui_columnview_activate(void *ignore, guint position, gpointer userdata) {
 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) {
@@ -1795,6 +1797,10 @@ void ui_listview_selection_event(
         GtkTreeSelection *treeselection,
         UiTreeEventData *event)
 {
+    if(!ui_selection_events_is_enabled()) {
+        return;
+    }
+    
     UiListSelection selection = ui_listview_get_selection(treeselection, event);
     
     UiEvent e;
index a2bac52a2ee86f8cbc84d2c16850d3c44686217b..899e8c6fd4440ac253208d6a9521e2dca506f630 100644 (file)
@@ -102,6 +102,9 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) {
     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);
     
index 361da2ff36ef7d132cfa9dad05b68c4ab4eda6ba..c74c43fe3ddbb515050a0cede813290b0e591cc8 100644 (file)
@@ -99,6 +99,10 @@ QVariant ListModel::data(const QModelIndex &index, int role) const {
 }
 
 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());
diff --git a/ui/server/Makefile b/ui/server/Makefile
new file mode 100644 (file)
index 0000000..7efd7f6
--- /dev/null
@@ -0,0 +1,36 @@
+#
+# 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
diff --git a/ui/server/args.c b/ui/server/args.c
new file mode 100644 (file)
index 0000000..8257780
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * 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);
+    }
+}
diff --git a/ui/server/args.h b/ui/server/args.h
new file mode 100644 (file)
index 0000000..d421e9a
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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 */
+
diff --git a/ui/server/button.c b/ui/server/button.c
new file mode 100644 (file)
index 0000000..8182791
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * 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);
+}
diff --git a/ui/server/button.h b/ui/server/button.h
new file mode 100644 (file)
index 0000000..2b69389
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * 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 */
+
diff --git a/ui/server/container.c b/ui/server/container.c
new file mode 100644 (file)
index 0000000..17a64d4
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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);
+}
diff --git a/ui/server/container.h b/ui/server/container.h
new file mode 100644 (file)
index 0000000..dc7f3e9
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * 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 */
+
similarity index 89%
rename from ui/qt/stock.cpp
rename to ui/server/image.c
index 1ead20bac6d7ef62584d104e8534f4e186f52b29..a54ebda48b43e6c30b8353668e9c879ff9c13a6e 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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) {
+    
+}
similarity index 89%
rename from ui/motif/stock.h
rename to ui/server/image.h
index c3cdb7f77fa5eb821f1960a9459733eb9dbe760c..2bc0490acfded30cf40a598f5d2d11d6609bf52b 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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 */
 
diff --git a/ui/server/objs.mk b/ui/server/objs.mk
new file mode 100644 (file)
index 0000000..6d5fa31
--- /dev/null
@@ -0,0 +1,42 @@
+#
+# 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)
diff --git a/ui/server/toolkit.c b/ui/server/toolkit.c
new file mode 100644 (file)
index 0000000..fd0b57d
--- /dev/null
@@ -0,0 +1,145 @@
+/*
+ * 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);
+}
diff --git a/ui/server/toolkit.h b/ui/server/toolkit.h
new file mode 100644 (file)
index 0000000..0a255a4
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * 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 */
+
diff --git a/ui/server/var.c b/ui/server/var.c
new file mode 100644 (file)
index 0000000..7865da2
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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) {
+    
+}
diff --git a/ui/server/var.h b/ui/server/var.h
new file mode 100644 (file)
index 0000000..dd46dc6
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * 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 */
+
diff --git a/ui/server/widget.c b/ui/server/widget.c
new file mode 100644 (file)
index 0000000..01a15e3
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * 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) {
+    
+}
similarity index 82%
rename from ui/qt/stock.h
rename to ui/server/widget.h
index f80f1a463afeae7f99a9aaee92e3d24a3ab19b66..66dce9eb514218fd78dacf1aef48c64177c30285 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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 */
 
diff --git a/ui/server/window.c b/ui/server/window.c
new file mode 100644 (file)
index 0000000..afc534c
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * 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);
+}
+
+
similarity index 79%
rename from ui/motif/stock.c
rename to ui/server/window.h
index 190fdbdde573f4f521fd2498b5e048d8856e95bd..40191b915203d37e08e9b03bffae85340da55b38 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * 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 */
 
diff --git a/ui/ui/stock.h b/ui/ui/stock.h
deleted file mode 100644 (file)
index ab2d13d..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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 */
-
index fff2dda4486550ded23b0339ad4c13720922c1fc..9d230734380cb7c3a92dec06b95eedd7d62250ee 100644 (file)
@@ -683,11 +683,15 @@ UIEXPORT void ui_list_clear(UiList *list);
 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);
@@ -699,9 +703,6 @@ UIEXPORT void ui_add_image(char *imgname, char *filename); // TODO: remove?
 
 
 
-UIEXPORT void ui_listselection_free(UiListSelection selection);
-
-
 UIEXPORT UiStr ui_str(char *cstr);
 UIEXPORT UiStr ui_str_free(char *str, void (*free)(void *v));
 
@@ -719,6 +720,8 @@ UIEXPORT void ui_setop_enable(int set);
 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);
diff --git a/ui/ui/tree.h b/ui/ui/tree.h
deleted file mode 100644 (file)
index a71092b..0000000
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * 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 */
-
index b2c1495d59ecc2b4cf2cba35edc924b7d6dfe841..179702a09a500b5b9678dec82100d23ebfeccd73 100644 (file)
@@ -41,7 +41,7 @@ static W32WidgetClass listview_widget_class = {
     .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
@@ -103,11 +103,15 @@ static UIWIDGET listview_create(UiObject *obj, UiListArgs *args, UiBool table) {
     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
@@ -278,6 +282,14 @@ W32Size ui_listview_get_preferred_size(W32Widget *widget) {
     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
index 3074ed40369f29c121f6d18f68423d7c1c7bb317..b8d501bfc3d96896e3b4ea2e1baf4981405142bb 100644 (file)
@@ -64,6 +64,7 @@ typedef struct UiListView {
 \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