Sun, 20 Jul 2025 22:04:39 +0200
update toolkit, adjust UI code
--- a/application/Makefile Sat Apr 05 17:57:04 2025 +0200 +++ b/application/Makefile Sun Jul 20 22:04:39 2025 +0200 @@ -45,10 +45,13 @@ OBJ = $(SRC:%.c=../build/application/%.$(OBJ_EXT)) +LIB_UCX = $(BUILD_ROOT)/build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)ucx$(LIB_EXT) +LIB_UITK = $(BUILD_ROOT)/build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)uitk$(LIB_EXT) + all: ../build/bin/idav$(APP_EXT) -../build/bin/idav$(APP_EXT): $(OBJ) - $(CC) -o ../build/bin/idav$(APP_EXT) $(OBJ) -L$(BUILD_ROOT)/build/lib -luitk -lucx -lidav $(LDFLAGS) $(TK_LDFLAGS) $(DAV_LDFLAGS) +../build/bin/idav$(APP_EXT): $(OBJ) $(LIB_UCX) $(LIB_UITK) + $(CC) -o ../build/bin/idav$(APP_EXT) $(OBJ) -L$(BUILD_ROOT)/build/lib -lidav $(LDFLAGS) $(TK_LDFLAGS) $(DAV_LDFLAGS) $(LIB_UCX) $(LIB_UITK) ../build/application/%.$(OBJ_EXT): %.c $(CC) $(CFLAGS) $(TK_CFLAGS) $(DAV_CFLAGS) -o $@ -c $<
--- a/application/settings.c Sat Apr 05 17:57:04 2025 +0200 +++ b/application/settings.c Sun Jul 20 22:04:39 2025 +0200 @@ -636,18 +636,18 @@ wdata->obj = obj; settings_init(obj, wdata); - ui_tabview(obj, .tabview = UI_TABVIEW_NAVIGATION_TOP) { + ui_tabview(obj, .tabview = UI_TABVIEW_NAVIGATION_TOP, .fill = TRUE) { ui_tab(obj, "General") { - ui_grid(obj, .margin = 10) { + ui_grid(obj, .margin = 10, .fill = TRUE) { ui_label(obj, .label = "TODO"); } } ui_tab(obj, "Repositories") { - ui_tabview(obj, .value = wdata->repo_tabview, .tabview = UI_TABVIEW_INVISIBLE) { + ui_tabview(obj, .value = wdata->repo_tabview, .tabview = UI_TABVIEW_INVISIBLE, .fill = TRUE) { ui_tab(obj, "list") { - ui_grid(obj, .margin = 16, .columnspacing = 10, .rowspacing = 10) { + ui_grid(obj, .margin = 16, .columnspacing = 10, .rowspacing = 10, .fill = TRUE) { ui_hbox(obj, .spacing = 4) { ui_button(obj, .label = "Add", .onclick = repolist_add); ui_button(obj, .label = "Edit", .onclick = repolist_edit, .groups = UI_GROUPS(SETTINGS_STATE_REPOLIST_SELECTED)); @@ -663,18 +663,19 @@ .multiselection = FALSE, .onactivate = repolist_activate, .onselection = repolist_selection, - .vexpand = TRUE, .hexpand = TRUE, .colspan = 3); + .vexpand = TRUE, .hexpand = TRUE, + .hfill = TRUE, .vfill = TRUE, .colspan = 3); } } ui_tab(obj, "repo") { - ui_vbox(obj, .margin = 16, .spacing = 10) { - ui_hbox(obj, .fill = UI_OFF, .spacing = 4) { + ui_vbox(obj, .margin = 16, .spacing = 10, .fill = TRUE) { + ui_hbox(obj, .spacing = 4) { ui_button(obj, .icon = UI_ICON_GO_BACK, .onclick = editrepo_go_back); ui_label(obj, .label = "Repository List"); } - ui_scrolledwindow(obj, .hexpand = TRUE, .vexpand = TRUE, .subcontainer = UI_CONTAINER_NO_SUB) { + ui_scrolledwindow(obj, .subcontainer = UI_CONTAINER_NO_SUB, .fill = TRUE) { ui_grid(obj, .margin = 10, .columnspacing = 10, .rowspacing = 10) { ui_llabel(obj, .label = "Name"); ui_textfield(obj, .value = wdata->repo_name, .width = 15); @@ -740,19 +741,19 @@ } ui_tab(obj, "Sync Directories") { - ui_grid(obj, .margin = 10) { + ui_grid(obj, .margin = 10, .fill = TRUE) { ui_label(obj, .label = "TODO"); } } ui_tab(obj, "Credentials") { - ui_hbox(obj, .margin = 16, .spacing = 30) { - ui_vbox(obj, .fill = UI_OFF, .spacing = 4) { - ui_hbox(obj, .fill = UI_OFF, .spacing = 4) { + ui_hbox(obj, .margin = 16, .spacing = 30, .fill = TRUE) { + ui_vbox(obj, .spacing = 4) { + ui_hbox(obj, .spacing = 4) { ui_button(obj, .label = "Add", .onclick = credentials_add); ui_button(obj, .label = "Remove", .onclick = credentials_remove, .groups = UI_GROUPS(SETTINGS_STATE_CREDENTIALS_SELECTED)); } - ui_listview(obj, .list = wdata->credentials_users, .fill = UI_ON, .onselection = credentials_onselect); + ui_listview(obj, .list = wdata->credentials_users, .fill = TRUE, .onselection = credentials_onselect); } ui_grid(obj, .columnspacing = 30, .rowspacing = 10) { @@ -783,8 +784,8 @@ #else ui_callback credentials_activate_callback = NULL; #endif - ui_listview(obj, .list = wdata->credentials_locations, .onactivate = credentials_activate_callback, .onselection = credentials_location_onselect, .colspan = 2, .fill = UI_ON, .groups = UI_GROUPS(SETTINGS_STATE_CREDENTIALS_SELECTED)); - ui_vbox(obj, .fill = UI_OFF, .spacing = 4) { + ui_listview(obj, .list = wdata->credentials_locations, .onactivate = credentials_activate_callback, .onselection = credentials_location_onselect, .colspan = 2, .fill = TRUE, .groups = UI_GROUPS(SETTINGS_STATE_CREDENTIALS_SELECTED)); + ui_vbox(obj, .spacing = 4) { ui_button(obj, .label = "Add", .onclick = credentials_location_add, .groups = UI_GROUPS(SETTINGS_STATE_CREDENTIALS_SELECTED)); ui_button(obj, .label = "Edit", .onclick = credentials_location_edit, .groups = UI_GROUPS(SETTINGS_STATE_CREDENTIALS_SELECTED, SETTINGS_STATE_CREDENTIALS_LOCATION_SELECTED)); ui_button(obj, .label = "Remove", .onclick = credentials_location_remove, .groups = UI_GROUPS(SETTINGS_STATE_CREDENTIALS_SELECTED, SETTINGS_STATE_CREDENTIALS_LOCATION_SELECTED)); @@ -798,12 +799,12 @@ ui_tab(obj, "Keys") { ui_hbox(obj, .margin = 16, .spacing = 30) { - ui_vbox(obj, .fill = UI_OFF, .spacing = 4) { - ui_hbox(obj, .fill = UI_OFF, .spacing = 4) { + ui_vbox(obj, .spacing = 4) { + ui_hbox(obj, .spacing = 4) { ui_button(obj, .label = "Add", .onclick = keys_add); ui_button(obj, .label = "Remove", .onclick = keys_remove, .groups = UI_GROUPS(SETTINGS_STATE_KEYS_SELECTED)); } - ui_listview(obj, .list = wdata->keys_list, .fill = UI_ON, .onselection = keys_onselect, .getvalue = keylist_getvalue); + ui_listview(obj, .list = wdata->keys_list, .fill = TRUE, .onselection = keys_onselect, .getvalue = keylist_getvalue); } ui_grid(obj, .columnspacing = 30, .rowspacing = 10) { @@ -828,9 +829,9 @@ */ } - ui_hbox(obj, .fill = UI_OFF, .margin = 10) { + ui_hbox(obj, .margin = 10) { ui_button(obj, .label = "Cancel", .onclick = settings_cancel); - ui_label(obj, .fill = UI_ON); + ui_label(obj, .fill = TRUE); ui_button(obj, .label = "Save", .onclick = settings_ok); }
--- a/application/window.c Sat Apr 05 17:57:04 2025 +0200 +++ b/application/window.c Sun Jul 20 22:04:39 2025 +0200 @@ -81,13 +81,13 @@ // navigation bar - ui_hbox(obj, .fill = UI_OFF, .margin = 8, .spacing = 8) { - ui_hbox(obj, .fill = UI_OFF, .style_class="linked") { + ui_hbox(obj, .margin = 8, .spacing = 8) { + ui_hbox(obj, .style_class="linked") { ui_button(obj, .icon = UI_ICON_GO_BACK, .onclick = action_go_back); ui_button(obj, .icon = UI_ICON_GO_FORWARD, .onclick = action_go_forward); } - ui_path_textfield(obj, .fill = UI_ON, .getpathelm = dav_get_pathelm, .onactivate = action_path_selected, .varname = "path"); + ui_path_textfield(obj, .fill = TRUE, .getpathelm = dav_get_pathelm, .onactivate = action_path_selected, .varname = "path"); ui_progressspinner(obj, .value = wdata->progress); } @@ -97,7 +97,7 @@ model->columnsize[2] = 150; model->getvalue = (ui_getvaluefunc) window_resource_table_getvalue; ui_table(obj, - .fill = UI_ON, + .fill = TRUE, .model = model, .onselection = action_list_selection, .onactivate = action_list_activate, @@ -110,7 +110,7 @@ // status bar - ui_hbox(obj, .fill = UI_OFF) { + ui_hbox0(obj) { ui_label(obj, .label = ""); } @@ -199,10 +199,10 @@ ui_attach_document(win->ctx, doc); ui_context_closefunc(win->ctx, resourceviewer_close, doc); - ui_tabview(win, .tabview = UI_TABVIEW_INVISIBLE, .varname = "tabview") { + ui_tabview(win, .tabview = UI_TABVIEW_INVISIBLE, .varname = "tabview", .fill = TRUE) { /* loading / message tab */ ui_tab(win, NULL) { - ui_hbox(win, .margin = 16, .spacing = 10, .fill = UI_OFF) { + ui_hbox(win, .margin = 16, .spacing = 10, .fill = TRUE) { ui_progressspinner(win, .varname = "loading"); ui_label(win, .varname = "message"); } @@ -210,7 +210,7 @@ /* preview tab */ ui_tab(win, NULL) { - ui_tabview0(win) { + ui_tabview(win, .fill = TRUE) { if(type == DAV_RESOURCE_VIEW_TEXT) { ui_tab(win, "Content") { ui_textarea(win, .varname = "text", .onchange = action_resourceviewer_text_modified); @@ -220,12 +220,13 @@ ui_imageviewer(win, .varname = "image", .scrollarea = TRUE, - .useradjustable = TRUE); + .useradjustable = TRUE, + .fill = TRUE); } } ui_tab(win, "Info") { - ui_grid(win, .margin = 16, .columnspacing = 30, .rowspacing = 6) { + ui_grid(win, .margin = 16, .columnspacing = 30, .rowspacing = 6, .fill = TRUE) { ui_llabel(win, .label = "URL"); ui_llabel(win, .varname = "info_url"); ui_newline(win); @@ -255,8 +256,8 @@ ui_tab(win, "Properties") { UiModel* model = ui_model(win->ctx, UI_STRING, "Namespace", UI_STRING, "Name", UI_STRING, "Value", -1); model->getvalue = (ui_getvaluefunc) resourceviewer_proplist_getvalue; - ui_table(win, .fill = UI_ON, .model = model, .varname = "properties", .onselection = action_resourceviewer_property_select, .onactivate = action_resourceviewer_property_activate); - ui_hbox(win, .fill = UI_OFF, .margin = 4, .spacing = 4) { + ui_table(win, .fill = TRUE, .model = model, .varname = "properties", .onselection = action_resourceviewer_property_select, .onactivate = action_resourceviewer_property_activate); + ui_hbox(win, .margin = 4, .spacing = 4) { ui_button(win, .label = "Add", .onclick = action_resourceviewer_property_add); ui_button(win, .label = "Edit", .onclick = action_resourceviewer_property_edit, .groups = UI_GROUPS(RESOURCEVIEWER_STATE_PROP_SELECTED)); ui_button(win, .label = "Remove", .onclick = action_resourceviewer_property_remove, .groups = UI_GROUPS(RESOURCEVIEWER_STATE_PROP_SELECTED)); @@ -322,7 +323,7 @@ wdata->password = ui_string_new(obj->ctx, NULL); obj->window = wdata; - ui_grid(obj, .margin = 20, .columnspacing = 12, .rowspacing = 12) { + ui_grid(obj, .margin = 20, .columnspacing = 12, .rowspacing = 12, .fill = TRUE) { cxmutstr heading = cx_asprintf("Authentication required for: %s", auth->sn->base_url); ui_llabel(obj, .label = heading.ptr, .colspan = 2); free(heading.ptr);
--- a/configure Sat Apr 05 17:57:04 2025 +0200 +++ b/configure Sun Jul 20 22:04:39 2025 +0200 @@ -107,11 +107,11 @@ --localedir=DIR locale-dependent data [DATAROOTDIR/locale] Build Types: ---debug add extra compile flags for debug builds ---release add extra compile flags for release builds + --debug add extra compile flags for debug builds + --release add extra compile flags for release builds Options: - --toolkit=(libadwaita|gtk4|gtk3|gtk2|gtk2legacy|qt5|qt4|motif) + --toolkit=(libadwaita|gtk4|gtk3|cocoa|qt5|motif) __EOF__ } @@ -178,7 +178,7 @@ "--debug") BUILD_TYPE="debug" ;; "--release") BUILD_TYPE="release" ;; "--toolkit="*) OPT_TOOLKIT=${ARG#--toolkit=} ;; - "--toolkit") echo "option '$ARG' needs a value:"; echo " $ARG=(libadwaita|gtk4|gtk3|gtk2|gtk2legacy|qt5|qt4|motif)"; abort_configure ;; + "--toolkit") echo "option '$ARG' needs a value:"; echo " $ARG=(libadwaita|gtk4|gtk3|cocoa|qt5|motif)"; abort_configure ;; "-"*) echo "unknown option: $ARG"; abort_configure ;; esac done @@ -202,6 +202,22 @@ : ${mandir:='${datarootdir}/man'} : ${localedir:='${datarootdir}/locale'} +# remember the above values and compare them later +orig_bindir="$bindir" +orig_sbindir="$sbindir" +orig_libdir="$libdir" +orig_libexecdir="$libexecdir" +orig_datarootdir="$datarootdir" +orig_datadir="$datadir" +orig_sysconfdir="$sysconfdir" +orig_sharedstatedir="$sharedstatedir" +orig_localstatedir="$localstatedir" +orig_runstatedir="$runstatedir" +orig_includedir="$includedir" +orig_infodir="$infodir" +orig_mandir="$mandir" +orig_localedir="$localedir" + # check if a config.site exists and load it if [ -n "$CONFIG_SITE" ]; then # CONFIG_SITE may contain space separated file names @@ -251,6 +267,9 @@ # check languages lang_c= lang_cpp= +if detect_cpp_compiler ; then + lang_cpp=1 +fi if detect_c_compiler ; then lang_c=1 fi @@ -279,32 +298,6 @@ fi } -dependency_error_gtk2legacy() -{ - print_check_msg "$dep_checked_gtk2legacy" "checking for gtk2legacy... " - # dependency gtk2legacy - while true - do - if [ -z "$PKG_CONFIG" ]; then - break - fi - if test_pkg_config "gtk+-2.0" "" "" "" ; then - TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags gtk+-2.0`" - TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs gtk+-2.0`" - else - break - fi - TEMP_CFLAGS="$TEMP_CFLAGS -DUI_GTK2 -DUI_GTK2LEGACY" - TEMP_LDFLAGS="$TEMP_LDFLAGS -lpthread" - print_check_msg "$dep_checked_gtk2legacy" "yes\n" - dep_checked_gtk2legacy=1 - return 1 - done - - print_check_msg "$dep_checked_gtk2legacy" "no\n" - dep_checked_gtk2legacy=1 - return 0 -} dependency_error_curl() { print_check_msg "$dep_checked_curl" "checking for curl... " @@ -399,6 +392,31 @@ dep_checked_gtk2=1 return 0 } +dependency_error_sqlite() +{ + print_check_msg "$dep_checked_sqlite" "checking for sqlite... " + # dependency sqlite + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + if test_pkg_config "sqlite3" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags sqlite3`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs sqlite3`" + else + break + fi + TEMP_CFLAGS="$TEMP_CFLAGS -DDBU_SQLITE" + print_check_msg "$dep_checked_sqlite" "yes\n" + dep_checked_sqlite=1 + return 1 + done + + print_check_msg "$dep_checked_sqlite" "no\n" + dep_checked_sqlite=1 + return 0 +} dependency_error_gtk3() { print_check_msg "$dep_checked_gtk3" "checking for gtk3... " @@ -451,6 +469,277 @@ dep_checked_gtk4=1 return 0 } +dependency_error_webkitgtk6() +{ + print_check_msg "$dep_checked_webkitgtk6" "checking for webkitgtk6... " + # dependency webkitgtk6 + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + if test_pkg_config "webkitgtk-6.0" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags webkitgtk-6.0`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs webkitgtk-6.0`" + else + break + fi + TEMP_CFLAGS="$TEMP_CFLAGS -DUI_WEBVIEW" + print_check_msg "$dep_checked_webkitgtk6" "yes\n" + dep_checked_webkitgtk6=1 + return 1 + done + + # dependency webkitgtk6 + while true + do + print_check_msg "$dep_checked_webkitgtk6" "yes\n" + dep_checked_webkitgtk6=1 + return 1 + done + + print_check_msg "$dep_checked_webkitgtk6" "no\n" + dep_checked_webkitgtk6=1 + return 0 +} +dependency_error_libxml2() +{ + print_check_msg "$dep_checked_libxml2" "checking for libxml2... " + # dependency libxml2 platform="windows" + while true + do + if notisplatform "windows"; then + break + fi + if tmp_flags=`xml2-config --cflags` ; then + TEMP_CFLAGS="$TEMP_CFLAGS $tmp_flags" + else + break + fi + if tmp_flags=`xml2-config --libs` ; then + TEMP_LDFLAGS="$TEMP_LDFLAGS $tmp_flags" + else + break + fi + print_check_msg "$dep_checked_libxml2" "yes\n" + dep_checked_libxml2=1 + return 1 + done + + # dependency libxml2 platform="macos" + while true + do + if notisplatform "macos"; then + break + fi + if tmp_flags=`xml2-config --cflags` ; then + TEMP_CFLAGS="$TEMP_CFLAGS $tmp_flags" + else + break + fi + if tmp_flags=`xml2-config --libs` ; then + TEMP_LDFLAGS="$TEMP_LDFLAGS $tmp_flags" + else + break + fi + print_check_msg "$dep_checked_libxml2" "yes\n" + dep_checked_libxml2=1 + return 1 + done + + # dependency libxml2 + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + if test_pkg_config "libxml-2.0" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags libxml-2.0`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs libxml-2.0`" + else + break + fi + print_check_msg "$dep_checked_libxml2" "yes\n" + dep_checked_libxml2=1 + return 1 + done + + # dependency libxml2 + while true + do + if tmp_flags=`xml2-config --cflags` ; then + TEMP_CFLAGS="$TEMP_CFLAGS $tmp_flags" + else + break + fi + if tmp_flags=`xml2-config --libs` ; then + TEMP_LDFLAGS="$TEMP_LDFLAGS $tmp_flags" + else + break + fi + print_check_msg "$dep_checked_libxml2" "yes\n" + dep_checked_libxml2=1 + return 1 + done + + print_check_msg "$dep_checked_libxml2" "no\n" + dep_checked_libxml2=1 + return 0 +} +dependency_error_webkit2gtk4() +{ + print_check_msg "$dep_checked_webkit2gtk4" "checking for webkit2gtk4... " + # dependency webkit2gtk4 + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + if test_pkg_config "webkit2gtk-4.1" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags webkit2gtk-4.1`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs webkit2gtk-4.1`" + else + break + fi + TEMP_CFLAGS="$TEMP_CFLAGS -DUI_WEBVIEW" + print_check_msg "$dep_checked_webkit2gtk4" "yes\n" + dep_checked_webkit2gtk4=1 + return 1 + done + + # dependency webkit2gtk4 + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + if test_pkg_config "webkit2gtk-4.0" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags webkit2gtk-4.0`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs webkit2gtk-4.0`" + else + break + fi + TEMP_CFLAGS="$TEMP_CFLAGS -DUI_WEBVIEW" + print_check_msg "$dep_checked_webkit2gtk4" "yes\n" + dep_checked_webkit2gtk4=1 + return 1 + done + + # dependency webkit2gtk4 + while true + do + print_check_msg "$dep_checked_webkit2gtk4" "yes\n" + dep_checked_webkit2gtk4=1 + return 1 + done + + print_check_msg "$dep_checked_webkit2gtk4" "no\n" + dep_checked_webkit2gtk4=1 + return 0 +} +dependency_error_cocoa() +{ + print_check_msg "$dep_checked_cocoa" "checking for cocoa... " + # dependency cocoa platform="macos" + while true + do + if notisplatform "macos"; then + break + fi + TEMP_CFLAGS="$TEMP_CFLAGS -DUI_COCOA" + TEMP_LDFLAGS="$TEMP_LDFLAGS -lobjc -framework Cocoa" + print_check_msg "$dep_checked_cocoa" "yes\n" + dep_checked_cocoa=1 + return 1 + done + + print_check_msg "$dep_checked_cocoa" "no\n" + dep_checked_cocoa=1 + return 0 +} +dependency_error_winui() +{ + print_check_msg "$dep_checked_winui" "checking for winui... " + # dependency winui platform="windows" + while true + do + if notisplatform "windows"; then + break + fi + TEMP_CFLAGS="$TEMP_CFLAGS -DUI_WINUI" + print_check_msg "$dep_checked_winui" "yes\n" + dep_checked_winui=1 + return 1 + done + + print_check_msg "$dep_checked_winui" "no\n" + dep_checked_winui=1 + return 0 +} +dependency_error_gtk2legacy() +{ + print_check_msg "$dep_checked_gtk2legacy" "checking for gtk2legacy... " + # dependency gtk2legacy + while true + do + if [ -z "$PKG_CONFIG" ]; then + break + fi + if test_pkg_config "gtk+-2.0" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags gtk+-2.0`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs gtk+-2.0`" + else + break + fi + TEMP_CFLAGS="$TEMP_CFLAGS -DUI_GTK2 -DUI_GTK2LEGACY" + TEMP_LDFLAGS="$TEMP_LDFLAGS -lpthread" + print_check_msg "$dep_checked_gtk2legacy" "yes\n" + dep_checked_gtk2legacy=1 + return 1 + done + + print_check_msg "$dep_checked_gtk2legacy" "no\n" + dep_checked_gtk2legacy=1 + return 0 +} +dependency_error_qt5() +{ + print_check_msg "$dep_checked_qt5" "checking for qt5... " + # dependency qt5 + while true + do + if [ -z "$lang_cpp" ] ; then + break + fi + if [ -z "$PKG_CONFIG" ]; then + break + fi + if which qmake-qt5 > /dev/null ; then + : + else + break + fi + if test_pkg_config "Qt5Widgets" "" "" "" ; then + TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags Qt5Widgets`" + TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs Qt5Widgets`" + else + break + fi + TEMP_CFLAGS="$TEMP_CFLAGS -DUI_QT5" + cat >> $TEMP_DIR/make.mk << __EOF__ +# Dependency: qt5 +QMAKE = qmake-qt5 +QT_PRO_FILE = qt5.pro +__EOF__ + print_check_msg "$dep_checked_qt5" "yes\n" + dep_checked_qt5=1 + return 1 + done + + print_check_msg "$dep_checked_qt5" "no\n" + dep_checked_qt5=1 + return 0 +} dependency_error_openssl() { print_check_msg "$dep_checked_openssl" "checking for openssl... " @@ -570,129 +859,6 @@ dep_checked_motif=1 return 0 } -dependency_error_libxml2() -{ - print_check_msg "$dep_checked_libxml2" "checking for libxml2... " - # dependency libxml2 platform="windows" - while true - do - if notisplatform "windows"; then - break - fi - if tmp_flags=`xml2-config --cflags` ; then - TEMP_CFLAGS="$TEMP_CFLAGS $tmp_flags" - else - break - fi - if tmp_flags=`xml2-config --libs` ; then - TEMP_LDFLAGS="$TEMP_LDFLAGS $tmp_flags" - else - break - fi - print_check_msg "$dep_checked_libxml2" "yes\n" - dep_checked_libxml2=1 - return 1 - done - - # dependency libxml2 platform="macos" - while true - do - if notisplatform "macos"; then - break - fi - if tmp_flags=`xml2-config --cflags` ; then - TEMP_CFLAGS="$TEMP_CFLAGS $tmp_flags" - else - break - fi - if tmp_flags=`xml2-config --libs` ; then - TEMP_LDFLAGS="$TEMP_LDFLAGS $tmp_flags" - else - break - fi - print_check_msg "$dep_checked_libxml2" "yes\n" - dep_checked_libxml2=1 - return 1 - done - - # dependency libxml2 - while true - do - if [ -z "$PKG_CONFIG" ]; then - break - fi - if test_pkg_config "libxml-2.0" "" "" "" ; then - TEMP_CFLAGS="$TEMP_CFLAGS `"$PKG_CONFIG" --cflags libxml-2.0`" - TEMP_LDFLAGS="$TEMP_LDFLAGS `"$PKG_CONFIG" --libs libxml-2.0`" - else - break - fi - print_check_msg "$dep_checked_libxml2" "yes\n" - dep_checked_libxml2=1 - return 1 - done - - # dependency libxml2 - while true - do - if tmp_flags=`xml2-config --cflags` ; then - TEMP_CFLAGS="$TEMP_CFLAGS $tmp_flags" - else - break - fi - if tmp_flags=`xml2-config --libs` ; then - TEMP_LDFLAGS="$TEMP_LDFLAGS $tmp_flags" - else - break - fi - print_check_msg "$dep_checked_libxml2" "yes\n" - dep_checked_libxml2=1 - return 1 - done - - print_check_msg "$dep_checked_libxml2" "no\n" - dep_checked_libxml2=1 - return 0 -} -dependency_error_cocoa() -{ - print_check_msg "$dep_checked_cocoa" "checking for cocoa... " - # dependency cocoa platform="macos" - while true - do - if notisplatform "macos"; then - break - fi - TEMP_CFLAGS="$TEMP_CFLAGS -DUI_COCOA" - TEMP_LDFLAGS="$TEMP_LDFLAGS -lobjc -framework Cocoa" - print_check_msg "$dep_checked_cocoa" "yes\n" - dep_checked_cocoa=1 - return 1 - done - - print_check_msg "$dep_checked_cocoa" "no\n" - dep_checked_cocoa=1 - return 0 -} -dependency_error_winui() -{ - print_check_msg "$dep_checked_winui" "checking for winui... " - # dependency winui platform="windows" - while true - do - if notisplatform "windows"; then - break - fi - TEMP_CFLAGS="$TEMP_CFLAGS -DUI_WINUI" - print_check_msg "$dep_checked_winui" "yes\n" - dep_checked_winui=1 - return 1 - done - - print_check_msg "$dep_checked_winui" "no\n" - dep_checked_winui=1 - return 0 -} # start collecting dependency information echo > "$TEMP_DIR/flags.mk" @@ -712,6 +878,9 @@ break fi + cat >> "$TEMP_DIR/make.mk" << __EOF__ +LD = \$(CC) +__EOF__ break done break @@ -727,6 +896,7 @@ cat >> "$TEMP_DIR/make.mk" << __EOF__ OBJ_EXT = .o LIB_EXT = .a +SHLIB_EXT = .dylib LIB_PREFIX = lib PACKAGE_SCRIPT = package_osx.sh __EOF__ @@ -748,6 +918,7 @@ cat >> "$TEMP_DIR/make.mk" << __EOF__ OBJ_EXT = .o LIB_EXT = .a +SHLIB_EXT = .so LIB_PREFIX = lib PACKAGE_SCRIPT = package_unix.sh __EOF__ @@ -757,6 +928,19 @@ done while true do + while true + do + + cat >> "$TEMP_DIR/make.mk" << __EOF__ +BUILD_BIN_DIR = bin +BUILD_LIB_DIR = lib +__EOF__ + break + done + break +done +while true +do if notisplatform "bsd"; then break fi @@ -770,6 +954,16 @@ break done +# build type +if [ "$BUILD_TYPE" = "debug" ]; then + TEMP_CFLAGS="\${DEBUG_CC_FLAGS} $TEMP_CFLAGS" + TEMP_CXXFLAGS="\${DEBUG_CXX_FLAGS} $TEMP_CXXFLAGS" +fi +if [ "$BUILD_TYPE" = "release" ]; then + TEMP_CFLAGS="\${RELEASE_CC_FLAGS} $TEMP_CFLAGS" + TEMP_CXXFLAGS="\${RELEASE_CXX_FLAGS} $TEMP_CXXFLAGS" +fi + # add general dependency flags to flags.mk echo "# general flags" >> "$TEMP_DIR/flags.mk" if [ -n "${TEMP_CFLAGS}" ] && [ -n "$lang_c" ]; then @@ -791,12 +985,17 @@ if dependency_error_libadwaita ; then VERR=1 fi + if dependency_error_webkitgtk6 ; then + VERR=1 + fi if [ $VERR -ne 0 ]; then return 1 fi cat >> "$TEMP_DIR/make.mk" << __EOF__ TOOLKIT = gtk GTKOBJ = draw_cairo.o +APP_PLATFORM_SRC = gtk-text.c +APP_PLATFORM_SRC += gtk-image.c __EOF__ return 0 } @@ -806,12 +1005,17 @@ if dependency_error_gtk4 ; then VERR=1 fi + if dependency_error_webkitgtk6 ; then + VERR=1 + fi if [ $VERR -ne 0 ]; then return 1 fi cat >> "$TEMP_DIR/make.mk" << __EOF__ TOOLKIT = gtk GTKOBJ = draw_cairo.o +APP_PLATFORM_SRC = gtk-text.c +APP_PLATFORM_SRC += gtk-image.c __EOF__ return 0 } @@ -821,19 +1025,7 @@ if dependency_error_gtk3 ; then VERR=1 fi - if [ $VERR -ne 0 ]; then - return 1 - fi - cat >> "$TEMP_DIR/make.mk" << __EOF__ -TOOLKIT = gtk -GTKOBJ = draw_cairo.o -__EOF__ - return 0 -} -checkopt_toolkit_gtk2() -{ - VERR=0 - if dependency_error_gtk2 ; then + if dependency_error_webkit2gtk4 ; then VERR=1 fi if [ $VERR -ne 0 ]; then @@ -842,21 +1034,24 @@ cat >> "$TEMP_DIR/make.mk" << __EOF__ TOOLKIT = gtk GTKOBJ = draw_cairo.o +GTKOBJ = draw_cairo.o +APP_PLATFORM_SRC = gtk-text.c +APP_PLATFORM_SRC += gtk-image.c __EOF__ return 0 } -checkopt_toolkit_gtk2legacy() +checkopt_toolkit_cocoa() { VERR=0 - if dependency_error_gtk2legacy ; then + if dependency_error_cocoa ; then VERR=1 fi if [ $VERR -ne 0 ]; then return 1 fi cat >> "$TEMP_DIR/make.mk" << __EOF__ -TOOLKIT = gtk -GTKOBJ = draw_gdk.o +TOOLKIT = cocoa +APP_PLATFORM_SRC = cocoa-text.m __EOF__ return 0 } @@ -871,22 +1066,7 @@ fi cat >> "$TEMP_DIR/make.mk" << __EOF__ TOOLKIT = qt -LD = $(CXX) -__EOF__ - return 0 -} -checkopt_toolkit_qt4() -{ - VERR=0 - if dependency_error_qt4 ; then - VERR=1 - fi - if [ $VERR -ne 0 ]; then - return 1 - fi - cat >> "$TEMP_DIR/make.mk" << __EOF__ -TOOLKIT = qt -LD = $(CXX) +LD = \$(CXX) __EOF__ return 0 } @@ -938,24 +1118,33 @@ if [ -n "${TEMP_CXXFLAGS}" ] && [ -n "$lang_cpp" ]; then echo "DAV_CXXFLAGS += $TEMP_CXXFLAGS" >> "$TEMP_DIR/flags.mk" fi -if [ "$BUILD_TYPE" = "debug" ]; then - if [ -n "$lang_c" ]; then - echo 'DAV_CFLAGS += ${DEBUG_CC_FLAGS}' >> "$TEMP_DIR/flags.mk" - fi - if [ -n "$lang_cpp" ]; then - echo 'DAV_CXXFLAGS += ${DEBUG_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk" - fi +if [ -n "${TEMP_LDFLAGS}" ]; then + echo "DAV_LDFLAGS += $TEMP_LDFLAGS" >> "$TEMP_DIR/flags.mk" fi -if [ "$BUILD_TYPE" = "release" ]; then - if [ -n "$lang_c" ]; then - echo 'DAV_CFLAGS += ${RELEASE_CC_FLAGS}' >> "$TEMP_DIR/flags.mk" - fi - if [ -n "$lang_cpp" ]; then - echo 'DAV_CXXFLAGS += ${RELEASE_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk" - fi + +echo >> "$TEMP_DIR/flags.mk" +echo "configuring target: dbu" +echo "# flags for target dbu" >> "$TEMP_DIR/flags.mk" +TEMP_CFLAGS= +TEMP_CXXFLAGS= +TEMP_LDFLAGS= + +if dependency_error_sqlite; then + DEPENDENCIES_FAILED="$DEPENDENCIES_FAILED sqlite " + ERROR=1 +fi + +# Features + + +if [ -n "${TEMP_CFLAGS}" ] && [ -n "$lang_c" ]; then + echo "DBU_CFLAGS += $TEMP_CFLAGS" >> "$TEMP_DIR/flags.mk" +fi +if [ -n "${TEMP_CXXFLAGS}" ] && [ -n "$lang_cpp" ]; then + echo "DBU_CXXFLAGS += $TEMP_CXXFLAGS" >> "$TEMP_DIR/flags.mk" fi if [ -n "${TEMP_LDFLAGS}" ]; then - echo "DAV_LDFLAGS += $TEMP_LDFLAGS" >> "$TEMP_DIR/flags.mk" + echo "DBU_LDFLAGS += $TEMP_LDFLAGS" >> "$TEMP_DIR/flags.mk" fi echo >> "$TEMP_DIR/flags.mk" @@ -990,6 +1179,11 @@ break fi fi + if checkopt_toolkit_libadwaita ; then + echo " toolkit: libadwaita" >> "$TEMP_DIR/options" + ERROR=0 + break + fi if checkopt_toolkit_gtk4 ; then echo " toolkit: gtk4" >> "$TEMP_DIR/options" ERROR=0 @@ -1000,21 +1194,6 @@ ERROR=0 break fi - if checkopt_toolkit_qt5 ; then - echo " toolkit: qt5" >> "$TEMP_DIR/options" - ERROR=0 - break - fi - if checkopt_toolkit_gtk2 ; then - echo " toolkit: gtk2" >> "$TEMP_DIR/options" - ERROR=0 - break - fi - if checkopt_toolkit_qt4 ; then - echo " toolkit: qt4" >> "$TEMP_DIR/options" - ERROR=0 - break - fi if checkopt_toolkit_motif ; then echo " toolkit: motif" >> "$TEMP_DIR/options" ERROR=0 @@ -1056,17 +1235,9 @@ ERROR=1 DEPENDENCIES_FAILED="option 'toolkit' $DEPENDENCIES_FAILED" fi - elif [ "$OPT_TOOLKIT" = "gtk2" ]; then + elif [ "$OPT_TOOLKIT" = "cocoa" ]; then echo " toolkit: $OPT_TOOLKIT" >> $TEMP_DIR/options - if checkopt_toolkit_gtk2 ; then - : - else - ERROR=1 - DEPENDENCIES_FAILED="option 'toolkit' $DEPENDENCIES_FAILED" - fi - elif [ "$OPT_TOOLKIT" = "gtk2legacy" ]; then - echo " toolkit: $OPT_TOOLKIT" >> $TEMP_DIR/options - if checkopt_toolkit_gtk2legacy ; then + if checkopt_toolkit_cocoa ; then : else ERROR=1 @@ -1080,14 +1251,6 @@ ERROR=1 DEPENDENCIES_FAILED="option 'toolkit' $DEPENDENCIES_FAILED" fi - elif [ "$OPT_TOOLKIT" = "qt4" ]; then - echo " toolkit: $OPT_TOOLKIT" >> $TEMP_DIR/options - if checkopt_toolkit_qt4 ; then - : - else - ERROR=1 - DEPENDENCIES_FAILED="option 'toolkit' $DEPENDENCIES_FAILED" - fi elif [ "$OPT_TOOLKIT" = "motif" ]; then echo " toolkit: $OPT_TOOLKIT" >> $TEMP_DIR/options if checkopt_toolkit_motif ; then @@ -1099,7 +1262,7 @@ else echo echo "Invalid option value - usage:" - echo " --toolkit=(libadwaita|gtk4|gtk3|gtk2|gtk2legacy|qt5|qt4|motif)" + echo " --toolkit=(libadwaita|gtk4|gtk3|cocoa|qt5|motif)" abort_configure fi fi @@ -1110,22 +1273,6 @@ if [ -n "${TEMP_CXXFLAGS}" ] && [ -n "$lang_cpp" ]; then echo "TK_CXXFLAGS += $TEMP_CXXFLAGS" >> "$TEMP_DIR/flags.mk" fi -if [ "$BUILD_TYPE" = "debug" ]; then - if [ -n "$lang_c" ]; then - echo 'TK_CFLAGS += ${DEBUG_CC_FLAGS}' >> "$TEMP_DIR/flags.mk" - fi - if [ -n "$lang_cpp" ]; then - echo 'TK_CXXFLAGS += ${DEBUG_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk" - fi -fi -if [ "$BUILD_TYPE" = "release" ]; then - if [ -n "$lang_c" ]; then - echo 'TK_CFLAGS += ${RELEASE_CC_FLAGS}' >> "$TEMP_DIR/flags.mk" - fi - if [ -n "$lang_cpp" ]; then - echo 'TK_CXXFLAGS += ${RELEASE_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk" - fi -fi if [ -n "${TEMP_LDFLAGS}" ]; then echo "TK_LDFLAGS += $TEMP_LDFLAGS" >> "$TEMP_DIR/flags.mk" fi @@ -1141,20 +1288,81 @@ echo "configure finished" echo +echo "Toolchain" +echo " name: $TOOLCHAIN_NAME" +if [ -n "$TOOLCHAIN_CC" ]; then + echo " cc: $TOOLCHAIN_CC" +fi +if [ -n "$TOOLCHAIN_CXX" ]; then + echo " cxx: $TOOLCHAIN_CXX" +fi +if [ -n "$TOOLCHAIN_WSIZE" ]; then + echo " word size: $TOOLCHAIN_WSIZE bit" +fi +if [ -n "$TOOLCHAIN_CSTD" ]; then + echo " default C std: $TOOLCHAIN_CSTD" +fi +echo echo "Build Config:" -echo " PREFIX: $prefix" -echo " TOOLCHAIN: $TOOLCHAIN_NAME" +echo " prefix: $prefix" +echo " exec_prefix: $exec_prefix" +if [ "$orig_bindir" != "$bindir" ]; then + echo " bindir: $bindir" +fi +if [ "$orig_sbindir" != "$sbindir" ]; then + echo " sbindir: $sbindir" +fi +if [ "$orig_libdir" != "$libdir" ]; then + echo " libdir: $libdir" +fi +if [ "$orig_libexecdir" != "$libexecdir" ]; then + echo " libexecdir: $libexecdir" +fi +if [ "$orig_datarootdir" != "$datarootdir" ]; then + echo " datarootdir: $datarootdir" +fi +if [ "$orig_datadir" != "$datadir" ]; then + echo " datadir: $datadir" +fi +if [ "$orig_sysconfdir" != "$sysconfdir" ]; then + echo " sysconfdir: $sysconfdir" +fi +if [ "$orig_sharedstatedir" != "$sharedstatedir" ]; then + echo " sharedstatedir: $sharedstatedir" +fi +if [ "$orig_localstatedir" != "$localstatedir" ]; then + echo " localstatedir: $localstatedir" +fi +if [ "$orig_runstatedir" != "$runstatedir" ]; then + echo " runstatedir: $runstatedir" +fi +if [ "$orig_includedir" != "$includedir" ]; then + echo " includedir: $includedir" +fi +if [ "$orig_infodir" != "$infodir" ]; then + echo " infodir: $infodir" +fi +if [ "$orig_mandir" != "$mandir" ]; then + echo " mandir: $mandir" +fi +if [ "$orig_localedir" != "$localedir" ]; then + echo " localedir: $localedir" +fi +echo echo "Options:" cat "$TEMP_DIR/options" echo # generate the config.mk file +pwd=`pwd` cat > "$TEMP_DIR/config.mk" << __EOF__ # -# config.mk generated by configure +# config.mk generated by: +# pwd: $pwd +# $0 $@ # __EOF__ write_toolchain_defaults "$TEMP_DIR/toolchain.mk" -cat "$TEMP_DIR/vars.mk" "$TEMP_DIR/toolchain.mk" "$TEMP_DIR/flags.mk" "$TEMP_DIR/make.mk" > config.mk +cat "$TEMP_DIR/config.mk" "$TEMP_DIR/vars.mk" "$TEMP_DIR/toolchain.mk" "$TEMP_DIR/flags.mk" "$TEMP_DIR/make.mk" > config.mk rm -Rf "$TEMP_DIR"
--- a/libidav/config.c Sat Apr 05 17:57:04 2025 +0200 +++ b/libidav/config.c Sun Jul 20 22:04:39 2025 +0200 @@ -198,7 +198,7 @@ DavConfig* dav_config_new(xmlDoc *doc) { - CxMempool *cfg_mp = cxMempoolCreate(128, NULL); + CxMempool *cfg_mp = cxMempoolCreateSimple(128); DavConfig *config = cxMalloc(cfg_mp->allocator, sizeof(DavConfig)); memset(config, 0, sizeof(DavConfig)); config->mp = cfg_mp;
--- a/libidav/resource.c Sat Apr 05 17:57:04 2025 +0200 +++ b/libidav/resource.c Sun Jul 20 22:04:39 2025 +0200 @@ -786,7 +786,7 @@ } int dav_load_prop(DavResource *res, DavPropName *properties, size_t numprop) { - CxMempool *mp = cxMempoolCreate(64, NULL); + CxMempool *mp = cxMempoolCreateSimple(64); const CxAllocator *a = mp->allocator; CxList *proplist = cxArrayListCreate(a, NULL, sizeof(DavProperty), numprop);
--- a/make/configure.vm Sat Apr 05 17:57:04 2025 +0200 +++ b/make/configure.vm Sun Jul 20 22:04:39 2025 +0200 @@ -108,8 +108,8 @@ --localedir=DIR locale-dependent data [DATAROOTDIR/locale] Build Types: ---debug add extra compile flags for debug builds ---release add extra compile flags for release builds + --debug add extra compile flags for debug builds + --release add extra compile flags for release builds #if( $options.size() > 0 ) Options: @@ -244,6 +244,22 @@ : ${mandir:='${datarootdir}/man'} : ${localedir:='${datarootdir}/locale'} +# remember the above values and compare them later +orig_bindir="$bindir" +orig_sbindir="$sbindir" +orig_libdir="$libdir" +orig_libexecdir="$libexecdir" +orig_datarootdir="$datarootdir" +orig_datadir="$datadir" +orig_sysconfdir="$sysconfdir" +orig_sharedstatedir="$sharedstatedir" +orig_localstatedir="$localstatedir" +orig_runstatedir="$runstatedir" +orig_includedir="$includedir" +orig_infodir="$infodir" +orig_mandir="$mandir" +orig_localedir="$localedir" + # check if a config.site exists and load it if [ -n "$CONFIG_SITE" ]; then # CONFIG_SITE may contain space separated file names @@ -485,6 +501,16 @@ done #end +# build type +if [ "$BUILD_TYPE" = "debug" ]; then + TEMP_CFLAGS="\${DEBUG_CC_FLAGS} $TEMP_CFLAGS" + TEMP_CXXFLAGS="\${DEBUG_CXX_FLAGS} $TEMP_CXXFLAGS" +fi +if [ "$BUILD_TYPE" = "release" ]; then + TEMP_CFLAGS="\${RELEASE_CC_FLAGS} $TEMP_CFLAGS" + TEMP_CXXFLAGS="\${RELEASE_CXX_FLAGS} $TEMP_CXXFLAGS" +fi + # add general dependency flags to flags.mk echo "# general flags" >> "$TEMP_DIR/flags.mk" if [ -n "${TEMP_CFLAGS}" ] && [ -n "$lang_c" ]; then @@ -661,22 +687,6 @@ if [ -n "${TEMP_CXXFLAGS}" ] && [ -n "$lang_cpp" ]; then echo "${target.cxxFlags} += $TEMP_CXXFLAGS" >> "$TEMP_DIR/flags.mk" fi -if [ "$BUILD_TYPE" = "debug" ]; then - if [ -n "$lang_c" ]; then - echo '${target.cFlags} += ${DEBUG_CC_FLAGS}' >> "$TEMP_DIR/flags.mk" - fi - if [ -n "$lang_cpp" ]; then - echo '${target.cxxFlags} += ${DEBUG_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk" - fi -fi -if [ "$BUILD_TYPE" = "release" ]; then - if [ -n "$lang_c" ]; then - echo '${target.cFlags} += ${RELEASE_CC_FLAGS}' >> "$TEMP_DIR/flags.mk" - fi - if [ -n "$lang_cpp" ]; then - echo '${target.cxxFlags} += ${RELEASE_CXX_FLAGS}' >> "$TEMP_DIR/flags.mk" - fi -fi if [ -n "${TEMP_LDFLAGS}" ]; then echo "${target.ldFlags} += $TEMP_LDFLAGS" >> "$TEMP_DIR/flags.mk" fi @@ -693,14 +703,73 @@ echo "configure finished" echo +echo "Toolchain" +echo " name: $TOOLCHAIN_NAME" +if [ -n "$TOOLCHAIN_CC" ]; then + echo " cc: $TOOLCHAIN_CC" +fi +if [ -n "$TOOLCHAIN_CXX" ]; then + echo " cxx: $TOOLCHAIN_CXX" +fi +if [ -n "$TOOLCHAIN_WSIZE" ]; then + echo " word size: $TOOLCHAIN_WSIZE bit" +fi +if [ -n "$TOOLCHAIN_CSTD" ]; then + echo " default C std: $TOOLCHAIN_CSTD" +fi +echo echo "Build Config:" -echo " PREFIX: $prefix" -echo " TOOLCHAIN: $TOOLCHAIN_NAME" +echo " prefix: $prefix" +echo " exec_prefix: $exec_prefix" +if [ "$orig_bindir" != "$bindir" ]; then + echo " bindir: $bindir" +fi +if [ "$orig_sbindir" != "$sbindir" ]; then + echo " sbindir: $sbindir" +fi +if [ "$orig_libdir" != "$libdir" ]; then + echo " libdir: $libdir" +fi +if [ "$orig_libexecdir" != "$libexecdir" ]; then + echo " libexecdir: $libexecdir" +fi +if [ "$orig_datarootdir" != "$datarootdir" ]; then + echo " datarootdir: $datarootdir" +fi +if [ "$orig_datadir" != "$datadir" ]; then + echo " datadir: $datadir" +fi +if [ "$orig_sysconfdir" != "$sysconfdir" ]; then + echo " sysconfdir: $sysconfdir" +fi +if [ "$orig_sharedstatedir" != "$sharedstatedir" ]; then + echo " sharedstatedir: $sharedstatedir" +fi +if [ "$orig_localstatedir" != "$localstatedir" ]; then + echo " localstatedir: $localstatedir" +fi +if [ "$orig_runstatedir" != "$runstatedir" ]; then + echo " runstatedir: $runstatedir" +fi +if [ "$orig_includedir" != "$includedir" ]; then + echo " includedir: $includedir" +fi +if [ "$orig_infodir" != "$infodir" ]; then + echo " infodir: $infodir" +fi +if [ "$orig_mandir" != "$mandir" ]; then + echo " mandir: $mandir" +fi +if [ "$orig_localedir" != "$localedir" ]; then + echo " localedir: $localedir" +fi #if ( $options.size() > 0 ) +echo echo "Options:" cat "$TEMP_DIR/options" #end #if ( $features.size() > 0 ) +echo echo "Features:" #foreach( $feature in $features ) if [ -n "${D}${feature.varName}" ]; then @@ -713,12 +782,15 @@ echo # generate the config.mk file +pwd=`pwd` cat > "$TEMP_DIR/config.mk" << __EOF__ # -# config.mk generated by configure +# config.mk generated by: +# pwd: $pwd +# $0 $@ # __EOF__ write_toolchain_defaults "$TEMP_DIR/toolchain.mk" -cat "$TEMP_DIR/vars.mk" "$TEMP_DIR/toolchain.mk" "$TEMP_DIR/flags.mk" "$TEMP_DIR/make.mk" > config.mk +cat "$TEMP_DIR/config.mk" "$TEMP_DIR/vars.mk" "$TEMP_DIR/toolchain.mk" "$TEMP_DIR/flags.mk" "$TEMP_DIR/make.mk" > config.mk rm -Rf "$TEMP_DIR"
--- a/make/project.xml Sat Apr 05 17:57:04 2025 +0200 +++ b/make/project.xml Sun Jul 20 22:04:39 2025 +0200 @@ -2,6 +2,7 @@ <project version="0.3" xmlns="http://unixwork.de/uwproj"> <dependency> <lang>c</lang> + <make>LD = \$(CC)</make> </dependency> <dependency name="curl" platform="macos"> @@ -16,6 +17,11 @@ <ldflags exec="true">curl-config --libs</ldflags> </dependency> + <dependency name="sqlite"> + <pkgconfig>sqlite3</pkgconfig> + <cflags>-DDBU_SQLITE</cflags> + </dependency> + <dependency name="libxml2" platform="windows"> <cflags exec="true">xml2-config --cflags</cflags> <ldflags exec="true">xml2-config --libs</ldflags> @@ -75,21 +81,34 @@ <cflags>-DUI_WINUI</cflags> </dependency> - <!-- - <dependency name="qt4"> - <test>which qmake-qt4</test> - <cflags exec="true">qmake-qt4 -o - /dev/null | grep DEFINES\ </cflags> - <cflags exec="true">qmake-qt4 -o - /dev/null | grep INCPATH\ </cflags> - <ldflags exec="true">qmake-qt4 -o - /dev/null | grep LIBS\ </ldflags> + <dependency name="webkitgtk6"> + <pkgconfig>webkitgtk-6.0</pkgconfig> + <cflags>-DUI_WEBVIEW</cflags> + </dependency> + <dependency name="webkitgtk6"> + <!-- webview unsupported --> + </dependency> + <dependency name="webkit2gtk4"> + <pkgconfig>webkit2gtk-4.1</pkgconfig> + <cflags>-DUI_WEBVIEW</cflags> + </dependency> + <dependency name="webkit2gtk4"> + <pkgconfig>webkit2gtk-4.0</pkgconfig> + <cflags>-DUI_WEBVIEW</cflags> + </dependency> + <dependency name="webkit2gtk4"> + <!-- webview unsupported --> </dependency> <dependency name="qt5"> <test>which qmake-qt5</test> - <cflags exec="true">qmake-qt5 -o - /dev/null | grep DEFINES\ </cflags> - <cflags exec="true">qmake-qt5 -o - /dev/null | grep INCPATH\ </cflags> - <ldflags exec="true">qmake-qt5 -o - /dev/null | grep LIBS\ </ldflags> + <lang>cpp</lang> + <cflags>-DUI_QT5</cflags> + <pkgconfig>Qt5Widgets</pkgconfig> + <make>QMAKE = qmake-qt5</make> + <make>QT_PRO_FILE = qt5.pro</make> </dependency> - --> + <dependency name="cocoa" platform="macos"> <cflags>-DUI_COCOA</cflags> <ldflags>-lobjc -framework Cocoa</ldflags> @@ -108,15 +127,21 @@ <dependency platform="macos"> <make>OBJ_EXT = .o</make> <make>LIB_EXT = .a</make> + <make>SHLIB_EXT = .dylib</make> <make>LIB_PREFIX = lib</make> <make>PACKAGE_SCRIPT = package_osx.sh</make> </dependency> <dependency platform="unix" not="macos"> <make>OBJ_EXT = .o</make> <make>LIB_EXT = .a</make> + <make>SHLIB_EXT = .so</make> <make>LIB_PREFIX = lib</make> <make>PACKAGE_SCRIPT = package_unix.sh</make> </dependency> + <dependency> + <make>BUILD_BIN_DIR = bin</make> + <make>BUILD_LIB_DIR = lib</make> + </dependency> <dependency platform="bsd"> <cflags>-I/usr/local/include</cflags> @@ -127,42 +152,43 @@ <dependencies>curl,libxml2,openssl</dependencies> </target> + <target name="dbu"> + <dependencies>sqlite</dependencies> + </target> + <target name="tk"> <option arg="toolkit"> <value str="libadwaita"> - <dependencies>libadwaita</dependencies> + <dependencies>libadwaita,webkitgtk6</dependencies> <make>TOOLKIT = gtk</make> <make>GTKOBJ = draw_cairo.o</make> + <make>APP_PLATFORM_SRC = gtk-text.c</make> + <make>APP_PLATFORM_SRC += gtk-image.c</make> </value> <value str="gtk4"> - <dependencies>gtk4</dependencies> + <dependencies>gtk4,webkitgtk6</dependencies> <make>TOOLKIT = gtk</make> <make>GTKOBJ = draw_cairo.o</make> + <make>APP_PLATFORM_SRC = gtk-text.c</make> + <make>APP_PLATFORM_SRC += gtk-image.c</make> </value> <value str="gtk3"> - <dependencies>gtk3</dependencies> + <dependencies>gtk3,webkit2gtk4</dependencies> <make>TOOLKIT = gtk</make> <make>GTKOBJ = draw_cairo.o</make> + <make>GTKOBJ = draw_cairo.o</make> + <make>APP_PLATFORM_SRC = gtk-text.c</make> + <make>APP_PLATFORM_SRC += gtk-image.c</make> </value> - <value str="gtk2"> - <dependencies>gtk2</dependencies> - <make>TOOLKIT = gtk</make> - <make>GTKOBJ = draw_cairo.o</make> - </value> - <value str="gtk2legacy"> - <dependencies>gtk2legacy</dependencies> - <make>TOOLKIT = gtk</make> - <make>GTKOBJ = draw_gdk.o</make> + <value str="cocoa"> + <dependencies>cocoa</dependencies> + <make>TOOLKIT = cocoa</make> + <make>APP_PLATFORM_SRC = cocoa-text.m</make> </value> <value str="qt5"> <dependencies>qt5</dependencies> <make>TOOLKIT = qt</make> - <make>LD = $(CXX)</make> - </value> - <value str="qt4"> - <dependencies>qt4</dependencies> - <make>TOOLKIT = qt</make> - <make>LD = $(CXX)</make> + <make>LD = \$(CXX)</make> </value> <value str="motif"> <dependencies>motif</dependencies> @@ -170,12 +196,15 @@ </value> <default value="winui" platform="windows" /> <default value="cocoa" platform="macos" /> + <default value="libadwaita" /> <default value="gtk4" /> <default value="gtk3" /> + <default value="motif" /> + <!-- <default value="qt5" /> <default value="gtk2" /> <default value="qt4" /> - <default value="motif" /> + --> </option> </target> </project>
--- a/make/toolchain.sh Sat Apr 05 17:57:04 2025 +0200 +++ b/make/toolchain.sh Sun Jul 20 22:04:39 2025 +0200 @@ -17,20 +17,28 @@ check_c_compiler() { + command -v $1 2>&1 >/dev/null + if [ $? -ne 0 ]; then + return 1 + fi cat > "$TEMP_DIR/test.c" << __EOF__ /* test file */ #include <stdio.h> int main(int argc, char **argv) { #if defined(_MSC_VER) - printf("msc\n"); + printf("toolchain:msc\n"); #elif defined(__clang__) - printf("clang gnuc\n"); + printf("toolchain:clang gnuc\n"); #elif defined(__GNUC__) - printf("gcc gnuc\n"); + printf("toolchain:gcc gnuc\n"); #elif defined(__sun) - printf("suncc\n"); + printf("toolchain:suncc\n"); #else - printf("unknown\n"); + printf("toolchain:unknown\n"); +#endif + printf("wsize:%d\n", (int)sizeof(void*)*8); +#ifdef __STDC_VERSION__ + printf("stdcversion:%d\n", __STDC_VERSION__); #endif return 0; } @@ -41,21 +49,26 @@ check_cpp_compiler() { + command -v $1 2>&1 >/dev/null + if [ $? -ne 0 ]; then + return 1 + fi cat > "$TEMP_DIR/test.cpp" << __EOF__ /* test file */ #include <iostream> int main(int argc, char **argv) { #if defined(_MSC_VER) - std::cout << "msc" << std::endl; + std::cout << "toolchain:msc" << std::endl; #elif defined(__clang__) - std::cout << "clang gnuc" << std::endl; + std::cout << "toolchain:clang gnuc" << std::endl; #elif defined(__GNUC__) - std::cout << "gcc gnuc" << std::endl; + std::cout << "toolchain:gcc gnuc" << std::endl; #elif defined(__sun) - std::cout << "suncc" << std::endl; + std::cout << "toolchain:suncc" << std::endl; #else - std::cout << "cc" << std::endl; + std::cout << "toolchain:unknown" << std::endl; #endif + std::cout << "wsize:" << sizeof(void*)*8 << std::endl; return 0; } __EOF__ @@ -113,6 +126,14 @@ fi } +parse_toolchain_properties() +{ + info_file="$1" + TOOLCHAIN=`grep '^toolchain:' "$info_file" | tail -c +11` + TOOLCHAIN_NAME=`echo "$TOOLCHAIN" | cut -f1 -d' ' -` + TOOLCHAIN_WSIZE=`grep '^wsize:' "$info_file" | tail -c +7` +} + detect_c_compiler() { if [ -n "$TOOLCHAIN_CC" ]; then @@ -122,8 +143,9 @@ if [ -n "$CC" ]; then if check_c_compiler "$CC"; then TOOLCHAIN_CC=$CC - TOOLCHAIN=`"$TEMP_DIR/checkcc"` - TOOLCHAIN_NAME=`echo "$TOOLCHAIN" | cut -f1 -d' ' -` + "$TEMP_DIR/checkcc" > "$TEMP_DIR/checkcc_out" + parse_toolchain_properties "$TEMP_DIR/checkcc_out" + TOOLCHAIN_CSTD=`grep '^stdcversion:' "$TEMP_DIR/checkcc_out" | tail -c +13` echo "$CC" return 0 else @@ -135,8 +157,9 @@ do if check_c_compiler "$COMP"; then TOOLCHAIN_CC=$COMP - TOOLCHAIN=`"$TEMP_DIR/checkcc"` - TOOLCHAIN_NAME=`echo "$TOOLCHAIN" | cut -f1 -d' ' -` + "$TEMP_DIR/checkcc" > "$TEMP_DIR/checkcc_out" + parse_toolchain_properties "$TEMP_DIR/checkcc_out" + TOOLCHAIN_CSTD=`grep '^stdcversion:' "$TEMP_DIR/checkcc_out" | tail -c +13` echo "$COMP" return 0 fi @@ -156,8 +179,8 @@ if [ -n "$CXX" ]; then if check_cpp_compiler "$CXX"; then TOOLCHAIN_CXX=$CXX - TOOLCHAIN=`"$TEMP_DIR/checkcc"` - TOOLCHAIN_NAME=`echo "$TOOLCHAIN" | cut -f1 -d' ' -` + "$TEMP_DIR/checkcc" > "$TEMP_DIR/checkcc_out" + parse_toolchain_properties "$TEMP_DIR/checkcc_out" echo "$CXX" return 0 else @@ -169,8 +192,8 @@ do if check_cpp_compiler "$COMP"; then TOOLCHAIN_CXX=$COMP - TOOLCHAIN=`"$TEMP_DIR/checkcc"` - TOOLCHAIN_NAME=`echo "$TOOLCHAIN" | cut -f1 -d' ' -` + "$TEMP_DIR/checkcc" > "$TEMP_DIR/checkcc_out" + parse_toolchain_properties "$TEMP_DIR/checkcc_out" echo "$COMP" return 0 fi
--- a/ucx/Makefile Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/Makefile Sun Jul 20 22:04:39 2025 +0200 @@ -49,16 +49,20 @@ OBJ = $(SRC:%.c=../build/ucx/%$(OBJ_EXT)) -UCX_LIB = ../build/lib/libucx$(LIB_EXT) +UCX_LIB = ../build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)ucx$(LIB_EXT) +UCX_SHLIB = ../build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)ucx$(SHLIB_EXT) -all: ../build/ucx $(UCX_LIB) +all: $(UCX_LIB) $(UCX_SHLIB) $(UCX_LIB): $(OBJ) - $(AR) $(ARFLAGS) $(UCX_LIB) $(OBJ) + $(AR) $(ARFLAGS) $@ $(OBJ) + +$(UCX_SHLIB): $(OBJ) + $(CC) -o $@ $(LDFLAGS) $(SHLIB_LDFLAGS) $(OBJ) ../build/ucx: mkdir -p ../build/ucx ../build/ucx/%$(OBJ_EXT): %.c - $(CC) $(CFLAGS) -o $@ -c $< + $(CC) $(CFLAGS) $(SHLIB_CFLAGS) -o $@ -c $<
--- a/ucx/allocator.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/allocator.c Sun Jul 20 22:04:39 2025 +0200 @@ -29,6 +29,7 @@ #include "cx/allocator.h" #include <errno.h> +#include <string.h> static void *cx_malloc_stdlib( cx_attr_unused void *d, @@ -60,18 +61,19 @@ free(mem); } -static cx_allocator_class cx_default_allocator_class = { +static cx_allocator_class cx_stdlib_allocator_class = { cx_malloc_stdlib, cx_realloc_stdlib, cx_calloc_stdlib, cx_free_stdlib }; -struct cx_allocator_s cx_default_allocator = { - &cx_default_allocator_class, +struct cx_allocator_s cx_stdlib_allocator = { + &cx_stdlib_allocator_class, NULL }; -const CxAllocator * const cxDefaultAllocator = &cx_default_allocator; +const CxAllocator * const cxStdlibAllocator = &cx_stdlib_allocator; +const CxAllocator * cxDefaultAllocator = cxStdlibAllocator; int cx_reallocate_( void **mem, @@ -115,6 +117,17 @@ return allocator->cl->malloc(allocator->data, n); } +void *cxZalloc( + const CxAllocator *allocator, + size_t n +) { + void *mem = allocator->cl->malloc(allocator->data, n); + if (mem != NULL) { + memset(mem, 0, n); + } + return mem; +} + void *cxRealloc( const CxAllocator *allocator, void *mem,
--- a/ucx/array_list.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/array_list.c Sun Jul 20 22:04:39 2025 +0200 @@ -36,16 +36,17 @@ static void *cx_array_default_realloc( void *array, - size_t capacity, + cx_attr_unused size_t old_capacity, + size_t new_capacity, size_t elem_size, cx_attr_unused CxArrayReallocator *alloc ) { size_t n; - if (cx_szmul(capacity, elem_size, &n)) { + if (cx_szmul(new_capacity, elem_size, &n)) { errno = EOVERFLOW; return NULL; } - return realloc(array, n); + return cxReallocDefault(array, n); } CxArrayReallocator cx_array_default_reallocator_impl = { @@ -58,13 +59,14 @@ static void *cx_array_advanced_realloc( void *array, - size_t capacity, + size_t old_capacity, + size_t new_capacity, size_t elem_size, cx_attr_unused CxArrayReallocator *alloc ) { // check for overflow size_t n; - if (cx_szmul(capacity, elem_size, &n)) { + if (cx_szmul(new_capacity, elem_size, &n)) { errno = EOVERFLOW; return NULL; } @@ -77,7 +79,7 @@ if (array == alloc->ptr2) { newmem = cxMalloc(al, n); if (newmem != NULL && array != NULL) { - memcpy(newmem, array, n); + memcpy(newmem, array, old_capacity*elem_size); } } else { newmem = cxRealloc(al, array, n); @@ -180,7 +182,7 @@ // perform reallocation void *newmem = reallocator->realloc( - *array, newcap, elem_size, reallocator + *array, oldcap, newcap, elem_size, reallocator ); if (newmem == NULL) { return 1; // LCOV_EXCL_LINE @@ -286,7 +288,7 @@ // perform reallocation void *newmem = reallocator->realloc( - *target, newcap, elem_size, reallocator + *target, oldcap, newcap, elem_size, reallocator ); if (newmem == NULL) { return 1; @@ -366,13 +368,14 @@ // store some counts size_t old_size = *size; + size_t old_capacity = *capacity; size_t needed_capacity = old_size + elem_count; // if we need more than we have, try a reallocation - if (needed_capacity > *capacity) { + if (needed_capacity > old_capacity) { size_t new_capacity = cx_array_align_capacity(needed_capacity, 16, SIZE_MAX); void *new_mem = reallocator->realloc( - *target, new_capacity, elem_size, reallocator + *target, old_capacity, new_capacity, elem_size, reallocator ); if (new_mem == NULL) { // give it up right away, there is no contract @@ -572,7 +575,7 @@ // decide if we can use the local buffer if (elem_size > CX_ARRAY_SWAP_SBO_SIZE) { - tmp = malloc(elem_size); + tmp = cxMallocDefault(elem_size); // we don't want to enforce error handling if (tmp == NULL) abort(); } else { @@ -591,7 +594,7 @@ // free dynamic memory, if it was needed if (tmp != sbo_mem) { - free(tmp); + cxFreeDefault(tmp); } } @@ -638,50 +641,38 @@ // get a correctly typed pointer to the list cx_array_list *arl = (cx_array_list *) list; - // do we need to move some elements? - if (index < list->collection.size) { - const char *first_to_move = (const char *) arl->data; - first_to_move += index * list->collection.elem_size; - size_t elems_to_move = list->collection.size - index; - size_t start_of_moved = index + n; - - if (cx_array_copy( - &arl->data, - &list->collection.size, - &arl->capacity, - 0, - start_of_moved, - first_to_move, - list->collection.elem_size, - elems_to_move, - &arl->reallocator - )) { - // if moving existing elems is unsuccessful, abort + // guarantee enough capacity + if (arl->capacity < list->collection.size + n) { + size_t new_capacity = list->collection.size + n; + new_capacity = new_capacity - (new_capacity % 16) + 16; + if (cxReallocateArray( + list->collection.allocator, + &arl->data, new_capacity, + list->collection.elem_size) + ) { return 0; } + arl->capacity = new_capacity; } - // note that if we had to move the elements, the following operation - // is guaranteed to succeed, because we have the memory already allocated - // therefore, it is impossible to leave this function with an invalid array + // determine insert position + char *arl_data = arl->data; + char *insert_pos = arl_data + index * list->collection.elem_size; - // place the new elements - if (cx_array_copy( - &arl->data, - &list->collection.size, - &arl->capacity, - 0, - index, - array, - list->collection.elem_size, - n, - &arl->reallocator - )) { - // array list implementation is "all or nothing" - return 0; - } else { - return n; + // do we need to move some elements? + if (index < list->collection.size) { + size_t elems_to_move = list->collection.size - index; + char *target = insert_pos + n * list->collection.elem_size; + memmove(target, insert_pos, elems_to_move * list->collection.elem_size); } + + // place the new elements, if any + if (array != NULL) { + memcpy(insert_pos, array, n * list->collection.elem_size); + } + list->collection.size += n; + + return n; } static size_t cx_arl_insert_sorted( @@ -709,12 +700,16 @@ } } -static int cx_arl_insert_element( +static void *cx_arl_insert_element( struct cx_list_s *list, size_t index, const void *element ) { - return 1 != cx_arl_insert_array(list, index, element, 1); + if (cx_arl_insert_array(list, index, element, 1) == 1) { + return ((char*)((cx_array_list *) list)->data) + index * list->collection.elem_size; + } else { + return NULL; + } } static int cx_arl_insert_iter( @@ -724,26 +719,23 @@ ) { struct cx_list_s *list = iter->src_handle.m; if (iter->index < list->collection.size) { - int result = cx_arl_insert_element( - list, - iter->index + 1 - prepend, - elem - ); - if (result == 0) { - iter->elem_count++; - if (prepend != 0) { - iter->index++; - iter->elem_handle = ((char *) iter->elem_handle) + list->collection.elem_size; - } + if (cx_arl_insert_element(list, + iter->index + 1 - prepend, elem) == NULL) { + return 1; + } + iter->elem_count++; + if (prepend != 0) { + iter->index++; + iter->elem_handle = ((char *) iter->elem_handle) + list->collection.elem_size; } - return result; + return 0; } else { - int result = cx_arl_insert_element(list, list->collection.size, elem); - if (result == 0) { - iter->elem_count++; - iter->index = list->collection.size; + if (cx_arl_insert_element(list, list->collection.size, elem) == NULL) { + return 1; } - return result; + iter->elem_count++; + iter->index = list->collection.size; + return 0; } }
--- a/ucx/buffer.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/buffer.c Sun Jul 20 22:04:39 2025 +0200 @@ -32,6 +32,24 @@ #include <string.h> #include <errno.h> +#ifdef _WIN32 +#include <Windows.h> +#include <sysinfoapi.h> +static unsigned long system_page_size() { + static unsigned long ps = 0; + if (ps == 0) { + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + ps = sysinfo.dwPageSize; + } + return ps; +} +#define SYSTEM_PAGE_SIZE system_page_size() +#else +#include <unistd.h> +#define SYSTEM_PAGE_SIZE sysconf(_SC_PAGESIZE) +#endif + static int buffer_copy_on_write(CxBuffer* buffer) { if (0 == (buffer->flags & CX_BUFFER_COPY_ON_WRITE)) return 0; void *newspace = cxMalloc(buffer->allocator, buffer->capacity); @@ -80,7 +98,7 @@ CxBuffer *buffer, CxBufferFlushConfig config ) { - buffer->flush = malloc(sizeof(CxBufferFlushConfig)); + buffer->flush = cxMallocDefault(sizeof(CxBufferFlushConfig)); if (buffer->flush == NULL) return -1; // LCOV_EXCL_LINE memcpy(buffer->flush, &config, sizeof(CxBufferFlushConfig)); return 0; @@ -90,7 +108,7 @@ if (buffer->flags & CX_BUFFER_FREE_CONTENTS) { cxFree(buffer->allocator, buffer->bytes); } - free(buffer->flush); + cxFreeDefault(buffer->flush); memset(buffer, 0, sizeof(CxBuffer)); } @@ -139,6 +157,7 @@ npos = 0; break; default: + errno = EINVAL; return -1; } @@ -146,11 +165,16 @@ npos += offset; if ((offset > 0 && npos < opos) || (offset < 0 && npos > opos)) { - errno = EOVERFLOW; + // to be compliant with fseek() specification + // we return EINVAL on underflow + errno = EINVAL; return -1; } if (npos > buffer->size) { + // not compliant with fseek() specification + // but this is the better behavior for CxBuffer + errno = EINVAL; return -1; } else { buffer->pos = npos; @@ -184,6 +208,28 @@ return 0; } + unsigned long pagesize = SYSTEM_PAGE_SIZE; + // if page size is larger than 64 KB - for some reason - truncate to 64 KB + if (pagesize > 65536) pagesize = 65536; + if (newcap < pagesize) { + // when smaller as one page, map to the next power of two + newcap--; + newcap |= newcap >> 1; + newcap |= newcap >> 2; + newcap |= newcap >> 4; + // last operation only needed for pages larger 4096 bytes + // but if/else would be more expensive than just doing this + newcap |= newcap >> 8; + newcap++; + } else { + // otherwise, map to a multiple of the page size + newcap -= newcap % pagesize; + newcap += pagesize; + // note: if newcap is already page aligned, + // this gives a full additional page (which is good) + } + + const int force_copy_flags = CX_BUFFER_COPY_ON_WRITE | CX_BUFFER_COPY_ON_EXTEND; if (buffer->flags & force_copy_flags) { void *newspace = cxMalloc(buffer->allocator, newcap); @@ -203,6 +249,28 @@ } } +void cxBufferShrink( + CxBuffer *buffer, + size_t reserve +) { + // Ensure buffer is in a reallocatable state + const int force_copy_flags = CX_BUFFER_COPY_ON_WRITE | CX_BUFFER_COPY_ON_EXTEND; + if (buffer->flags & force_copy_flags) { + // do nothing when we are not allowed to reallocate + return; + } + + // calculate new capacity + size_t newCapacity = buffer->size + reserve; + + // If new capacity is smaller than current capacity, resize the buffer + if (newCapacity < buffer->capacity) { + if (0 == cxReallocate(buffer->allocator, &buffer->bytes, newCapacity)) { + buffer->capacity = newCapacity; + } + } +} + static size_t cx_buffer_flush_helper( const CxBuffer *buffer, const unsigned char *src, @@ -399,10 +467,8 @@ } int cxBufferTerminate(CxBuffer *buffer) { - bool success = 0 == cxBufferPut(buffer, 0); - if (success) { - buffer->pos--; - buffer->size--; + if (0 == cxBufferPut(buffer, 0)) { + buffer->size = buffer->pos - 1; return 0; } else { return -1;
--- a/ucx/cx/allocator.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/cx/allocator.h Sun Jul 20 22:04:39 2025 +0200 @@ -98,10 +98,17 @@ typedef struct cx_allocator_s CxAllocator; /** - * A default allocator using standard library malloc() etc. + * A pre-defined allocator using standard library malloc() etc. */ cx_attr_export -extern const CxAllocator * const cxDefaultAllocator; +extern const CxAllocator * const cxStdlibAllocator; + +/** + * The default allocator that is used by UCX. + * Initialized with cxStdlibAllocator, but you may change it. + */ +cx_attr_export +extern const CxAllocator * cxDefaultAllocator; /** * Function pointer type for destructor functions. @@ -135,6 +142,8 @@ * Reallocate a previously allocated block and changes the pointer in-place, * if necessary. * + * @note This will use stdlib reallocate and @em not the cxDefaultAllocator. + * * @par Error handling * @c errno will be set by realloc() on failure. * @@ -158,6 +167,8 @@ * * The size is calculated by multiplying @p nemb and @p size. * + * @note This will use stdlib reallocate and @em not the cxDefaultAllocator. + * * @par Error handling * @c errno will be set by realloc() on failure or when the multiplication of * @p nmemb and @p size overflows. @@ -182,6 +193,8 @@ * Reallocate a previously allocated block and changes the pointer in-place, * if necessary. * + * @note This will use stdlib reallocate and @em not the cxDefaultAllocator. + * * @par Error handling * @c errno will be set by realloc() on failure. * @@ -199,6 +212,8 @@ * * The size is calculated by multiplying @p nemb and @p size. * + * @note This will use stdlib reallocate and @em not the cxDefaultAllocator. + * * @par Error handling * @c errno will be set by realloc() on failure or when the multiplication of * @p nmemb and @p size overflows. @@ -213,6 +228,14 @@ cx_reallocatearray_((void**)(mem), nmemb, size) /** + * Allocates memory and sets every byte to zero. + * + * @param n (@c size_t) the number of bytes + * @return (@c void*) a pointer to the allocated memory + */ +#define cx_zalloc(n) calloc(1, n) + +/** * Free a block allocated by this allocator. * * @note Freeing a block of a different allocator is undefined. @@ -414,6 +437,57 @@ size_t size ); +/** + * Allocate @p n bytes of memory and sets every byte to zero. + * + * @param allocator the allocator + * @param n the number of bytes + * @return a pointer to the allocated memory + */ +cx_attr_nodiscard +cx_attr_nonnull +cx_attr_malloc +cx_attr_dealloc_ucx +cx_attr_allocsize(2) +cx_attr_export +void *cxZalloc( + const CxAllocator *allocator, + size_t n +); + +/** + * Convenience macro that invokes cxMalloc() with the cxDefaultAllocator. + */ +#define cxMallocDefault(...) cxMalloc(cxDefaultAllocator, __VA_ARGS__) +/** + * Convenience macro that invokes cxZalloc() with the cxDefaultAllocator. + */ +#define cxZallocDefault(...) cxZalloc(cxDefaultAllocator, __VA_ARGS__) +/** + * Convenience macro that invokes cxCalloc() with the cxDefaultAllocator. + */ +#define cxCallocDefault(...) cxCalloc(cxDefaultAllocator, __VA_ARGS__) +/** + * Convenience macro that invokes cxRealloc() with the cxDefaultAllocator. + */ +#define cxReallocDefault(...) cxRealloc(cxDefaultAllocator, __VA_ARGS__) +/** + * Convenience macro that invokes cxReallocate() with the cxDefaultAllocator. + */ +#define cxReallocateDefault(...) cxReallocate(cxDefaultAllocator, __VA_ARGS__) +/** + * Convenience macro that invokes cxReallocateArray() with the cxDefaultAllocator. + */ +#define cxReallocateArrayDefault(...) cxReallocateArray(cxDefaultAllocator, __VA_ARGS__) +/** + * Convenience macro that invokes cxReallocArray() with the cxDefaultAllocator. + */ +#define cxReallocArrayDefault(...) cxReallocArray(cxDefaultAllocator, __VA_ARGS__) +/** + * Convenience macro that invokes cxFree() with the cxDefaultAllocator. + */ +#define cxFreeDefault(...) cxFree(cxDefaultAllocator, __VA_ARGS__) + #ifdef __cplusplus } // extern "C" #endif
--- a/ucx/cx/array_list.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/cx/array_list.h Sun Jul 20 22:04:39 2025 +0200 @@ -123,7 +123,8 @@ * @endcode * * - * The memory for the array is allocated with stdlib malloc(). + * The memory for the array is allocated with the cxDefaultAllocator. + * * @param array the name of the array * @param capacity the initial capacity * @see cx_array_initialize_a() @@ -133,7 +134,7 @@ #define cx_array_initialize(array, capacity) \ array##_capacity = capacity; \ array##_size = 0; \ - array = malloc(sizeof(array[0]) * capacity) + array = cxMallocDefault(sizeof(array[0]) * capacity) /** * Initializes an array with the given capacity using the specified allocator. @@ -149,7 +150,6 @@ * cxFree(al, myarray); // don't forget to free with same allocator * @endcode * - * The memory for the array is allocated with stdlib malloc(). * @param allocator (@c CxAllocator*) the allocator * @param array the name of the array * @param capacity the initial capacity @@ -178,17 +178,19 @@ * or to transport other additional data. * * @param array the array to reallocate - * @param capacity the new capacity (number of elements) + * @param old_capacity the old number of elements + * @param new_capacity the new number of elements * @param elem_size the size of each element * @param alloc a reference to this allocator * @return a pointer to the reallocated memory or @c NULL on failure */ cx_attr_nodiscard - cx_attr_nonnull_arg(4) - cx_attr_allocsize(2, 3) + cx_attr_nonnull_arg(5) + cx_attr_allocsize(3, 4) void *(*realloc)( void *array, - size_t capacity, + size_t old_capacity, + size_t new_capacity, size_t elem_size, struct cx_array_reallocator_s *alloc ); @@ -217,7 +219,7 @@ typedef struct cx_array_reallocator_s CxArrayReallocator; /** - * A default stdlib-based array reallocator. + * A default array reallocator that is based on the cxDefaultAllocator. */ cx_attr_export extern CxArrayReallocator *cx_array_default_reallocator; @@ -225,7 +227,7 @@ /** * Creates a new array reallocator. * - * When @p allocator is @c NULL, the stdlib default allocator will be used. + * When @p allocator is @c NULL, the cxDefaultAllocator will be used. * * When @p stackmem is not @c NULL, the reallocator is supposed to be used * @em only for the specific array that is initially located at @p stackmem. @@ -699,7 +701,7 @@ * to cx_cmp_ptr(), if none is given. * * @param allocator the allocator for allocating the list memory - * (if @c NULL, a default stdlib allocator will be used) + * (if @c NULL, the cxDefaultAllocator will be used) * @param comparator the comparator for the elements * (if @c NULL, and the list is not storing pointers, sort and find * functions will not work) @@ -727,7 +729,7 @@ * * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of * copies of the added elements and the compare function will be automatically set - * to cx_cmp_ptr(), if none is given. + * to cx_cmp_ptr(). * * @param elem_size (@c size_t) the size of each element in bytes * @param initial_capacity (@c size_t) the initial number of elements the array can store
--- a/ucx/cx/buffer.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/cx/buffer.h Sun Jul 20 22:04:39 2025 +0200 @@ -222,7 +222,7 @@ * @param capacity the capacity of the buffer * @param allocator the allocator this buffer shall use for automatic * memory management - * (if @c NULL, a default stdlib allocator will be used) + * (if @c NULL, the cxDefaultAllocator will be used) * @param flags buffer features (see cx_buffer_s.flags) * @return zero on success, non-zero if a required allocation failed */ @@ -305,7 +305,7 @@ * @param capacity the capacity of the buffer * @param allocator the allocator to use for allocating the structure and the automatic * memory management within the buffer - * (if @c NULL, a default stdlib allocator will be used) + * (if @c NULL, the cxDefaultAllocator will be used) * @param flags buffer features (see cx_buffer_s.flags) * @return a pointer to the buffer on success, @c NULL if a required allocation failed */ @@ -474,10 +474,14 @@ * * If the current capacity is not sufficient, the buffer will be extended. * + * The new capacity will be a power of two until the system's page size is reached. + * Then, the new capacity will be a multiple of the page size. + * * @param buffer the buffer * @param capacity the minimum required capacity for this buffer * @retval zero the capacity was already sufficient or successfully increased * @retval non-zero on allocation failure + * @see cxBufferShrink() */ cx_attr_nonnull cx_attr_export @@ -487,6 +491,29 @@ ); /** + * Shrinks the capacity of the buffer to fit its current size. + * + * If @p reserve is larger than zero, the buffer is shrunk to its size plus + * the number of reserved bytes. + * + * If the current capacity is not larger than the size plus the reserved bytes, + * nothing happens. + * + * If the #CX_BUFFER_COPY_ON_WRITE or #CX_BUFFER_COPY_ON_EXTEND flag is set, + * this function does nothing. + * + * @param buffer the buffer + * @param reserve the number of bytes that shall remain reserved + * @see cxBufferMinimumCapacity() + */ +cx_attr_nonnull +cx_attr_export +void cxBufferShrink( + CxBuffer *buffer, + size_t reserve +); + +/** * Writes data to a CxBuffer. * * If automatic flushing is not enabled, the data is simply written into the @@ -674,11 +701,10 @@ /** * Writes a terminating zero to a buffer at the current position. * - * On successful write, @em neither the position @em nor the size of the buffer is - * increased. + * If successful, sets the size to the current position and advances the position by one. * * The purpose of this function is to have the written data ready to be used as - * a C string. + * a C string with the buffer's size being the length of that string. * * @param buffer the buffer to write to * @return zero, if the terminator could be written, non-zero otherwise
--- a/ucx/cx/common.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/cx/common.h Sun Jul 20 22:04:39 2025 +0200 @@ -46,7 +46,7 @@ * Repositories:<br> * <a href="https://sourceforge.net/p/ucx/code">https://sourceforge.net/p/ucx/code</a> * - or - - * <a href="https://develop.uap-core.de/hg/ucx">https://develop.uap-core.de/hg/ucx</a> + * <a href="https://uap-core.de/hg/ucx">https://uap-core.de/hg/ucx</a> * </p> * * <h2>LICENCE</h2> @@ -150,7 +150,7 @@ */ #define cx_attr_malloc __attribute__((__malloc__)) -#ifndef __clang__ +#if !defined(__clang__) && __GNUC__ >= 11 /** * The pointer returned by the attributed function is supposed to be freed * by @p freefunc. @@ -240,20 +240,6 @@ */ #define cx_attr_access_w(...) cx_attr_access(__write_only__, __VA_ARGS__) -#if __STDC_VERSION__ >= 202300L - -/** - * Do not warn about unused variable. - */ -#define cx_attr_unused [[maybe_unused]] - -/** - * Warn about discarded return value. - */ -#define cx_attr_nodiscard [[nodiscard]] - -#else // no C23 - /** * Do not warn about unused variable. */ @@ -264,8 +250,6 @@ */ #define cx_attr_nodiscard __attribute__((__warn_unused_result__)) -#endif // __STDC_VERSION__ - // --------------------------------------------------------------------------- // MSVC specifics
--- a/ucx/cx/hash_map.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/cx/hash_map.h Sun Jul 20 22:04:39 2025 +0200 @@ -77,7 +77,7 @@ * In other words, when the iterator is finished, @c index==size . * * @param allocator the allocator to use - * (if @c NULL, a default stdlib allocator will be used) + * (if @c NULL, the cxDefaultAllocator will be used) * @param itemsize the size of one element * @param buckets the initial number of buckets in this hash map * @return a pointer to the new hash map
--- a/ucx/cx/linked_list.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/cx/linked_list.h Sun Jul 20 22:04:39 2025 +0200 @@ -51,7 +51,7 @@ * to cx_cmp_ptr(), if none is given. * * @param allocator the allocator for allocating the list nodes - * (if @c NULL, a default stdlib allocator will be used) + * (if @c NULL, the cxDefaultAllocator will be used) * @param comparator the comparator for the elements * (if @c NULL, and the list is not storing pointers, sort and find * functions will not work) @@ -77,7 +77,7 @@ * * If @p elem_size is #CX_STORE_POINTERS, the created list stores pointers instead of * copies of the added elements and the compare function will be automatically set - * to cx_cmp_ptr(), if none is given. + * to cx_cmp_ptr(). * * @param elem_size (@c size_t) the size of each element in bytes * @return (@c CxList*) the created list @@ -393,7 +393,7 @@ * @li @p loc_next and @p loc_prev (ancestor node is determined by using the prev pointer, overall O(1) performance) * @li @p loc_next and @p begin (ancestor node is determined by list traversal, overall O(n) performance) * - * @remark The @c next and @c prev pointers of the removed node are not cleared by this function and may still be used + * @remark The @c next and @c prev pointers of the removed chain are not cleared by this function and may still be used * to traverse to a former adjacent node in the list, or within the chain. * * @param begin a pointer to the beginning node pointer (optional)
--- a/ucx/cx/list.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/cx/list.h Sun Jul 20 22:04:39 2025 +0200 @@ -80,8 +80,10 @@ /** * Member function for inserting a single element. + * The data pointer may be @c NULL in which case the function shall only allocate memory. + * Returns a pointer to the data of the inserted element. */ - int (*insert_element)( + void *(*insert_element)( struct cx_list_s *list, size_t index, const void *data @@ -203,6 +205,22 @@ }; /** + * Common type for all list implementations. + */ +typedef struct cx_list_s CxList; + +/** + * A shared instance of an empty list. + * + * Writing to that list is not allowed. + * + * You can use this is a placeholder for initializing CxList pointers + * for which you do not want to reserve memory right from the beginning. + */ +cx_attr_export +extern CxList *const cxEmptyList; + +/** * Default implementation of an array insert. * * This function uses the element insert function for each element of the array. @@ -336,11 +354,6 @@ ); /** - * Common type for all list implementations. - */ -typedef struct cx_list_s CxList; - -/** * Returns the number of elements currently stored in the list. * * @param list the list @@ -359,6 +372,7 @@ * @retval zero success * @retval non-zero memory allocation failure * @see cxListAddArray() + * @see cxListEmplace() */ cx_attr_nonnull static inline int cxListAdd( @@ -366,7 +380,7 @@ const void *elem ) { list->collection.sorted = false; - return list->cl->insert_element(list, list->collection.size, elem); + return list->cl->insert_element(list, list->collection.size, elem) == NULL; } /** @@ -407,6 +421,7 @@ * @retval non-zero memory allocation failure or the index is out of bounds * @see cxListInsertAfter() * @see cxListInsertBefore() + * @see cxListEmplaceAt() */ cx_attr_nonnull static inline int cxListInsert( @@ -415,7 +430,41 @@ const void *elem ) { list->collection.sorted = false; - return list->cl->insert_element(list, index, elem); + return list->cl->insert_element(list, index, elem) == NULL; +} + +/** + * Allocates memory for an element at the specified index and returns a pointer to that memory. + * + * @remark When the list is storing pointers, this will return a @c void**. + * + * @param list the list + * @param index the index where to emplace the element + * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds + * @see cxListEmplace() + * @see cxListInsert() + */ +cx_attr_nonnull +static inline void *cxListEmplaceAt(CxList *list, size_t index) { + list->collection.sorted = false; + return list->cl->insert_element(list, index, NULL); +} + + +/** + * Allocates memory for an element at the end of the list and returns a pointer to that memory. + * + * @remark When the list is storing pointers, this will return a @c void**. + * + * @param list the list + * @return a pointer to the allocated memory; @c NULL when the operation fails, or the index is out-of-bounds + * @see cxListEmplaceAt() + * @see cxListAdd() + */ +cx_attr_nonnull +static inline void *cxListEmplace(CxList *list) { + list->collection.sorted = false; + return list->cl->insert_element(list, list->collection.size, NULL); } /** @@ -571,8 +620,9 @@ /** * Removes and returns the element at the specified index. * - * No destructor is called and instead the element is copied to the + * No destructor is called, and instead the element is copied to the * @p targetbuf which MUST be large enough to hold the removed element. + * If the list is storing pointers, only the pointer is copied to @p targetbuf. * * @param list the list * @param index the index of the element @@ -591,11 +641,93 @@ } /** + * Removes and returns the first element of the list. + * + * No destructor is called, and instead the element is copied to the + * @p targetbuf which MUST be large enough to hold the removed element. + * If the list is storing pointers, only the pointer is copied to @p targetbuf. + * + * @param list the list + * @param targetbuf a buffer where to copy the element + * @retval zero success + * @retval non-zero list is empty + * @see cxListPopFront() + * @see cxListRemoveAndGetLast() + */ +cx_attr_nonnull +cx_attr_access_w(2) +static inline int cxListRemoveAndGetFirst( + CxList *list, + void *targetbuf +) { + return list->cl->remove(list, 0, 1, targetbuf) == 0; +} + +/** + * Removes and returns the first element of the list. + * + * Alias for cxListRemoveAndGetFirst(). + * + * No destructor is called, and instead the element is copied to the + * @p targetbuf which MUST be large enough to hold the removed element. + * If the list is storing pointers, only the pointer is copied to @p targetbuf. + * + * @param list (@c CxList*) the list + * @param targetbuf (@c void*) a buffer where to copy the element + * @retval zero success + * @retval non-zero list is empty + * @see cxListRemoveAndGetFirst() + * @see cxListPop() + */ +#define cxListPopFront(list, targetbuf) cxListRemoveAndGetFirst((list), (targetbuf)) + + +/** + * Removes and returns the last element of the list. + * + * No destructor is called, and instead the element is copied to the + * @p targetbuf which MUST be large enough to hold the removed element. + * If the list is storing pointers, only the pointer is copied to @p targetbuf. + * + * @param list the list + * @param targetbuf a buffer where to copy the element + * @retval zero success + * @retval non-zero list is empty + */ +cx_attr_nonnull +cx_attr_access_w(2) +static inline int cxListRemoveAndGetLast( + CxList *list, + void *targetbuf +) { + // note: index may wrap - member function will catch that + return list->cl->remove(list, list->collection.size - 1, 1, targetbuf) == 0; +} + +/** + * Removes and returns the last element of the list. + * + * Alias for cxListRemoveAndGetLast(). + * + * No destructor is called, and instead the element is copied to the + * @p targetbuf which MUST be large enough to hold the removed element. + * If the list is storing pointers, only the pointer is copied to @p targetbuf. + * + * @param list (@c CxList*) the list + * @param targetbuf (@c void*) a buffer where to copy the element + * @retval zero success + * @retval non-zero list is empty + * @see cxListRemoveAndGetLast() + * @see cxListPopFront() + */ +#define cxListPop(list, targetbuf) cxListRemoveAndGetLast((list), (targetbuf)) + +/** * Removes multiple element starting at the specified index. * * If an element destructor function is specified, it is called for each * element. It is guaranteed that the destructor is called before removing - * the element, however, due to possible optimizations it is neither guaranteed + * the element. However, due to possible optimizations, it is neither guaranteed * that the destructors are invoked for all elements before starting to remove * them, nor that the element is removed immediately after the destructor call * before proceeding to the next element. @@ -615,10 +747,11 @@ } /** - * Removes and returns multiple element starting at the specified index. + * Removes and returns multiple elements starting at the specified index. * - * No destructor is called and instead the elements are copied to the + * No destructor is called, and instead the elements are copied to the * @p targetbuf which MUST be large enough to hold all removed elements. + * If the list is storing pointers, @p targetbuf is expected to be an array of pointers. * * @param list the list * @param index the index of the element @@ -654,15 +787,15 @@ /** * Swaps two items in the list. * - * Implementations should only allocate temporary memory for the swap, if + * Implementations should only allocate temporary memory for the swap if * it is necessary. * * @param list the list * @param i the index of the first element * @param j the index of the second element * @retval zero success - * @retval non-zero one of the indices is out of bounds - * or the swap needed extra memory but allocation failed + * @retval non-zero one of the indices is out of bounds, + * or the swap needed extra memory, but allocation failed */ cx_attr_nonnull static inline int cxListSwap( @@ -677,6 +810,8 @@ /** * Returns a pointer to the element at the specified index. * + * If the list is storing pointers, returns the pointer stored at the specified index. + * * @param list the list * @param index the index of the element * @return a pointer to the element or @c NULL if the index is out of bounds @@ -690,6 +825,49 @@ } /** + * Returns a pointer to the first element. + * + * If the list is storing pointers, returns the first pointer stored in the list. + * + * @param list the list + * @return a pointer to the first element or @c NULL if the list is empty + */ +cx_attr_nonnull +static inline void *cxListFirst(const CxList *list) { + return list->cl->at(list, 0); +} + +/** + * Returns a pointer to the last element. + * + * If the list is storing pointers, returns the last pointer stored in the list. + * + * @param list the list + * @return a pointer to the last element or @c NULL if the list is empty + */ +cx_attr_nonnull +static inline void *cxListLast(const CxList *list) { + return list->cl->at(list, list->collection.size - 1); +} + +/** + * Sets the element at the specified index in the list + * + * @param list the list to set the element in + * @param index the index to set the element at + * @param elem element to set + * @retval zero on success + * @retval non-zero when index is out of bounds + */ +cx_attr_nonnull +cx_attr_export +int cxListSet( + CxList *list, + size_t index, + const void *elem +); + +/** * Returns an iterator pointing to the item at the specified index. * * The returned iterator is position-aware. @@ -773,14 +951,14 @@ * * The returned iterator is position-aware. * - * If the list is empty, a past-the-end iterator will be returned. + * If the list is empty or @c NULL, a past-the-end iterator will be returned. * * @param list the list * @return a new iterator */ -cx_attr_nonnull cx_attr_nodiscard static inline CxIterator cxListIterator(const CxList *list) { + if (list == NULL) list = cxEmptyList; return list->cl->iterator(list, 0, false); } @@ -789,14 +967,14 @@ * * The returned iterator is position-aware. * - * If the list is empty, a past-the-end iterator will be returned. + * If the list is empty or @c NULL, a past-the-end iterator will be returned. * * @param list the list * @return a new iterator */ -cx_attr_nonnull cx_attr_nodiscard static inline CxIterator cxListMutIterator(CxList *list) { + if (list == NULL) list = cxEmptyList; return cxListMutIteratorAt(list, 0); } @@ -806,14 +984,14 @@ * * The returned iterator is position-aware. * - * If the list is empty, a past-the-end iterator will be returned. + * If the list is empty or @c NULL, a past-the-end iterator will be returned. * * @param list the list * @return a new iterator */ -cx_attr_nonnull cx_attr_nodiscard static inline CxIterator cxListBackwardsIterator(const CxList *list) { + if (list == NULL) list = cxEmptyList; return list->cl->iterator(list, list->collection.size - 1, true); } @@ -822,14 +1000,14 @@ * * The returned iterator is position-aware. * - * If the list is empty, a past-the-end iterator will be returned. + * If the list is empty or @c NULL, a past-the-end iterator will be returned. * * @param list the list * @return a new iterator */ -cx_attr_nonnull cx_attr_nodiscard static inline CxIterator cxListMutBackwardsIterator(CxList *list) { + if (list == NULL) list = cxEmptyList; return cxListMutBackwardsIteratorAt(list, list->collection.size - 1); } @@ -842,6 +1020,7 @@ * @param elem the element to find * @return the index of the element or the size of the list when the element is not found * @see cxListIndexValid() + * @see cxListContains() */ cx_attr_nonnull cx_attr_nodiscard @@ -853,6 +1032,26 @@ } /** + * Checks, if the list contains the specified element. + * + * The elements are compared with the list's comparator function. + * + * @param list the list + * @param elem the element to find + * @retval true if the element is contained + * @retval false if the element is not contained + * @see cxListFind() + */ +cx_attr_nonnull +cx_attr_nodiscard +static inline bool cxListContains( + const CxList* list, + const void* elem +) { + return list->cl->find_remove((CxList*)list, elem, false) < list->collection.size; +} + +/** * Checks if the specified index is within bounds. * * @param list the list @@ -894,6 +1093,7 @@ */ cx_attr_nonnull static inline void cxListSort(CxList *list) { + if (list->collection.sorted) return; list->cl->sort(list); list->collection.sorted = true; } @@ -942,17 +1142,6 @@ cx_attr_export void cxListFree(CxList *list); -/** - * A shared instance of an empty list. - * - * Writing to that list is not allowed. - * - * You can use this is a placeholder for initializing CxList pointers - * for which you do not want to reserve memory right from the beginning. - */ -cx_attr_export -extern CxList *const cxEmptyList; - #ifdef __cplusplus } // extern "C"
--- a/ucx/cx/mempool.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/cx/mempool.h Sun Jul 20 22:04:39 2025 +0200 @@ -43,31 +43,107 @@ extern "C" { #endif -/** Internal structure for pooled memory. */ -struct cx_mempool_memory_s; +/** A memory block in a simple memory pool. */ +struct cx_mempool_memory_s { + /** The destructor. */ + cx_destructor_func destructor; + /** The actual memory. */ + char c[]; +}; + +/** A memory block in an advanced memory pool. */ +struct cx_mempool_memory2_s { + /** The destructor. */ + cx_destructor_func2 destructor; + /** Data for the destructor. */ + void *data; + /** The actual memory. */ + char c[]; +}; + +/** Represents memory that is not allocated by, but registered with a pool. */ +struct cx_mempool_foreign_memory_s { + /** The foreign memory. */ + void* mem; + union { + /** Simple destructor. */ + cx_destructor_func destr; + /** Advanced destructor. */ + cx_destructor_func2 destr2; + }; + /** Data for the advanced destructor. */ + void *destr2_data; +}; + +/** Specifies how individual blocks are allocated. */ +enum cx_mempool_type { + /** + * Allows registration of cx_destructor_func for each memory block. + */ + CX_MEMPOOL_TYPE_SIMPLE, + /** + * Allows registration of cx_destructor_func2 for each memory block. + */ + CX_MEMPOOL_TYPE_ADVANCED, + /** + * No individual destructor registration allowed. + * + * In this mode, no additional memory per block is allocated. + */ + CX_MEMPOOL_TYPE_PURE, +}; /** * The basic structure of a memory pool. * Should be the first member of an actual memory pool implementation. */ struct cx_mempool_s { + /** The used allocator, initialized with the cxDefaultAllocator. */ + const CxAllocator * const base_allocator; + /** The provided allocator. */ const CxAllocator *allocator; - /** - * A destructor that shall be automatically registered for newly allocated memory. - * This destructor MUST NOT free the memory. - */ - cx_destructor_func auto_destr; - /** Array of pooled memory. */ - struct cx_mempool_memory_s **data; + void **data; /** Number of pooled memory items. */ size_t size; /** Memory pool capacity. */ size_t capacity; + + /** Array of registered memory. */ + struct cx_mempool_foreign_memory_s *registered; + + /** Number of registered memory items. */ + size_t registered_size; + + /** Capacity for registered memory. */ + size_t registered_capacity; + + /** + * A destructor that shall be called before deallocating a memory block. + * This destructor MUST NOT free the memory itself. + * + * It is guaranteed that this destructor is called after the individual + * destructor of the memory block and before @c destr2. + */ + cx_destructor_func destr; + + /** + * A destructor that shall be called before deallocating a memory block. + * This destructor MUST NOT free the memory itself. + * + * It is guaranteed that this destructor is called after the individual + * destructor of the memory block and @c destr. + */ + cx_destructor_func2 destr2; + + /** + * Additional data for the @c destr2. + */ + void *destr2_data; }; /** @@ -84,31 +160,76 @@ void cxMempoolFree(CxMempool *pool); /** - * Creates an array-based memory pool with a shared destructor function. + * Creates an array-based memory pool. * - * This destructor MUST NOT free the memory. + * The type determines how much additional memory is allocated per block + * to register a destructor function. * - * @param capacity the initial capacity of the pool - * @param destr optional destructor function to use for allocated memory + * @param capacity the initial capacity of the pool (an implementation default if zero) + * @param type the type of memory pool * @return the created memory pool or @c NULL if allocation failed */ cx_attr_nodiscard cx_attr_malloc cx_attr_dealloc(cxMempoolFree, 1) cx_attr_export -CxMempool *cxMempoolCreate(size_t capacity, cx_destructor_func destr); +CxMempool *cxMempoolCreate(size_t capacity, enum cx_mempool_type type); + +/** + * Creates a basic array-based memory pool. + * + * Convenience macro to create a memory pool of type #CX_MEMPOOL_TYPE_SIMPLE. + * + * @param capacity (@c size_t) the initial capacity of the pool + * @return (@c CxMempool*) the created memory pool or @c NULL if allocation failed + */ +#define cxMempoolCreateSimple(capacity) cxMempoolCreate(capacity, CX_MEMPOOL_TYPE_SIMPLE) + +/** + * Creates a basic array-based memory pool. + * + * Convenience macro to create a memory pool of type #CX_MEMPOOL_TYPE_ADVANCED. + * + * @param capacity (@c size_t) the initial capacity of the pool + * @return (@c CxMempool*) the created memory pool or @c NULL if allocation failed + */ +#define cxMempoolCreateAdvanced(capacity) cxMempoolCreate(capacity, CX_MEMPOOL_TYPE_ADVANCED) /** * Creates a basic array-based memory pool. * + * Convenience macro to create a memory pool of type #CX_MEMPOOL_TYPE_PURE. + * * @param capacity (@c size_t) the initial capacity of the pool * @return (@c CxMempool*) the created memory pool or @c NULL if allocation failed */ -#define cxMempoolCreateSimple(capacity) cxMempoolCreate(capacity, NULL) +#define cxMempoolCreatePure(capacity) cxMempoolCreate(capacity, CX_MEMPOOL_TYPE_PURE) + +/** + * Sets the global destructor for all memory blocks within the specified pool. + * + * @param pool the memory pool + * @param fnc the destructor that shall be applied to all memory blocks + */ +cx_attr_nonnull_arg(1) +cx_attr_export +void cxMempoolGlobalDestructor(CxMempool *pool, cx_destructor_func fnc); + +/** + * Sets the global destructor for all memory blocks within the specified pool. + * + * @param pool the memory pool + * @param fnc the destructor that shall be applied to all memory blocks + * @param data additional data for the destructor function + */ +cx_attr_nonnull_arg(1) +cx_attr_export +void cxMempoolGlobalDestructor2(CxMempool *pool, cx_destructor_func2 fnc, void *data); /** * Sets the destructor function for a specific allocated memory object. * + * If the type of memory pool is not #CX_MEMPOOL_TYPE_SIMPLE, the behavior is undefined. * If the memory is not managed by a UCX memory pool, the behavior is undefined. * The destructor MUST NOT free the memory. * @@ -123,10 +244,29 @@ ); /** + * Sets the destructor function for a specific allocated memory object. + * + * If the type of memory pool is not #CX_MEMPOOL_TYPE_ADVANCED, the behavior is undefined. + * If the memory is not managed by a UCX memory pool, the behavior is undefined. + * The destructor MUST NOT free the memory. + * + * @param memory the object allocated in the pool + * @param fnc the destructor function + * @param data additional data for the destructor function + */ +cx_attr_nonnull +cx_attr_export +void cxMempoolSetDestructor2( + void *memory, + cx_destructor_func2 fnc, + void *data +); + +/** * Removes the destructor function for a specific allocated memory object. * + * If the type of memory pool is not #CX_MEMPOOL_TYPE_SIMPLE, the behavior is undefined. * If the memory is not managed by a UCX memory pool, the behavior is undefined. - * The destructor MUST NOT free the memory. * * @param memory the object allocated in the pool */ @@ -135,12 +275,25 @@ void cxMempoolRemoveDestructor(void *memory); /** + * Removes the destructor function for a specific allocated memory object. + * + * If the type of memory pool is not #CX_MEMPOOL_TYPE_ADVANCED, the behavior is undefined. + * If the memory is not managed by a UCX memory pool, the behavior is undefined. + * + * @param memory the object allocated in the pool + */ +cx_attr_nonnull +cx_attr_export +void cxMempoolRemoveDestructor2(void *memory); + +/** * Registers foreign memory with this pool. * * The destructor, in contrast to memory allocated by the pool, MUST free the memory. + * This function can be used with any pool of any type, since destructors for registered memory + * are entirely independent of the pool's memory management. * - * A small portion of memory will be allocated to register the information in the pool. - * If that allocation fails, this function will return non-zero. + * The destructor for the registered memory will be called after all pooled items have been freed. * * @param pool the pool * @param memory the object to register (MUST NOT be already allocated in the pool) @@ -156,6 +309,79 @@ cx_destructor_func destr ); + +/** + * Registers foreign memory with this pool. + * + * The destructor, in contrast to memory allocated by the pool, MUST free the memory. + * This function can be used with any pool of any type, since destructors for registered memory + * are entirely independent of the pool's memory management. + * + * The destructor for the registered memory will be called after all pooled items have been freed. + * + * @attention The data pointer MUST NOT be @c NULL. + * If you wish to register a destructor without additional data, use cxMempoolRegister(). + * + * @param pool the pool + * @param memory the object to register (MUST NOT be already allocated in the pool) + * @param destr the destructor function + * @param data additional data for the destructor function + * @retval zero success + * @retval non-zero failure + */ +cx_attr_nonnull +cx_attr_export +int cxMempoolRegister2( + CxMempool *pool, + void *memory, + cx_destructor_func2 destr, + void *data +); + +/** + * Transfers all the memory managed by one pool to another. + * + * The allocator of the source pool will also be transferred and registered with the destination pool + * and stays valid, as long as the destination pool is not destroyed. + * + * The source pool will get a completely new allocator and can be reused or destroyed afterward. + * + * This function fails when the destination pool has a different type than the source pool. + * + * @param source the pool to move the memory from + * @param dest the pool where to transfer the memory to + * @retval zero success + * @retval non-zero allocation failure or incompatible pools + */ +cx_attr_nonnull +cx_attr_export +int cxMempoolTransfer( + CxMempool *source, + CxMempool *dest +); + +/** + * Transfers an object from one pool to another. + * + * This function fails when the destination pool has a different type than the source pool. + * + * @attention If the object maintains a reference to the pool's allocator, + * you must make sure to update that reference to the allocator of the destination pool. + * + * @param source the pool to move the memory from + * @param dest the pool where to transfer the memory to + * @param obj pointer to the object that shall be transferred + * @retval zero success + * @retval non-zero failure, or the object was not found in the source pool, or the pools are incompatible + */ +cx_attr_nonnull +cx_attr_export +int cxMempoolTransferObject( + CxMempool *source, + CxMempool *dest, + const void *obj +); + #ifdef __cplusplus } // extern "C" #endif
--- a/ucx/cx/printf.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/cx/printf.h Sun Jul 20 22:04:39 2025 +0200 @@ -229,7 +229,7 @@ cx_attr_cstr_arg(4) cx_attr_export int cx_sprintf_a( - CxAllocator *alloc, + const CxAllocator *alloc, char **str, size_t *len, const char *fmt, @@ -274,7 +274,7 @@ cx_attr_access_rw(3) cx_attr_export int cx_vsprintf_a( - CxAllocator *alloc, + const CxAllocator *alloc, char **str, size_t *len, const char *fmt, @@ -333,7 +333,7 @@ cx_attr_access_rw(4) cx_attr_export int cx_sprintf_sa( - CxAllocator *alloc, + const CxAllocator *alloc, char *buf, size_t *len, char **str, @@ -388,7 +388,7 @@ cx_attr_cstr_arg(5) cx_attr_export int cx_vsprintf_sa( - CxAllocator *alloc, + const CxAllocator *alloc, char *buf, size_t *len, char **str,
--- a/ucx/cx/properties.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/cx/properties.h Sun Jul 20 22:04:39 2025 +0200 @@ -551,10 +551,12 @@ /** * Creates a properties sink for an UCX map. * - * The values stored in the map will be pointers to strings allocated - * by #cx_strdup_a(). - * The default stdlib allocator will be used, unless you specify a custom - * allocator in the optional @c data of the sink. + * The values stored in the map will be pointers to freshly allocated, + * zero-terminated C strings (@c char*), which means the @p map should have been + * created with #CX_STORE_POINTERS. + * + * The cxDefaultAllocator will be used unless you specify a custom + * allocator in the optional @c data field of the returned sink. * * @param map the map that shall consume the k/v-pairs. * @return the sink
--- a/ucx/cx/string.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/cx/string.h Sun Jul 20 22:04:39 2025 +0200 @@ -39,6 +39,12 @@ #include "common.h" #include "allocator.h" +/** Expands a UCX string as printf arguments. */ +#define CX_SFMT(s) (int) (s).length, (s).ptr + +/** Format specifier for a UCX string */ +#define CX_PRIstr ".*s" + /** * The maximum length of the "needle" in cx_strstr() that can use SBO. */ @@ -151,7 +157,7 @@ * * @param literal the string literal */ -#define CX_STR(literal) (cxstring){literal, sizeof(literal) - 1} +#define CX_STR(literal) ((cxstring){literal, sizeof(literal) - 1}) #endif @@ -299,7 +305,7 @@ #endif /** - * Passes the pointer in this string to @c free(). + * Passes the pointer in this string to the cxDefaultAllocator's @c free() function. * * The pointer in the struct is set to @c NULL and the length is set to zero * which means that this function protects you against double-free. @@ -334,6 +340,46 @@ ); /** + * Copies a string. + * + * The memory in the @p dest structure is either allocated or re-allocated to fit the entire + * source string, including a zero-terminator. + * + * The string in @p dest is guaranteed to be zero-terminated, regardless of whether @p src is. + * + * @param alloc the allocator + * @param dest a pointer to the structure where to copy the contents to + * @param src the source string + * + * @retval zero success + * @retval non-zero if re-allocation failed + */ +cx_attr_nonnull_arg(1) +cx_attr_export +int cx_strcpy_a( + const CxAllocator *alloc, + cxmutstr *dest, + cxstring src +); + + +/** + * Copies a string. + * + * The memory in the @p dest structure is either allocated or re-allocated to fit the entire + * source string, including a zero-terminator. + * + * The string in @p dest is guaranteed to be zero-terminated, regardless of whether @p src is. + * + * @param dest (@c cxmutstr*) a pointer to the structure where to copy the contents to + * @param src (@c cxstring) the source string + * + * @retval zero success + * @retval non-zero if re-allocation failed + */ +#define cx_strcpy(dest, src) cx_strcpy_a(cxDefaultAllocator, dest, src) + +/** * Returns the accumulated length of all specified strings. * * If this sum overflows, errno is set to EOVERFLOW. @@ -408,7 +454,7 @@ /** * Concatenates strings and returns a new string. * - * The resulting string will be allocated by standard @c malloc(). + * The resulting string will be allocated by the cxDefaultAllocator. * So developers @em must pass the return value to cx_strfree() eventually. * * If memory allocation fails, the pointer in the returned string will @@ -428,7 +474,7 @@ /** * Concatenates strings. * - * The resulting string will be allocated by standard @c malloc(). + * The resulting string will be allocated by the cxDefaultAllocator. * So developers @em must pass the return value to cx_strfree() eventually. * * If @p str already contains a string, the memory will be reallocated and @@ -879,13 +925,13 @@ * @see cx_strfree_a() */ #define cx_strdup_a(allocator, string) \ - cx_strdup_a_((allocator), cx_strcast((string))) + cx_strdup_a_((allocator), cx_strcast(string)) /** * Creates a duplicate of the specified string. * - * The new string will contain a copy allocated by standard - * @c malloc(). So developers @em must pass the return value to cx_strfree(). + * The new string will contain a copy allocated by the cxDefaultAllocator. + * So developers @em must pass the return value to cx_strfree(). * * @note The returned string is guaranteed to be zero-terminated. * @@ -894,7 +940,7 @@ * @see cx_strdup_a() * @see cx_strfree() */ -#define cx_strdup(string) cx_strdup_a_(cxDefaultAllocator, string) +#define cx_strdup(string) cx_strdup_a(cxDefaultAllocator, string) /** * Omits leading and trailing spaces. @@ -1016,7 +1062,7 @@ * * Replaces at most @p replmax occurrences. * - * The returned string will be allocated by @c malloc() and is guaranteed + * The returned string will be allocated by the cxDefaultAllocator and is guaranteed * to be zero-terminated. * * If allocation fails, or the input string is empty, @@ -1052,7 +1098,7 @@ /** * Replaces a string with another string. * - * The returned string will be allocated by @c malloc() and is guaranteed + * The returned string will be allocated by the cxDefaultAllocator and is guaranteed * to be zero-terminated. * * If allocation fails, or the input string is empty, @@ -1091,7 +1137,7 @@ * @return (@c CxStrtokCtx) a new string tokenization context */ #define cx_strtok(str, delim, limit) \ - cx_strtok_(cx_strcast((str)), cx_strcast((delim)), (limit)) + cx_strtok_(cx_strcast(str), cx_strcast(delim), (limit)) /** * Returns the next token.
--- a/ucx/cx/tree.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/cx/tree.h Sun Jul 20 22:04:39 2025 +0200 @@ -120,6 +120,7 @@ size_t stack_size; /** * The current depth in the tree. + * The node with which the iteration starts has depth 1. */ size_t depth; }; @@ -135,6 +136,7 @@ void *node; /** * The depth of the node. + * The first visited node has depth 1. */ size_t depth; /** @@ -211,7 +213,7 @@ */ cx_attr_nonnull static inline void cxTreeIteratorDispose(CxTreeIterator *iter) { - free(iter->stack); + cxFreeDefault(iter->stack); iter->stack = NULL; } @@ -224,7 +226,7 @@ struct cx_tree_visitor_queue_s *q = visitor->queue_next; while (q != NULL) { struct cx_tree_visitor_queue_s *next = q->next; - free(q); + cxFreeDefault(q); q = next; } } @@ -441,7 +443,7 @@ * Creates a depth-first iterator for a tree with the specified root node. * * @note A tree iterator needs to maintain a stack of visited nodes, which is - * allocated using stdlib malloc(). + * allocated using the cxDefaultAllocator. * When the iterator becomes invalid, this memory is automatically released. * However, if you wish to cancel the iteration before the iterator becomes * invalid by itself, you MUST call cxTreeIteratorDispose() manually to release @@ -469,8 +471,8 @@ /** * Creates a breadth-first iterator for a tree with the specified root node. * - * @note A tree visitor needs to maintain a queue of to be visited nodes, which - * is allocated using stdlib malloc(). + * @note A tree visitor needs to maintain a queue of to-be visited nodes, which + * is allocated using the cxDefaultAllocator. * When the visitor becomes invalid, this memory is automatically released. * However, if you wish to cancel the iteration before the visitor becomes * invalid by itself, you MUST call cxTreeVisitorDispose() manually to release @@ -956,7 +958,7 @@ * will free the nodes with the allocator's free() method. * * @param allocator the allocator that shall be used - * (if @c NULL, a default stdlib allocator will be used) + * (if @c NULL, the cxDefaultAllocator will be used) * @param create_func a function that creates new nodes * @param search_func a function that compares two nodes * @param search_data_func a function that compares a node with data @@ -1020,7 +1022,7 @@ * tree, you need to specify those functions afterwards. * * @param allocator the allocator that was used for nodes of the wrapped tree - * (if @c NULL, a default stdlib allocator is assumed) + * (if @c NULL, the cxDefaultAllocator is assumed) * @param root the root node of the tree that shall be wrapped * @param loc_parent offset in the node struct for the parent pointer * @param loc_children offset in the node struct for the children linked list @@ -1188,6 +1190,18 @@ size_t cxTreeSubtreeDepth(CxTree *tree, void *subtree_root); /** + * Determines the size of the entire tree. + * + * @param tree the tree + * @return the tree size, counting the root as one + */ +cx_attr_nonnull +cx_attr_nodiscard +static inline size_t cxTreeSize(CxTree *tree) { + return tree->size; +} + +/** * Determines the depth of the entire tree. * * @param tree the tree
--- a/ucx/json.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/json.c Sun Jul 20 22:04:39 2025 +0200 @@ -500,7 +500,7 @@ if (all_printable && escape) { size_t capa = str.length + 32; - char *space = malloc(capa); + char *space = cxMallocDefault(capa); if (space == NULL) return cx_mutstrn(NULL, 0); cxBufferInit(&buf, space, capa, NULL, CX_BUFFER_AUTO_EXTEND); cxBufferWrite(str.ptr, 1, i, &buf); @@ -631,10 +631,10 @@ void cxJsonDestroy(CxJson *json) { cxBufferDestroy(&json->buffer); if (json->states != json->states_internal) { - free(json->states); + cxFreeDefault(json->states); } if (json->vbuf != json->vbuf_internal) { - free(json->vbuf); + cxFreeDefault(json->vbuf); } cxJsonValueFree(json->parsed); json->parsed = NULL; @@ -984,67 +984,67 @@ if (values[i] == NULL) break; cxJsonValueFree(values[i]); } - free(values); + cxFreeDefault(values); } // LCOV_EXCL_STOP int cxJsonArrAddNumbers(CxJsonValue* arr, const double* num, size_t count) { - CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); + CxJsonValue** values = cxCallocDefault(count, sizeof(CxJsonValue*)); if (values == NULL) return -1; for (size_t i = 0; i < count; i++) { values[i] = cxJsonCreateNumber(arr->allocator, num[i]); if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } } int ret = cxJsonArrAddValues(arr, values, count); - free(values); + cxFreeDefault(values); return ret; } int cxJsonArrAddIntegers(CxJsonValue* arr, const int64_t* num, size_t count) { - CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); + CxJsonValue** values = cxCallocDefault(count, sizeof(CxJsonValue*)); if (values == NULL) return -1; for (size_t i = 0; i < count; i++) { values[i] = cxJsonCreateInteger(arr->allocator, num[i]); if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } } int ret = cxJsonArrAddValues(arr, values, count); - free(values); + cxFreeDefault(values); return ret; } int cxJsonArrAddStrings(CxJsonValue* arr, const char* const* str, size_t count) { - CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); + CxJsonValue** values = cxCallocDefault(count, sizeof(CxJsonValue*)); if (values == NULL) return -1; for (size_t i = 0; i < count; i++) { values[i] = cxJsonCreateString(arr->allocator, str[i]); if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } } int ret = cxJsonArrAddValues(arr, values, count); - free(values); + cxFreeDefault(values); return ret; } int cxJsonArrAddCxStrings(CxJsonValue* arr, const cxstring* str, size_t count) { - CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); + CxJsonValue** values = cxCallocDefault(count, sizeof(CxJsonValue*)); if (values == NULL) return -1; for (size_t i = 0; i < count; i++) { values[i] = cxJsonCreateCxString(arr->allocator, str[i]); if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } } int ret = cxJsonArrAddValues(arr, values, count); - free(values); + cxFreeDefault(values); return ret; } int cxJsonArrAddLiterals(CxJsonValue* arr, const CxJsonLiteral* lit, size_t count) { - CxJsonValue** values = calloc(count, sizeof(CxJsonValue*)); + CxJsonValue** values = cxCallocDefault(count, sizeof(CxJsonValue*)); if (values == NULL) return -1; for (size_t i = 0; i < count; i++) { values[i] = cxJsonCreateLiteral(arr->allocator, lit[i]); if (values[i] == NULL) { json_arr_free_temp(values, count); return -1; } } int ret = cxJsonArrAddValues(arr, values, count); - free(values); + cxFreeDefault(values); return ret; }
--- a/ucx/linked_list.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/linked_list.c Sun Jul 20 22:04:39 2025 +0200 @@ -401,7 +401,7 @@ ) { void *sbo[CX_LINKED_LIST_SORT_SBO_SIZE]; void **sorted = length >= CX_LINKED_LIST_SORT_SBO_SIZE ? - malloc(sizeof(void *) * length) : sbo; + cxMallocDefault(sizeof(void *) * length) : sbo; if (sorted == NULL) abort(); void *rc, *lc; @@ -439,7 +439,7 @@ *begin = sorted[0]; *end = sorted[length - 1]; if (sorted != sbo) { - free(sorted); + cxFreeDefault(sorted); } } @@ -613,7 +613,9 @@ // initialize new new_node new_node->prev = new_node->next = NULL; - memcpy(new_node->payload, elem, list->collection.elem_size); + if (elem != NULL) { + memcpy(new_node->payload, elem, list->collection.elem_size); + } // insert cx_linked_list *ll = (cx_linked_list *) list; @@ -659,12 +661,26 @@ return n; } -static int cx_ll_insert_element( +static void *cx_ll_insert_element( struct cx_list_s *list, size_t index, const void *element ) { - return 1 != cx_ll_insert_array(list, index, element, 1); + // out-of-bounds check + if (index > list->collection.size) return NULL; + + // find position efficiently + cx_linked_list_node *node = index == 0 ? NULL : cx_ll_node_at((cx_linked_list *) list, index - 1); + + // perform first insert + if (cx_ll_insert_at(list, node, element)) return NULL; + + // return a pointer to the data of the inserted node + if (node == NULL) { + return ((cx_linked_list *) list)->begin->payload; + } else { + return node->next->payload; + } } static _Thread_local cx_compare_func cx_ll_insert_sorted_cmp_func; @@ -920,6 +936,8 @@ const void *elem, bool remove ) { + if (list->collection.size == 0) return 0; + size_t index; cx_linked_list *ll = ((cx_linked_list *) list); cx_linked_list_node *node = cx_linked_list_find( @@ -1054,12 +1072,12 @@ } return result; } else { - int result = cx_ll_insert_element(list, list->collection.size, elem); - if (result == 0) { - iter->elem_count++; - iter->index = list->collection.size; + if (cx_ll_insert_element(list, list->collection.size, elem) == NULL) { + return 1; } - return result; + iter->elem_count++; + iter->index = list->collection.size; + return 0; } }
--- a/ucx/list.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/list.c Sun Jul 20 22:04:39 2025 +0200 @@ -62,7 +62,7 @@ list->climpl->deallocate(list); } -static int cx_pl_insert_element( +static void *cx_pl_insert_element( struct cx_list_s *list, size_t index, const void *element @@ -282,7 +282,7 @@ const char *src = data; size_t i = 0; for (; i < n; i++) { - if (0 != invoke_list_func( + if (NULL == invoke_list_func( insert_element, list, index + i, src + (i * elem_size))) return i; } @@ -329,7 +329,7 @@ // insert the elements at location si if (ins == 1) { - if (0 != invoke_list_func( + if (NULL == invoke_list_func( insert_element, list, di, src)) return inserted; } else { size_t r = invoke_list_func(insert_array, list, di, src, ins); @@ -354,7 +354,7 @@ void cx_list_default_sort(struct cx_list_s *list) { size_t elem_size = list->collection.elem_size; size_t list_size = list->collection.size; - void *tmp = malloc(elem_size * list_size); + void *tmp = cxMallocDefault(elem_size * list_size); if (tmp == NULL) abort(); // copy elements from source array @@ -377,7 +377,7 @@ loc += elem_size; } - free(tmp); + cxFreeDefault(tmp); } int cx_list_default_swap(struct cx_list_s *list, size_t i, size_t j) { @@ -387,7 +387,7 @@ size_t elem_size = list->collection.elem_size; - void *tmp = malloc(elem_size); + void *tmp = cxMallocDefault(elem_size); if (tmp == NULL) return 1; void *ip = invoke_list_func(at, list, i); @@ -397,7 +397,7 @@ memcpy(ip, jp, elem_size); memcpy(jp, tmp, elem_size); - free(tmp); + cxFreeDefault(tmp); return 0; } @@ -494,3 +494,24 @@ if (list == NULL) return; list->cl->deallocate(list); } + +int cxListSet( + CxList *list, + size_t index, + const void *elem +) { + if (index >= list->collection.size) { + return 1; + } + + if (list->collection.store_pointer) { + // For pointer collections, always use climpl + void **target = list->climpl->at(list, index); + *target = (void *)elem; + } else { + void *target = list->cl->at(list, index); + memcpy(target, elem, list->collection.elem_size); + } + + return 0; +}
--- a/ucx/mempool.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/mempool.c Sun Jul 20 22:04:39 2025 +0200 @@ -31,44 +31,69 @@ #include <string.h> #include <errno.h> -struct cx_mempool_memory_s { - /** The destructor. */ - cx_destructor_func destructor; - /** The actual memory. */ - char c[]; -}; +static int cx_mempool_ensure_capacity( + struct cx_mempool_s *pool, + size_t needed_capacity +) { + if (needed_capacity <= pool->capacity) return 0; + size_t newcap = pool->capacity >= 1000 ? + pool->capacity + 1000 : pool->capacity * 2; + size_t newmsize; + // LCOV_EXCL_START + if (pool->capacity > newcap + || cx_szmul(newcap, sizeof(void*), &newmsize)) { + errno = EOVERFLOW; + return 1; + } // LCOV_EXCL_STOP + void **newdata = cxRealloc(pool->base_allocator, pool->data, newmsize); + if (newdata == NULL) return 1; + pool->data = newdata; + pool->capacity = newcap; + return 0; +} -static void *cx_mempool_malloc( +static int cx_mempool_ensure_registered_capacity( + struct cx_mempool_s *pool, + size_t needed_capacity +) { + if (needed_capacity <= pool->registered_capacity) return 0; + // we do not expect so many registrations + size_t newcap = pool->registered_capacity + 8; + size_t newmsize; + // LCOV_EXCL_START + if (pool->registered_capacity > newcap || cx_szmul(newcap, + sizeof(struct cx_mempool_foreign_memory_s), &newmsize)) { + errno = EOVERFLOW; + return 1; + } // LCOV_EXCL_STOP + void *newdata = cxRealloc(pool->base_allocator, pool->registered, newmsize); + if (newdata == NULL) return 1; + pool->registered = newdata; + pool->registered_capacity = newcap; + return 0; +} + +static void *cx_mempool_malloc_simple( void *p, size_t n ) { struct cx_mempool_s *pool = p; - if (pool->size >= pool->capacity) { - size_t newcap = pool->capacity - (pool->capacity % 16) + 16; - size_t newmsize; - if (pool->capacity > newcap || cx_szmul(newcap, - sizeof(struct cx_mempool_memory_s*), &newmsize)) { - errno = EOVERFLOW; - return NULL; - } - struct cx_mempool_memory_s **newdata = realloc(pool->data, newmsize); - if (newdata == NULL) return NULL; - pool->data = newdata; - pool->capacity = newcap; + if (cx_mempool_ensure_capacity(pool, pool->size + 1)) { + return NULL; // LCOV_EXCL_LINE } - struct cx_mempool_memory_s *mem = malloc(sizeof(cx_destructor_func) + n); + struct cx_mempool_memory_s *mem = + cxMalloc(pool->base_allocator, sizeof(struct cx_mempool_memory_s) + n); if (mem == NULL) return NULL; - - mem->destructor = pool->auto_destr; + mem->destructor = NULL; pool->data[pool->size] = mem; pool->size++; return mem->c; } -static void *cx_mempool_calloc( +static void *cx_mempool_calloc_simple( void *p, size_t nelem, size_t elsize @@ -78,53 +103,165 @@ errno = EOVERFLOW; return NULL; } - void *ptr = cx_mempool_malloc(p, msz); + void *ptr = cx_mempool_malloc_simple(p, msz); if (ptr == NULL) return NULL; memset(ptr, 0, nelem * elsize); return ptr; } -static void *cx_mempool_realloc( +static void cx_mempool_free_simple( + void *p, + void *ptr +) { + if (!ptr) return; + struct cx_mempool_s *pool = p; + + struct cx_mempool_memory_s *mem = + (void*) ((char *) ptr - sizeof(struct cx_mempool_memory_s)); + + for (size_t i = 0; i < pool->size; i++) { + if (mem == pool->data[i]) { + if (mem->destructor) { + mem->destructor(mem->c); + } + if (pool->destr) { + pool->destr(mem->c); + } + if (pool->destr2) { + pool->destr2(pool->destr2_data, mem->c); + } + cxFree(pool->base_allocator, mem); + size_t last_index = pool->size - 1; + if (i != last_index) { + pool->data[i] = pool->data[last_index]; + pool->data[last_index] = NULL; + } + pool->size--; + return; + } + } + abort(); // LCOV_EXCL_LINE +} + +static void *cx_mempool_realloc_simple( void *p, void *ptr, size_t n ) { + if (ptr == NULL) { + return cx_mempool_malloc_simple(p, n); + } + if (n == 0) { + cx_mempool_free_simple(p, ptr); + return NULL; + } struct cx_mempool_s *pool = p; - struct cx_mempool_memory_s *mem, *newm; - mem = (struct cx_mempool_memory_s*)(((char *) ptr) - sizeof(cx_destructor_func)); - newm = realloc(mem, n + sizeof(cx_destructor_func)); + const unsigned overhead = sizeof(struct cx_mempool_memory_s); + struct cx_mempool_memory_s *mem = + (void *) (((char *) ptr) - overhead); + struct cx_mempool_memory_s *newm = + cxRealloc(pool->base_allocator, mem, n + overhead); if (newm == NULL) return NULL; if (mem != newm) { for (size_t i = 0; i < pool->size; i++) { if (pool->data[i] == mem) { pool->data[i] = newm; - return ((char*)newm) + sizeof(cx_destructor_func); + return ((char*)newm) + overhead; } } abort(); // LCOV_EXCL_LINE } else { - return ptr; + // unfortunately glibc() realloc seems to always move + return ptr; // LCOV_EXCL_LINE + } +} + +static void cx_mempool_free_all_simple(const struct cx_mempool_s *pool) { + const bool has_destr = pool->destr; + const bool has_destr2 = pool->destr2; + for (size_t i = 0; i < pool->size; i++) { + struct cx_mempool_memory_s *mem = pool->data[i]; + if (mem->destructor) { + mem->destructor(mem->c); + } + if (has_destr) { + pool->destr(mem->c); + } + if (has_destr2) { + pool->destr2(pool->destr2_data, mem->c); + } + cxFree(pool->base_allocator, mem); } } -static void cx_mempool_free( +static cx_allocator_class cx_mempool_simple_allocator_class = { + cx_mempool_malloc_simple, + cx_mempool_realloc_simple, + cx_mempool_calloc_simple, + cx_mempool_free_simple +}; + +static void *cx_mempool_malloc_advanced( + void *p, + size_t n +) { + struct cx_mempool_s *pool = p; + + if (cx_mempool_ensure_capacity(pool, pool->size + 1)) { + return NULL; // LCOV_EXCL_LINE + } + + struct cx_mempool_memory2_s *mem = + cxMalloc(pool->base_allocator, sizeof(struct cx_mempool_memory2_s) + n); + if (mem == NULL) return NULL; + mem->destructor = NULL; + mem->data = NULL; + pool->data[pool->size] = mem; + pool->size++; + + return mem->c; +} + +static void *cx_mempool_calloc_advanced( + void *p, + size_t nelem, + size_t elsize +) { + size_t msz; + if (cx_szmul(nelem, elsize, &msz)) { + errno = EOVERFLOW; + return NULL; + } + void *ptr = cx_mempool_malloc_advanced(p, msz); + if (ptr == NULL) return NULL; + memset(ptr, 0, nelem * elsize); + return ptr; +} + +static void cx_mempool_free_advanced( void *p, void *ptr ) { if (!ptr) return; struct cx_mempool_s *pool = p; - struct cx_mempool_memory_s *mem = (struct cx_mempool_memory_s *) - ((char *) ptr - sizeof(cx_destructor_func)); + struct cx_mempool_memory2_s *mem = + (void*) ((char *) ptr - sizeof(struct cx_mempool_memory2_s)); for (size_t i = 0; i < pool->size; i++) { if (mem == pool->data[i]) { if (mem->destructor) { - mem->destructor(mem->c); + mem->destructor(mem->data, mem->c); + } + if (pool->destr) { + pool->destr(mem->c); } - free(mem); + if (pool->destr2) { + pool->destr2(pool->destr2_data, mem->c); + } + cxFree(pool->base_allocator, mem); size_t last_index = pool->size - 1; if (i != last_index) { pool->data[i] = pool->data[last_index]; @@ -137,19 +274,207 @@ abort(); // LCOV_EXCL_LINE } +static void *cx_mempool_realloc_advanced( + void *p, + void *ptr, + size_t n +) { + if (ptr == NULL) { + return cx_mempool_malloc_advanced(p, n); + } + if (n == 0) { + cx_mempool_free_advanced(p, ptr); + return NULL; + } + struct cx_mempool_s *pool = p; + + const unsigned overhead = sizeof(struct cx_mempool_memory2_s); + struct cx_mempool_memory2_s *mem = + (void *) (((char *) ptr) - overhead); + struct cx_mempool_memory2_s *newm = + cxRealloc(pool->base_allocator, mem, n + overhead); + + if (newm == NULL) return NULL; + if (mem != newm) { + for (size_t i = 0; i < pool->size; i++) { + if (pool->data[i] == mem) { + pool->data[i] = newm; + return ((char*)newm) + overhead; + } + } + abort(); // LCOV_EXCL_LINE + } else { + // unfortunately glibc() realloc seems to always move + return ptr; // LCOV_EXCL_LINE + } +} + +static void cx_mempool_free_all_advanced(const struct cx_mempool_s *pool) { + const bool has_destr = pool->destr; + const bool has_destr2 = pool->destr2; + for (size_t i = 0; i < pool->size; i++) { + struct cx_mempool_memory2_s *mem = pool->data[i]; + if (mem->destructor) { + mem->destructor(mem->data, mem->c); + } + if (has_destr) { + pool->destr(mem->c); + } + if (has_destr2) { + pool->destr2(pool->destr2_data, mem->c); + } + cxFree(pool->base_allocator, mem); + } +} + +static cx_allocator_class cx_mempool_advanced_allocator_class = { + cx_mempool_malloc_advanced, + cx_mempool_realloc_advanced, + cx_mempool_calloc_advanced, + cx_mempool_free_advanced +}; + + +static void *cx_mempool_malloc_pure( + void *p, + size_t n +) { + struct cx_mempool_s *pool = p; + + if (cx_mempool_ensure_capacity(pool, pool->size + 1)) { + return NULL; // LCOV_EXCL_LINE + } + + void *mem = cxMalloc(pool->base_allocator, n); + if (mem == NULL) return NULL; + pool->data[pool->size] = mem; + pool->size++; + + return mem; +} + +static void *cx_mempool_calloc_pure( + void *p, + size_t nelem, + size_t elsize +) { + size_t msz; + if (cx_szmul(nelem, elsize, &msz)) { + errno = EOVERFLOW; + return NULL; + } + void *ptr = cx_mempool_malloc_pure(p, msz); + if (ptr == NULL) return NULL; + memset(ptr, 0, nelem * elsize); + return ptr; +} + +static void cx_mempool_free_pure( + void *p, + void *ptr +) { + if (!ptr) return; + struct cx_mempool_s *pool = p; + + for (size_t i = 0; i < pool->size; i++) { + if (ptr == pool->data[i]) { + if (pool->destr) { + pool->destr(ptr); + } + if (pool->destr2) { + pool->destr2(pool->destr2_data, ptr); + } + cxFree(pool->base_allocator, ptr); + size_t last_index = pool->size - 1; + if (i != last_index) { + pool->data[i] = pool->data[last_index]; + pool->data[last_index] = NULL; + } + pool->size--; + return; + } + } + abort(); // LCOV_EXCL_LINE +} + +static void *cx_mempool_realloc_pure( + void *p, + void *ptr, + size_t n +) { + if (ptr == NULL) { + return cx_mempool_malloc_pure(p, n); + } + if (n == 0) { + cx_mempool_free_pure(p, ptr); + return NULL; + } + struct cx_mempool_s *pool = p; + void *newm = cxRealloc(pool->base_allocator, ptr, n); + if (newm == NULL) return NULL; + if (ptr != newm) { + for (size_t i = 0; i < pool->size; i++) { + if (pool->data[i] == ptr) { + pool->data[i] = newm; + return newm; + } + } + abort(); // LCOV_EXCL_LINE + } else { + // unfortunately glibc() realloc seems to always move + return ptr; // LCOV_EXCL_LINE + } +} + +static void cx_mempool_free_all_pure(const struct cx_mempool_s *pool) { + const bool has_destr = pool->destr; + const bool has_destr2 = pool->destr2; + for (size_t i = 0; i < pool->size; i++) { + void *mem = pool->data[i]; + if (has_destr) { + pool->destr(mem); + } + if (has_destr2) { + pool->destr2(pool->destr2_data, mem); + } + cxFree(pool->base_allocator, mem); + } +} + +static cx_allocator_class cx_mempool_pure_allocator_class = { + cx_mempool_malloc_pure, + cx_mempool_realloc_pure, + cx_mempool_calloc_pure, + cx_mempool_free_pure +}; + +static void cx_mempool_free_foreign(const struct cx_mempool_s *pool) { + for (size_t i = 0; i < pool->registered_size; i++) { + struct cx_mempool_foreign_memory_s info = pool->registered[i]; + if (info.destr2_data == NULL) { + if (info.destr) { + info.destr(info.mem); + } + } else { + info.destr2(info.destr2_data, info.mem); + } + } +} + void cxMempoolFree(CxMempool *pool) { if (pool == NULL) return; - struct cx_mempool_memory_s *mem; - for (size_t i = 0; i < pool->size; i++) { - mem = pool->data[i]; - if (mem->destructor) { - mem->destructor(mem->c); - } - free(mem); + if (pool->allocator->cl == &cx_mempool_simple_allocator_class) { + cx_mempool_free_all_simple(pool); + } else if (pool->allocator->cl == &cx_mempool_advanced_allocator_class) { + cx_mempool_free_all_advanced(pool); + } else { + cx_mempool_free_all_pure(pool); } - free(pool->data); - free((void*) pool->allocator); - free(pool); + cx_mempool_free_foreign(pool); + cxFree(pool->base_allocator, pool->data); + cxFree(pool->base_allocator, pool->registered); + cxFree(pool->base_allocator, (void*) pool->allocator); + cxFree(pool->base_allocator, pool); } void cxMempoolSetDestructor( @@ -159,18 +484,26 @@ *(cx_destructor_func *) ((char *) ptr - sizeof(cx_destructor_func)) = func; } +void cxMempoolSetDestructor2( + void *ptr, + cx_destructor_func2 func, + void *data +) { + struct cx_mempool_memory2_s *info = + (void*)((char *) ptr - sizeof(struct cx_mempool_memory2_s)); + info->destructor = func; + info->data = data; +} + void cxMempoolRemoveDestructor(void *ptr) { *(cx_destructor_func *) ((char *) ptr - sizeof(cx_destructor_func)) = NULL; } -struct cx_mempool_foreign_mem_s { - cx_destructor_func destr; - void* mem; -}; - -static void cx_mempool_destr_foreign_mem(void* ptr) { - struct cx_mempool_foreign_mem_s *fm = ptr; - fm->destr(fm->mem); +void cxMempoolRemoveDestructor2(void *ptr) { + struct cx_mempool_memory2_s *info = + (void*)((char *) ptr - sizeof(struct cx_mempool_memory2_s)); + info->destructor = NULL; + info->data = NULL; } int cxMempoolRegister( @@ -178,60 +511,206 @@ void *memory, cx_destructor_func destr ) { - struct cx_mempool_foreign_mem_s *fm = cx_mempool_malloc( - pool, - sizeof(struct cx_mempool_foreign_mem_s) - ); - if (fm == NULL) return 1; + if (cx_mempool_ensure_registered_capacity(pool, pool->registered_size + 1)) { + return 1; // LCOV_EXCL_LINE + } + + pool->registered[pool->registered_size++] = + (struct cx_mempool_foreign_memory_s) { + .mem = memory, + .destr = destr, + .destr2_data = NULL + }; + + return 0; +} - fm->mem = memory; - fm->destr = destr; - *(cx_destructor_func *) ((char *) fm - sizeof(cx_destructor_func)) = cx_mempool_destr_foreign_mem; +int cxMempoolRegister2( + CxMempool *pool, + void *memory, + cx_destructor_func2 destr, + void *data +) { + if (cx_mempool_ensure_registered_capacity(pool, pool->registered_size + 1)) { + return 1; // LCOV_EXCL_LINE + } + + pool->registered[pool->registered_size++] = + (struct cx_mempool_foreign_memory_s) { + .mem = memory, + .destr2 = destr, + .destr2_data = data + }; return 0; } -static cx_allocator_class cx_mempool_allocator_class = { - cx_mempool_malloc, - cx_mempool_realloc, - cx_mempool_calloc, - cx_mempool_free -}; - CxMempool *cxMempoolCreate( size_t capacity, - cx_destructor_func destr + enum cx_mempool_type type ) { + if (capacity == 0) capacity = 16; size_t poolsize; - if (cx_szmul(capacity, sizeof(struct cx_mempool_memory_s*), &poolsize)) { + if (cx_szmul(capacity, sizeof(void*), &poolsize)) { + // LCOV_EXCL_START errno = EOVERFLOW; return NULL; + } // LCOV_EXCL_STOP + + CxAllocator *provided_allocator = cxMallocDefault(sizeof(CxAllocator)); + if (provided_allocator == NULL) { // LCOV_EXCL_START + return NULL; + } // LCOV_EXCL_STOP + + CxMempool *pool = cxCallocDefault(1, sizeof(CxMempool)); + if (pool == NULL) { // LCOV_EXCL_START + cxFreeDefault(provided_allocator); + return NULL; + } // LCOV_EXCL_STOP + + provided_allocator->data = pool; + *((const CxAllocator**)&pool->base_allocator) = cxDefaultAllocator; + pool->allocator = provided_allocator; + if (type == CX_MEMPOOL_TYPE_SIMPLE) { + provided_allocator->cl = &cx_mempool_simple_allocator_class; + } else if (type == CX_MEMPOOL_TYPE_ADVANCED) { + provided_allocator->cl = &cx_mempool_advanced_allocator_class; + } else { + provided_allocator->cl = &cx_mempool_pure_allocator_class; } - struct cx_mempool_s *pool = - malloc(sizeof(struct cx_mempool_s)); - if (pool == NULL) return NULL; - - CxAllocator *provided_allocator = malloc(sizeof(CxAllocator)); - if (provided_allocator == NULL) { // LCOV_EXCL_START - free(pool); - return NULL; - } // LCOV_EXCL_STOP - provided_allocator->cl = &cx_mempool_allocator_class; - provided_allocator->data = pool; - - pool->allocator = provided_allocator; - - pool->data = malloc(poolsize); + pool->data = cxMallocDefault(poolsize); if (pool->data == NULL) { // LCOV_EXCL_START - free(provided_allocator); - free(pool); + cxFreeDefault(provided_allocator); + cxFreeDefault(pool); return NULL; } // LCOV_EXCL_STOP pool->size = 0; pool->capacity = capacity; - pool->auto_destr = destr; return pool; } + +void cxMempoolGlobalDestructor(CxMempool *pool, cx_destructor_func fnc) { + pool->destr = fnc; +} + +void cxMempoolGlobalDestructor2(CxMempool *pool, cx_destructor_func2 fnc, void *data) { + pool->destr2 = fnc; + pool->destr2_data = data; +} + +static void cx_mempool_free_transferred_allocator(void *base_al, void *al) { + cxFree(base_al, al); +} + +int cxMempoolTransfer( + CxMempool *source, + CxMempool *dest +) { + // safety checks + if (source == dest) return 1; + if (source->allocator->cl != dest->allocator->cl) return 1; + if (source->base_allocator->cl != dest->base_allocator->cl) return 1; + + // ensure enough capacity in the destination pool + if (cx_mempool_ensure_capacity(dest, dest->size + source->size)) { + return 1; // LCOV_EXCL_LINE + } + if (cx_mempool_ensure_registered_capacity(dest, + dest->registered_size + source->registered_size)) { + return 1; // LCOV_EXCL_LINE + } + + // allocate a replacement allocator for the source pool + CxAllocator *new_source_allocator = + cxMalloc(source->base_allocator, sizeof(CxAllocator)); + if (new_source_allocator == NULL) { // LCOV_EXCL_START + return 1; + } // LCOV_EXCL_STOP + new_source_allocator->cl = source->allocator->cl; + new_source_allocator->data = source; + + // transfer all the data + memcpy(&dest->data[dest->size], source->data, sizeof(void*)*source->size); + dest->size += source->size; + + // transfer all registered memory + memcpy(&dest->registered[dest->registered_size], source->registered, + sizeof(struct cx_mempool_foreign_memory_s) * source->registered_size); + dest->registered_size += source->registered_size; + + // register the old allocator with the new pool + // we have to remove const-ness for this, but that's okay here + // also register the base allocator, s.t. the pool knows how to free it + CxAllocator *transferred_allocator = (CxAllocator*) source->allocator; + transferred_allocator->data = dest; + cxMempoolRegister2(dest, transferred_allocator, + cx_mempool_free_transferred_allocator, (void*)source->base_allocator); + + // prepare the source pool for re-use + source->allocator = new_source_allocator; + memset(source->data, 0, source->size * sizeof(void*)); + memset(source->registered, 0, + source->registered_size * sizeof(struct cx_mempool_foreign_memory_s)); + source->size = 0; + source->registered_size = 0; + + return 0; +} + +int cxMempoolTransferObject( + CxMempool *source, + CxMempool *dest, + const void *obj +) { + // safety checks + if (source == dest) return 1; + if (source->allocator->cl != dest->allocator->cl) return 1; + if (source->base_allocator->cl != dest->base_allocator->cl) return 1; + + // search for the object + for (size_t i = 0; i < source->size; i++) { + struct cx_mempool_memory_s *mem = source->data[i]; + if (mem->c == obj) { + // first, make sure that the dest pool can take the object + if (cx_mempool_ensure_capacity(dest, dest->size + 1)) { + return 1; // LCOV_EXCL_LINE + } + // remove from the source pool + size_t last_index = source->size - 1; + if (i != last_index) { + source->data[i] = source->data[last_index]; + source->data[last_index] = NULL; + } + source->size--; + // add to the target pool + dest->data[dest->size++] = mem; + return 0; + } + } + // search in the registered objects + for (size_t i = 0; i < source->registered_size; i++) { + struct cx_mempool_foreign_memory_s *mem = &source->registered[i]; + if (mem->mem == obj) { + // first, make sure that the dest pool can take the object + if (cx_mempool_ensure_registered_capacity(dest, + dest->registered_size + 1)) { + return 1; // LCOV_EXCL_LINE + } + dest->registered[dest->registered_size++] = *mem; + // remove from the source pool + size_t last_index = source->registered_size - 1; + if (i != last_index) { + source->registered[i] = source->registered[last_index]; + memset(&source->registered[last_index], 0, + sizeof(struct cx_mempool_foreign_memory_s)); + } + source->registered_size--; + return 0; + } + } + // not found + return 1; +}
--- a/ucx/printf.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/printf.c Sun Jul 20 22:04:39 2025 +0200 @@ -68,7 +68,7 @@ return (int) wfc(buf, 1, ret, stream); } else { int len = ret + 1; - char *newbuf = malloc(len); + char *newbuf = cxMallocDefault(len); if (!newbuf) { // LCOV_EXCL_START va_end(ap2); return -1; @@ -79,7 +79,7 @@ if (ret > 0) { ret = (int) wfc(newbuf, 1, ret, stream); } - free(newbuf); + cxFreeDefault(newbuf); } return ret; } @@ -121,7 +121,7 @@ if (s.ptr) { ret = vsnprintf(s.ptr, len, fmt, ap2); if (ret < 0) { - free(s.ptr); + cxFree(a, s.ptr); s.ptr = NULL; } else { s.length = (size_t) ret; @@ -132,7 +132,13 @@ return s; } -int cx_sprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, ... ) { +int cx_sprintf_a( + const CxAllocator *alloc, + char **str, + size_t *len, + const char *fmt, + ... +) { va_list ap; va_start(ap, fmt); int ret = cx_vsprintf_a(alloc, str, len, fmt, ap); @@ -140,7 +146,13 @@ return ret; } -int cx_vsprintf_a(CxAllocator *alloc, char **str, size_t *len, const char *fmt, va_list ap) { +int cx_vsprintf_a( + const CxAllocator *alloc, + char **str, + size_t *len, + const char *fmt, + va_list ap +) { va_list ap2; va_copy(ap2, ap); int ret = vsnprintf(*str, *len, fmt, ap); @@ -162,7 +174,14 @@ return ret; } -int cx_sprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, ... ) { +int cx_sprintf_sa( + const CxAllocator *alloc, + char *buf, + size_t *len, + char **str, + const char *fmt, + ... +) { va_list ap; va_start(ap, fmt); int ret = cx_vsprintf_sa(alloc, buf, len, str, fmt, ap); @@ -170,7 +189,14 @@ return ret; } -int cx_vsprintf_sa(CxAllocator *alloc, char *buf, size_t *len, char **str, const char *fmt, va_list ap) { +int cx_vsprintf_sa( + const CxAllocator *alloc, + char *buf, + size_t *len, + char **str, + const char *fmt, + va_list ap +) { va_list ap2; va_copy(ap2, ap); int ret = vsnprintf(buf, *len, fmt, ap);
--- a/ucx/properties.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/properties.c Sun Jul 20 22:04:39 2025 +0200 @@ -287,7 +287,7 @@ cx_attr_unused CxProperties *prop, CxPropertiesSource *src ) { - src->data_ptr = malloc(src->data_size); + src->data_ptr = cxMallocDefault(src->data_size); if (src->data_ptr == NULL) return 1; return 0; } @@ -296,7 +296,7 @@ cx_attr_unused CxProperties *prop, CxPropertiesSource *src ) { - free(src->data_ptr); + cxFreeDefault(src->data_ptr); } CxPropertiesSource cxPropertiesStringSource(cxstring str) {
--- a/ucx/streams.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/streams.c Sun Jul 20 22:04:39 2025 +0200 @@ -27,6 +27,7 @@ */ #include "cx/streams.h" +#include "cx/allocator.h" #ifndef CX_STREAM_BCOPY_BUF_SIZE #define CX_STREAM_BCOPY_BUF_SIZE 8192 @@ -57,7 +58,7 @@ lbuf = buf; } else { if (bufsize == 0) bufsize = CX_STREAM_BCOPY_BUF_SIZE; - lbuf = malloc(bufsize); + lbuf = cxMallocDefault(bufsize); if (lbuf == NULL) return 0; } @@ -74,7 +75,7 @@ } if (lbuf != buf) { - free(lbuf); + cxFreeDefault(lbuf); } return ncp;
--- a/ucx/string.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/string.c Sun Jul 20 22:04:39 2025 +0200 @@ -65,7 +65,7 @@ void cx_strfree(cxmutstr *str) { if (str == NULL) return; - free(str->ptr); + cxFreeDefault(str->ptr); str->ptr = NULL; str->length = 0; } @@ -80,6 +80,22 @@ str->length = 0; } +int cx_strcpy_a( + const CxAllocator *alloc, + cxmutstr *dest, + cxstring src +) { + if (cxReallocate(alloc, &dest->ptr, src.length + 1)) { + return 1; + } + + memcpy(dest->ptr, src.ptr, src.length); + dest->length = src.length; + dest->ptr[dest->length] = '\0'; + + return 0; +} + size_t cx_strlen( size_t count, ... @@ -106,27 +122,16 @@ ... ) { if (count == 0) return str; - - cxstring strings_stack[8]; - cxstring *strings; - if (count > 8) { - strings = calloc(count, sizeof(cxstring)); - if (strings == NULL) { - return (cxmutstr) {NULL, 0}; - } - } else { - strings = strings_stack; - } - va_list ap; va_start(ap, count); + va_list ap2; + va_copy(ap2, ap); - // get all args and overall length + // compute overall length bool overflow = false; size_t slen = str.length; for (size_t i = 0; i < count; i++) { - cxstring s = va_arg (ap, cxstring); - strings[i] = s; + cxstring s = va_arg(ap, cxstring); if (slen > SIZE_MAX - str.length) overflow = true; slen += s.length; } @@ -134,10 +139,8 @@ // abort in case of overflow if (overflow) { + va_end(ap2); errno = EOVERFLOW; - if (strings != strings_stack) { - free(strings); - } return (cxmutstr) { NULL, 0 }; } @@ -149,9 +152,7 @@ newstr = cxRealloc(alloc, str.ptr, slen + 1); } if (newstr == NULL) { - if (strings != strings_stack) { - free(strings); - } + va_end(ap2); return (cxmutstr) {NULL, 0}; } str.ptr = newstr; @@ -160,19 +161,15 @@ size_t pos = str.length; str.length = slen; for (size_t i = 0; i < count; i++) { - cxstring s = strings[i]; + cxstring s = va_arg(ap2, cxstring); memcpy(str.ptr + pos, s.ptr, s.length); pos += s.length; } + va_end(ap2); // terminate string str.ptr[str.length] = '\0'; - // free temporary array - if (strings != strings_stack) { - free(strings); - } - return str; } @@ -289,8 +286,9 @@ // check needle length and use appropriate prefix table // if the pattern exceeds static prefix table, allocate on the heap const bool useheap = needle.length >= CX_STRSTR_SBO_SIZE; - register size_t *ptable = useheap ? calloc(needle.length + 1, - sizeof(size_t)) : s_prefix_table; + register size_t *ptable = useheap + ? cxCallocDefault(needle.length + 1, sizeof(size_t)) + : s_prefix_table; // keep counter in registers register size_t i, j; @@ -328,7 +326,7 @@ // if prefix table was allocated on the heap, free it if (useheap) { - free(ptable); + cxFreeDefault(ptable); } return result; @@ -588,27 +586,6 @@ #endif } -#ifndef CX_STRREPLACE_INDEX_BUFFER_SIZE -#define CX_STRREPLACE_INDEX_BUFFER_SIZE 64 -#endif - -struct cx_strreplace_ibuf { - size_t *buf; - struct cx_strreplace_ibuf *next; - unsigned int len; -}; - -static void cx_strrepl_free_ibuf(struct cx_strreplace_ibuf *buf) { - // remember, the first data is on the stack! - buf = buf->next; - while (buf) { - struct cx_strreplace_ibuf *next = buf->next; - free(buf->buf); - free(buf); - buf = next; - } -} - cxmutstr cx_strreplacen_a( const CxAllocator *allocator, cxstring str, @@ -616,108 +593,60 @@ cxstring replacement, size_t replmax ) { + // special cases + if (search.length == 0 || search.length > str.length || replmax == 0) { + return cx_strdup_a(allocator, str); + } - if (search.length == 0 || search.length > str.length || replmax == 0) - return cx_strdup_a(allocator, str); + size_t in_len = str.length; + size_t search_len = search.length; + size_t repl_len = replacement.length; - // Compute expected buffer length - size_t ibufmax = str.length / search.length; - size_t ibuflen = replmax < ibufmax ? replmax : ibufmax; - if (ibuflen > CX_STRREPLACE_INDEX_BUFFER_SIZE) { - ibuflen = CX_STRREPLACE_INDEX_BUFFER_SIZE; + // first run, count the occurrences + // and remember where the first is + size_t occurrences = 1; + cxstring first = cx_strstr(str, search); + if (first.length == 0) { + // special case, no replacements + return cx_strdup_a(allocator, str); + } + cxstring tmp = cx_strsubs(first, search_len); + while (occurrences < replmax && + (tmp = cx_strstr(tmp, search)).length > 0) { + occurrences++; + tmp = cx_strsubs(tmp, search_len); } - // First index buffer can be on the stack - struct cx_strreplace_ibuf ibuf, *curbuf = &ibuf; - size_t ibuf_sbo[CX_STRREPLACE_INDEX_BUFFER_SIZE]; - ibuf.buf = ibuf_sbo; - ibuf.next = NULL; - ibuf.len = 0; + // calculate necessary memory + signed long long diff_len = (signed long long) repl_len - search_len; + size_t out_len = in_len + diff_len * occurrences; + cxmutstr out = { + cxMalloc(allocator, out_len + 1), + out_len + }; + if (out.ptr == NULL) return out; - // Search occurrences - cxstring searchstr = str; - size_t found = 0; - do { - cxstring match = cx_strstr(searchstr, search); - if (match.length > 0) { - // Allocate next buffer in chain, if required - if (curbuf->len == ibuflen) { - struct cx_strreplace_ibuf *nextbuf = - calloc(1, sizeof(struct cx_strreplace_ibuf)); - if (!nextbuf) { - cx_strrepl_free_ibuf(&ibuf); - return cx_mutstrn(NULL, 0); - } - nextbuf->buf = calloc(ibuflen, sizeof(size_t)); - if (!nextbuf->buf) { - free(nextbuf); - cx_strrepl_free_ibuf(&ibuf); - return cx_mutstrn(NULL, 0); - } - curbuf->next = nextbuf; - curbuf = nextbuf; - } - - // Record match index - found++; - size_t idx = match.ptr - str.ptr; - curbuf->buf[curbuf->len++] = idx; - searchstr.ptr = match.ptr + search.length; - searchstr.length = str.length - idx - search.length; - } else { - break; - } - } while (searchstr.length > 0 && found < replmax); - - // Allocate result string - cxmutstr result; - { - long long adjlen = (long long) replacement.length - (long long) search.length; - size_t rcount = 0; - curbuf = &ibuf; - do { - rcount += curbuf->len; - curbuf = curbuf->next; - } while (curbuf); - result.length = str.length + rcount * adjlen; - result.ptr = cxMalloc(allocator, result.length + 1); - if (!result.ptr) { - cx_strrepl_free_ibuf(&ibuf); - return cx_mutstrn(NULL, 0); - } + // second run: perform the replacements + // but start where we found the first occurrence + const char *inp = str.ptr; + tmp = first; + char *outp = out.ptr; + while (occurrences-- > 0 && (tmp = cx_strstr(tmp, search)).length > 0) { + size_t copylen = tmp.ptr - inp; + memcpy(outp, inp, copylen); + outp += copylen; + memcpy(outp, replacement.ptr, repl_len); + outp += repl_len; + inp += copylen + search_len; + tmp = cx_strsubs(tmp, search_len); } - // Build result string - curbuf = &ibuf; - size_t srcidx = 0; - char *destptr = result.ptr; - do { - for (size_t i = 0; i < curbuf->len; i++) { - // Copy source part up to next match - size_t idx = curbuf->buf[i]; - size_t srclen = idx - srcidx; - if (srclen > 0) { - memcpy(destptr, str.ptr + srcidx, srclen); - destptr += srclen; - srcidx += srclen; - } + // add the remaining string + size_t copylen = in_len - (inp - str.ptr); + memcpy(outp, inp, copylen); + out.ptr[out_len] = '\0'; - // Copy the replacement and skip the source pattern - srcidx += search.length; - memcpy(destptr, replacement.ptr, replacement.length); - destptr += replacement.length; - } - curbuf = curbuf->next; - } while (curbuf); - memcpy(destptr, str.ptr + srcidx, str.length - srcidx); - - // Result is guaranteed to be zero-terminated - result.ptr[result.length] = '\0'; - - // Free index buffer - cx_strrepl_free_ibuf(&ibuf); - - return result; + return out; } CxStrtokCtx cx_strtok_(
--- a/ucx/tree.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ucx/tree.c Sun Jul 20 22:04:39 2025 +0200 @@ -226,14 +226,14 @@ int ret_elem = sfunc(elem, node); if (ret_elem == 0) { // if found, exit the search - *result = (void *) elem; + *result = elem; ret = 0; break; } else if (ret_elem > 0 && ret_elem < ret) { // new distance is better *result = elem; ret = ret_elem; - } else { + } else if (ret_elem < 0 || ret_elem > ret) { // not contained or distance is worse, skip entire subtree cxTreeIteratorContinue(iter); } @@ -305,12 +305,12 @@ if (children == NULL) { // search for the next node - void *next; + void *next = NULL; cx_tree_iter_search_next: - // check if there is a sibling + // check if there is a sibling, but only if we are not a (subtree-)root if (iter->exiting) { next = iter->node_next; - } else { + } else if (iter->depth > 1) { next = tree_next(iter->node); iter->node_next = next; } @@ -326,7 +326,7 @@ // invalidate the iterator and free the node stack iter->node = iter->node_next = NULL; iter->stack_capacity = iter->depth = 0; - free(iter->stack); + cxFreeDefault(iter->stack); iter->stack = NULL; } else { // the parent node can be obtained from the top of stack @@ -386,7 +386,7 @@ iter.node = root; if (root != NULL) { iter.stack_capacity = 16; - iter.stack = malloc(sizeof(void *) * 16); + iter.stack = cxMallocDefault(sizeof(void *) * 16); iter.stack[0] = root; iter.counter = 1; iter.depth = 1; @@ -416,7 +416,7 @@ node = tree_next(node); while (node != NULL) { struct cx_tree_visitor_queue_s *q; - q = malloc(sizeof(struct cx_tree_visitor_queue_s)); + q = cxMallocDefault(sizeof(struct cx_tree_visitor_queue_s)); q->depth = iter->queue_last->depth; q->node = node; iter->queue_last->next = q; @@ -445,7 +445,7 @@ } if (children != NULL) { struct cx_tree_visitor_queue_s *q; - q = malloc(sizeof(struct cx_tree_visitor_queue_s)); + q = cxMallocDefault(sizeof(struct cx_tree_visitor_queue_s)); q->depth = iter->depth + 1; q->node = children; if (iter->queue_last == NULL) { @@ -474,7 +474,7 @@ assert(iter->queue_last == q); iter->queue_last = NULL; } - free(q); + cxFreeDefault(q); } // increment the node counter
--- a/ui/Makefile Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/Makefile Sun Jul 20 22:04:39 2025 +0200 @@ -33,15 +33,16 @@ include common/objs.mk -UI_LIB = ../build/lib/$(LIB_PREFIX)uitk$(LIB_EXT) +UI_LIB = ../build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)uitk$(LIB_EXT) +UI_SHLIB = ../build/$(BUILD_LIB_DIR)/$(LIB_PREFIX)uitk$(SHLIB_EXT) include $(TOOLKIT)/objs.mk OBJ = $(TOOLKITOBJS) $(COMMONOBJS) -all: $(UI_LIB) +all: $(UI_LIB) $(UI_SHLIB) include $(TOOLKIT)/Makefile $(COMMON_OBJPRE)uic_%$(OBJ_EXT): common/%.c - $(CC) -o $@ -c -I../ucx/ $(CFLAGS) $(TK_CFLAGS) $< + $(CC) -o $@ -c -I../ucx/ $(CFLAGS) $(SHLIB_CFLAGS) $(TK_CFLAGS) $<
--- a/ui/cocoa/EventData.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/cocoa/EventData.h Sun Jul 20 22:04:39 2025 +0200 @@ -47,6 +47,5 @@ - (void)handleEventWithEventData:(id)sender; -- (SEL)addDynamicMethod:(unsigned long long)method_id; +@end -@end
--- a/ui/cocoa/MainWindow.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/cocoa/MainWindow.h Sun Jul 20 22:04:39 2025 +0200 @@ -31,8 +31,36 @@ @interface MainWindow : NSWindow -@property UiObject *uiobj; - - (MainWindow*)init:(UiObject*)obj; @end + + +@interface MainWindowController : NSWindowController<NSMenuItemValidation> + +@property UiObject *uiobj; +@property NSMutableDictionary *checkItemStates; +@property NSMutableDictionary *radioItems; + +- (MainWindowController*)initWithWindow:(UiObject*)obj window:(NSWindow*)window; + +- (void) windowDidLoad; + +- (void)menuItemAction:(id)sender; + +- (BOOL) validateMenuItem:(NSMenuItem *) menuItem; + +@end + +@interface MenuItemState : NSObject +@property (weak) MainWindowController *mainWindow; +@property UiVar *var; +@property int state; +@end + + +int64_t ui_menu_check_item_get(UiInteger *i); +void ui_menu_check_item_set(UiInteger *i, int64_t value); + +int64_t ui_menu_radio_item_get(UiInteger *i); +void ui_menu_radio_item_set(UiInteger *i, int64_t value);
--- a/ui/cocoa/MainWindow.m Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/cocoa/MainWindow.m Sun Jul 20 22:04:39 2025 +0200 @@ -30,11 +30,14 @@ #import "Container.h" #import "GridLayout.h" #import "../common/object.h" +#import <objc/runtime.h> + +#import "EventData.h" +#import "menu.h" @implementation MainWindow - (MainWindow*)init:(UiObject*)obj { - self.uiobj = obj; NSRect frame = NSMakeRect(300, 200, 600, 500); self = [self initWithContentRect:frame @@ -63,3 +66,198 @@ } @end + + + +@implementation MainWindowController + +- (MainWindowController*)initWithWindow:(UiObject*)obj window:(NSWindow*)window { + self = [super initWithWindow:window]; + _uiobj = obj; + + self.checkItemStates = [[NSMutableDictionary alloc] init]; + self.radioItems = [[NSMutableDictionary alloc] init]; + + // bind all stateful menu items (checkbox, radiobuttons, lists) + NSArray *menuBindItems = ui_get_binding_items(); // returns all items that require binding + for(MenuItem *item in menuBindItems) { + if(item.checkItem || item.radioItem) { + // simple check item (ui_menu_toggleitem_create) + UiVar *var = uic_widget_var(obj->ctx, obj->ctx, NULL, item.checkItem ? item.checkItem->varname : item.radioItem->varname, UI_VAR_INTEGER); + // create the state object for this item/window + MenuItemState *state = [[MenuItemState alloc] init]; + state.mainWindow = self; + state.var = var; + if(var) { + UiInteger *i = var->value; + if(item.checkItem) { + // bind toggle item + state.state = (int)i->value; + i->obj = (__bridge void*)state; + i->get = ui_menu_check_item_get; + i->set = ui_menu_check_item_set; + } else { + // bind radio item + NSMutableArray *rgroup = nil; + if(i->obj) { + rgroup = (__bridge NSMutableArray*)i->obj; + } else { + // create a new rgroup array and register it in the window + rgroup = [[NSMutableArray alloc] init]; + NSString *varname = [[NSString alloc] initWithUTF8String:item.radioItem->varname]; + [_radioItems setObject:rgroup forKey:varname]; + i->obj = (__bridge void*)rgroup; + } + i->get = ui_menu_radio_item_get; + i->set = ui_menu_radio_item_set; + [rgroup addObject:state]; // add this item state to the radio group + // i->value can contain a non-zero value, which means a specific radiobutton + // should be pre-selected + if(i->value == rgroup.count) { + state.state = NSControlStateValueOn; + } + } + } else { + state.state = 0; + } + [_checkItemStates setObject:state forKey:item.itemId]; + } + } + + return self; +} + +- (void) windowDidLoad { + [self.window setNextResponder:self]; +} + +- (void)menuItemAction:(id)sender { + EventData *event = objc_getAssociatedObject(sender, "eventdata"); + if(event) { + event.obj = self.uiobj; // temporary set the event object + [event handleEvent:sender]; + } +} + +- (void)menuCheckItemAction:(id)sender { + NSMenuItem *menuItem = sender; + MenuItem *item = objc_getAssociatedObject(sender, "menuitem"); + if(!item || !item.checkItem) { + return; + } + + MenuItemState *state = [_checkItemStates objectForKey:item.itemId]; + state.state = state.state == NSControlStateValueOff ? NSControlStateValueOn : NSControlStateValueOff; + menuItem.state = state.state; + + UiMenuCheckItem *it = item.checkItem; + if(it->callback) { + UiEvent event; + event.obj = _uiobj; + event.window = event.obj->window; + event.document = event.obj->ctx->document; + event.eventdata = state.var ? state.var->value : NULL; + event.intval = state.state; + it->callback(&event, it->userdata); + } +} + +- (void)menuRadioItemAction:(id)sender { + NSMenuItem *menuItem = sender; + MenuItem *item = objc_getAssociatedObject(sender, "menuitem"); + if(!item || !item.radioItem) { + return; + } + + UiMenuRadioItem *it = item.radioItem; + if(!it->varname) { + return; + } + + MenuItemState *state = [_checkItemStates objectForKey:item.itemId]; // current state of this menu item + + NSString *varname = [[NSString alloc] initWithUTF8String:it->varname]; + NSArray *radioGroup = [_radioItems objectForKey:varname]; + if(!radioGroup) { + return; + } + int index = 1; + int value = 0; + for(MenuItemState *g in radioGroup) { + if(g == state) { + menuItem.state = NSControlStateValueOn; + g.state = NSControlStateValueOn; + value = index; + } else { + menuItem.state = NSControlStateValueOff; + g.state = NSControlStateValueOff; + } + } + + if(it->callback) { + UiEvent event; + event.obj = _uiobj; + event.window = event.obj->window; + event.document = event.obj->ctx->document; + event.eventdata = state.var ? state.var->value : NULL; + event.intval = value; + it->callback(&event, it->userdata); + } +} + + +- (BOOL) validateMenuItem:(NSMenuItem *) menuItem { + MenuItem *item = objc_getAssociatedObject(menuItem, "menuitem"); + if(item) { + MenuItemState *state = [_checkItemStates objectForKey:item.itemId]; + if(state) { + menuItem.state = state.state; + } else { + menuItem.state = NSControlStateValueOff; + } + } + + return YES; +} + +@end + +@implementation MenuItemState + +@end + +int64_t ui_menu_check_item_get(UiInteger *i) { + MenuItemState *state = (__bridge MenuItemState*)i->obj; + i->value = state.state; + return i->value; +} + +void ui_menu_check_item_set(UiInteger *i, int64_t value) { + MenuItemState *state = (__bridge MenuItemState*)i->obj; + i->value = value; + state.state = (int)value; +} + +int64_t ui_menu_radio_item_get(UiInteger *i) { + NSArray *rgroup = (__bridge NSArray*)i->obj; + i->value = 0; + int index = 1; + for(MenuItemState *state in rgroup) { + if(state.state == NSControlStateValueOn) { + i->value = index; + break; + } + index++; + } + return i->value; +} + +void ui_menu_radio_item_set(UiInteger *i, int64_t value) { + NSArray *rgroup = (__bridge NSArray*)i->obj; + i->value = 0; + int index = 1; + for(MenuItemState *state in rgroup) { + state.state = value == index; + index++; + } +}
--- a/ui/cocoa/Makefile Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/cocoa/Makefile Sun Jul 20 22:04:39 2025 +0200 @@ -27,8 +27,10 @@ # $(COCOA_OBJPRE)%.o: cocoa/%.m - $(CC) -o $@ -c -I../ucx -fobjc-arc $(CFLAGS) $(TK_CFLAGS) $< + $(CC) -o $@ -c -I../ucx -fobjc-arc $(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
--- a/ui/cocoa/button.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/cocoa/button.h Sun Jul 20 22:04:39 2025 +0200 @@ -30,6 +30,17 @@ #import "../ui/button.h" +@interface UiRadioButton : NSButton + +@property UiVar *var; +@property Boolean direct_state; + +- (UiRadioButton*)init; +- (void)setState:(NSControlStateValue)state; + +@end + + int64_t ui_togglebutton_get(UiInteger *i); void ui_togglebutton_set(UiInteger *i, int64_t value);
--- a/ui/cocoa/button.m Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/cocoa/button.m Sun Jul 20 22:04:39 2025 +0200 @@ -31,15 +31,15 @@ #import "Container.h" #import <objc/runtime.h> -UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs args) { +UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs *args) { NSButton *button = [[NSButton alloc] init]; - if(args.label) { - NSString *label = [[NSString alloc] initWithUTF8String:args.label]; + if(args->label) { + NSString *label = [[NSString alloc] initWithUTF8String:args->label]; button.title = label; } - if(args.onclick) { - EventData *event = [[EventData alloc] init:args.onclick userdata:args.onclickdata]; + if(args->onclick) { + EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata]; event.obj = obj; button.target = event; button.action = @selector(handleEvent:); @@ -59,17 +59,17 @@ *value = (int)state; } -UIWIDGET togglebutton_create(UiObject* obj, UiToggleArgs args, enum NSButtonType type) { +UIWIDGET togglebutton_create(UiObject* obj, UiToggleArgs *args, enum NSButtonType type) { NSButton *button = [[NSButton alloc] init]; [button setButtonType:type]; //[button setAllowsMixedState:YES]; - if(args.label) { - NSString *label = [[NSString alloc] initWithUTF8String:args.label]; + if(args->label) { + NSString *label = [[NSString alloc] initWithUTF8String:args->label]; button.title = label; } - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_INTEGER); + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_INTEGER); if(var) { UiInteger *i = var->value; i->obj = (__bridge void*)button; @@ -77,8 +77,8 @@ i->set = ui_togglebutton_set; } - if(args.onchange) { - EventData *event = [[EventData alloc] init:args.onchange userdata:args.onchangedata]; + if(args->onchange) { + EventData *event = [[EventData alloc] init:args->onchange userdata:args->onchangedata]; event.get_eventdata = togglebutton_eventdata; event.obj = obj; event.var = var; @@ -113,11 +113,11 @@ button.state = state; } -UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs args) { +UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs *args) { return togglebutton_create(obj, args, NSButtonTypePushOnPushOff); } -UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs args) { +UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs *args) { return togglebutton_create(obj, args, NSButtonTypeSwitch); } @@ -127,10 +127,10 @@ *value = (int)state; } -UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs args) { +UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs *args) { NSSwitch *button = [[NSSwitch alloc] init]; - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_INTEGER); + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_INTEGER); if(var) { UiInteger *i = var->value; i->obj = (__bridge void*)button; @@ -138,8 +138,8 @@ i->set = ui_switch_set; } - if(args.onchange) { - EventData *event = [[EventData alloc] init:args.onchange userdata:args.onchangedata]; + if(args->onchange) { + EventData *event = [[EventData alloc] init:args->onchange userdata:args->onchangedata]; event.get_eventdata = switch_eventdata; event.obj = obj; event.var = var; @@ -174,17 +174,45 @@ button.state = state; } + +@implementation UiRadioButton + +- (UiRadioButton*)init { + self = [super init]; + _direct_state = NO; + [self setButtonType:NSButtonTypeRadio]; + return self; +} + +- (void)setState:(NSControlStateValue)state { + // NOOP +} + +@end + static void radiobutton_eventdata(id button, UiVar *var, void **eventdata, int *value) { if(var) { - printf("switch radiobutton\n"); + UiInteger *value = var->value; + NSMutableArray *buttons = (__bridge NSMutableArray*)value->obj; + for(UiRadioButton *b in buttons) { + if(b != button) { + b.direct_state = YES; + [[b cell] setState:0]; + b.direct_state = NO; + } + } } } -UIWIDGET ui_radiobutton_create(UiObject* obj, UiToggleArgs args) { - NSButton *button = [[NSButton alloc] init]; - [button setButtonType:NSButtonTypeRadio]; +UIWIDGET ui_radiobutton_create(UiObject* obj, UiToggleArgs *args) { + UiRadioButton *button = [[UiRadioButton alloc] init]; - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_INTEGER); + if(args->label) { + button.title = [[NSString alloc] initWithUTF8String:args->label]; + } + + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_INTEGER); + button.var = var; NSMutableArray *buttons = nil; if(var) { UiInteger *i = var->value; @@ -199,8 +227,8 @@ objc_setAssociatedObject(button, "radiogroup", buttons, OBJC_ASSOCIATION_RETAIN); } - if(args.onchange || var) { - EventData *event = [[EventData alloc] init:args.onchange userdata:args.onchangedata]; + if(args->onchange || var) { + EventData *event = [[EventData alloc] init:args->onchange userdata:args->onchangedata]; event.get_eventdata = radiobutton_eventdata; event.obj = obj; event.var = var; @@ -220,9 +248,27 @@ } int64_t ui_radiobuttons_get(UiInteger *i) { - return 0; + NSMutableArray *buttons = (__bridge NSMutableArray*)i->obj; + int64_t index = 0; + for(UiRadioButton *b in buttons) { + if([b cell].state != 0) { + i->value = index + 1; + break; + } + index++; + } + return i->value; } void ui_radiobuttons_set(UiInteger *i, int64_t value) { - + NSMutableArray *buttons = (__bridge NSMutableArray*)i->obj; + int64_t index = 1; + for(UiRadioButton *b in buttons) { + if(index == value) { + [b cell].state = NSControlStateValueOn; + } else { + [b cell].state = NSControlStateValueOff; + } + index++; + } }
--- a/ui/cocoa/container.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/cocoa/container.h Sun Jul 20 22:04:39 2025 +0200 @@ -43,7 +43,7 @@ }; struct UiLayout { - UiTri fill; + UiBool fill; //UiBool newline; //char *label; UiBool hexpand; @@ -56,13 +56,13 @@ }; #define UI_INIT_LAYOUT(args) (UiLayout) {\ - .fill = args.fill, \ - .hexpand = args.hexpand, \ - .vexpand = args.vexpand, \ - .hfill = args.hfill, \ - .vfill = args.vfill, \ - .colspan = args.colspan, \ - .rowspan = args.rowspan } + .fill = args->fill, \ + .hexpand = args->hexpand, \ + .vexpand = args->vexpand, \ + .hfill = args->hfill, \ + .vfill = args->vfill, \ + .colspan = args->colspan, \ + .rowspan = args->rowspan } @protocol Container
--- a/ui/cocoa/container.m Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/cocoa/container.m Sun Jul 20 22:04:39 2025 +0200 @@ -95,8 +95,8 @@ /* -------------------- public container functions --------------------- */ -static UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs args, NSUserInterfaceLayoutOrientation orientation) { - BoxContainer *box = [[BoxContainer alloc] init:orientation spacing:args.spacing]; +static UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs *args, NSUserInterfaceLayoutOrientation orientation) { + BoxContainer *box = [[BoxContainer alloc] init:orientation spacing:args->spacing]; box.translatesAutoresizingMaskIntoConstraints = false; // add box to the parent @@ -109,15 +109,15 @@ return (__bridge void*)box; } -UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs args) { +UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs *args) { return ui_box_create(obj, args, NSUserInterfaceLayoutOrientationVertical); } -UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs args) { +UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs *args) { return ui_box_create(obj, args, NSUserInterfaceLayoutOrientationHorizontal); } -UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs args) { +UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) { GridLayout *grid = [[GridLayout alloc] init]; grid.translatesAutoresizingMaskIntoConstraints = false;
--- a/ui/cocoa/graphics.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2014 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. - */ - -#import "../ui/graphics.h" -#import "toolkit.h" - - -@interface UiCanvas : NSView { - UiObject *object; - ui_drawfunc callback; - void *userdata; -} - -- (UiObject*) object; -- (void) setObject:(void*)obj; - -- (void*) userdata; -- (void) setUserdata:(void*)d; - -- (ui_drawfunc) callback; -- (void) setCallback: (ui_drawfunc)f; - - -- (void)drawRect:(NSRect)rect; - -@end -
--- a/ui/cocoa/graphics.m Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,124 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2014 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. - */ - -#import <stdio.h> -#import <stdlib.h> -#import <string.h> - -#import "graphics.h" -#import "container.h" -#import "../common/context.h" - - - -@implementation UiCanvas - -- (UiObject*) object { - return object; -} - -- (void) setObject:(void*)obj { - object = obj; -} - -- (void*) userdata { - return userdata; -} - -- (void) setUserdata:(void*)d { - userdata = d; -} - -- (ui_drawfunc) callback { - return callback; -} -- (void) setCallback: (ui_drawfunc)f { - callback = f; -} - -- (void) drawRect:(NSRect)rect { - UiGraphics g; - NSRect bounds = [self bounds]; - g.width = bounds.size.width; - g.height = bounds.size.height; - - UiEvent ev; - ev.obj = object; - ev.window = object->window; - ev.document = object->ctx->document; - - callback(&ev, &g, userdata); -} - -@end - - -UIWIDGET ui_drawingarea(UiObject *obj, ui_drawfunc f, void *userdata) { - UiContainer *ct = uic_get_current_container(obj); - - NSRect frame = ct->getframe(ct); - - UiCanvas *canvas = [[UiCanvas alloc]initWithFrame:frame]; - [canvas setObject: obj]; - [canvas setCallback: f]; - [canvas setUserdata: userdata]; - ct->add(ct, canvas); - - return canvas; -} - - -// drawing functions -void ui_graphics_color(UiGraphics *gr, int red, int green, int blue) { - float r = ((float)red) / 255.f; - float g = ((float)green) / 255.f; - float b = ((float)blue) / 255.f; - - NSColor *color = [NSColor colorWithCalibratedRed:r green:g blue:b alpha:1]; - [color set]; -} - -void ui_draw_rect(UiGraphics *g, int x, int y, int w, int h, int fill) { - // translate y - y = g->height - y - h; - - NSRect bounds; - bounds.origin.x = x; - bounds.origin.y = y; - bounds.size.width = w; - bounds.size.height = h; - - if(fill) { - NSRectFill(bounds); - } else { - NSFrameRect(bounds); - } -} - - -
--- a/ui/cocoa/menu.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/cocoa/menu.h Sun Jul 20 22:04:39 2025 +0200 @@ -31,6 +31,18 @@ #import "../common/menu.h" +@interface MenuItem : NSObject + +@property (strong) NSString *itemId; +@property UiMenuCheckItem *checkItem; +@property UiMenuRadioItem *radioItem; +@property ui_callback callback; +@property void *userdata; + +- (MenuItem*)init:(int)itId; + +@end + void ui_menu_init(void); typedef void(*ui_menu_add_f)(NSMenu*, int, UiMenuItemI*); @@ -42,3 +54,5 @@ void add_radioitem_widget(NSMenu *parent, int index, UiMenuItemI *item); void add_checkitemnv_widget(NSMenu *parent, int i, UiMenuItemI *item); void add_menuitem_list_widget(NSMenu *parent, int i, UiMenuItemI *item); + +NSArray* ui_get_binding_items(void);
--- a/ui/cocoa/menu.m Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/cocoa/menu.m Sun Jul 20 22:04:39 2025 +0200 @@ -30,9 +30,27 @@ #import <stdlib.h> #import <string.h> #import <stdarg.h> +#import <objc/runtime.h> #import "menu.h" #import "window.h" +#import "EventData.h" + +#pragma GCC diagnostic ignored "-Wundeclared-selector" +#pragma clang diagnostic ignored "-Wundeclared-selector" + +// holds all items that need bindings +// value type: MenuItem* +static NSMutableArray *bindingItems; + +@implementation MenuItem + +- (MenuItem*)init:(int)itId { + self.itemId = [[NSString alloc] initWithFormat:@"item%d", itId]; + return self; +} + +@end static ui_menu_add_f createMenuItem[] = { /* UI_MENU */ add_menu_widget, @@ -67,20 +85,51 @@ void add_menuitem_widget(NSMenu *parent, int i, UiMenuItemI *item) { UiMenuItem *it = (UiMenuItem*)item; + NSString *str = [[NSString alloc] initWithUTF8String:it->label]; - NSMenuItem *menuItem = [parent addItemWithTitle:str action:nil keyEquivalent:@""]; + NSMenuItem *menuItem = [parent addItemWithTitle:str action:@selector(menuItemAction:) keyEquivalent:@""]; + + if(it->callback) { + EventData *event = [[EventData alloc] init:it->callback userdata:it->userdata]; + objc_setAssociatedObject(menuItem, "eventdata", event, OBJC_ASSOCIATION_RETAIN); + } } void add_menuseparator_widget(NSMenu *parent, int i, UiMenuItemI *item) { - + NSMenuItem *menuItem = [NSMenuItem separatorItem]; + [parent addItem:menuItem]; } +static int nItem = 0; + void add_checkitem_widget(NSMenu *parent, int i, UiMenuItemI *item) { + UiMenuCheckItem *it = (UiMenuCheckItem*)item; + NSString *str = [[NSString alloc] initWithUTF8String:it->label]; + NSMenuItem *menuItem = [parent addItemWithTitle:str action:@selector(menuCheckItemAction:) keyEquivalent:@""]; + + MenuItem *mItem = [[MenuItem alloc] init:nItem++]; + mItem.callback = it->callback; + mItem.userdata = it->userdata; + mItem.checkItem = it; + + objc_setAssociatedObject(menuItem, "menuitem", mItem, OBJC_ASSOCIATION_RETAIN); + [bindingItems addObject:mItem]; } void add_radioitem_widget(NSMenu *parent, int index, UiMenuItemI *item) { + UiMenuRadioItem *it = (UiMenuRadioItem*)item; + NSString *str = [[NSString alloc] initWithUTF8String:it->label]; + NSMenuItem *menuItem = [parent addItemWithTitle:str action:@selector(menuRadioItemAction:) keyEquivalent:@""]; + + MenuItem *mItem = [[MenuItem alloc] init:nItem++]; + mItem.callback = it->callback; + mItem.userdata = it->userdata; + mItem.radioItem = it; + + objc_setAssociatedObject(menuItem, "menuitem", mItem, OBJC_ASSOCIATION_RETAIN); + [bindingItems addObject:mItem]; } void add_checkitemnv_widget(NSMenu *parent, int i, UiMenuItemI *item) { @@ -93,17 +142,25 @@ void ui_menu_init(void) { + bindingItems = [[NSMutableArray alloc] init]; + UiMenu *menus_begin = uic_get_menu_list(); UiMenu *ls = menus_begin; + int index = 1; while(ls) { if(ls->item.type == UI_MENU) { NSString *str = [[NSString alloc] initWithUTF8String:ls->label]; NSMenu *menu = [[NSMenu alloc] initWithTitle: str]; - NSMenuItem *menuItem = [[NSApp mainMenu] addItemWithTitle:str action:nil keyEquivalent:@""]; + NSMenuItem *menuItem = [[NSApp mainMenu] insertItemWithTitle:str action:nil keyEquivalent:@"" atIndex:index]; [[NSApp mainMenu] setSubmenu:menu forItem:menuItem]; add_menu_items(menu, 0, ls); } ls = (UiMenu*)ls->item.next; + index++; } } + +NSArray* ui_get_binding_items(void) { + return bindingItems; +}
--- a/ui/cocoa/resource.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* - * 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. - */ - -#import "../ui/toolkit.h" -#import "../ui/properties.h" - -
--- a/ui/cocoa/resource.m Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,73 +0,0 @@ -/* - * 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. - */ - -#import <stdio.h> -#import <stdlib.h> -#import <string.h> - -#import "resource.h" -#import "../common/properties.h" - - - -void ui_load_lang_def(char *locale, char *default_locale) { - NSString *localeString = nil; - char tmp[6]; - if(!locale) { - NSString* lang = [[NSLocale currentLocale] localeIdentifier]; - if(lang) { - localeString = lang; - } else { - [[NSString alloc]initWithUTF8String:default_locale]; - } - } else { - localeString = [[NSString alloc]initWithUTF8String:locale]; - } - - NSString *path = [[NSBundle mainBundle] pathForResource:localeString ofType:@"properties" inDirectory:@"locales"]; - - const char *p = [path UTF8String]; - - if(uic_load_language_file((char*)p)) { - if(default_locale) { - ui_load_lang_def(default_locale, NULL); - } else { - // cannot find any language file - fprintf(stderr, "Ui Error: Cannot load language.\n"); - exit(-1); - } - } -} - -void ui_locales_dir(char *path) { - // empty -} - -void ui_pixmaps_dir(char *path) { - // empty -} \ No newline at end of file
--- a/ui/cocoa/stock.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -/* - * 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. - */ - -#import "toolkit.h" -#import "../ui/stock.h" -#import <ucx/map.h> - -typedef struct UiStockItem { - NSString *label; - NSString *keyEquivalent; - NSImage *image; -} UiStockItem; - -void ui_stock_init(); - -void ui_add_stock_item(char *stock_id, NSString *label, NSString *keyEquivalent, NSImage *image); - -UiStockItem* ui_get_stock_item(char *stock_id);
--- a/ui/cocoa/stock.m Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/* - * 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. - */ - -#import <stdio.h> -#import <stdlib.h> - -#import "stock.h" -#import "../common/properties.h" - -static UcxMap *stock_items; - -void ui_stock_init() { - stock_items = ucx_map_new(64); - - ui_add_stock_item(UI_STOCK_NEW, @"New", @"n", nil); - ui_add_stock_item(UI_STOCK_OPEN, @"Open", @"o", nil); - ui_add_stock_item(UI_STOCK_SAVE, @"Save", @"s", nil); - ui_add_stock_item(UI_STOCK_SAVE_AS, @"Save as ...", @"", nil); - ui_add_stock_item(UI_STOCK_CLOSE, @"Close", @"w", nil); - ui_add_stock_item(UI_STOCK_UNDO, @"Undo", @"z", nil); - ui_add_stock_item(UI_STOCK_REDO, @"Redo", @"", nil); - ui_add_stock_item(UI_STOCK_CUT, @"Cut", @"x", nil); - ui_add_stock_item(UI_STOCK_COPY, @"Copy", @"c", nil); - ui_add_stock_item(UI_STOCK_PASTE, @"Paste", @"v", nil); - ui_add_stock_item(UI_STOCK_DELETE, @"Delete", @"", nil); - - ui_add_stock_item(UI_STOCK_GO_BACK, @"Back", @"", [NSImage imageNamed: NSImageNameGoLeftTemplate]); - ui_add_stock_item(UI_STOCK_GO_FORWARD, @"Forward", @"", [NSImage imageNamed: NSImageNameGoRightTemplate]); -} - -void ui_add_stock_item(char *stock_id, NSString *label, NSString *keyEquivalent, NSImage *image) { - UiStockItem *i = malloc(sizeof(UiStockItem)); - i->label = label; - i->keyEquivalent = keyEquivalent; - i->image = image; - - ucx_map_cstr_put(stock_items, stock_id, i); -} - -UiStockItem* ui_get_stock_item(char *stock_id) { - UiStockItem *item = ucx_map_cstr_get(stock_items, stock_id); - if(item) { - char *label = uistr_n(stock_id); - if(label) { - NSString *str = [[NSString alloc]initWithUTF8String:label]; - item->label = str; - } - } - return item; -}
--- a/ui/cocoa/text.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/cocoa/text.h Sun Jul 20 22:04:39 2025 +0200 @@ -30,3 +30,20 @@ #import "../ui/text.h" + +void ui_textarea_save(UiText *text); +void ui_textarea_destroy(UiText *text); +void ui_textarea_restore(UiText *text); +void ui_textarea_set(UiText *text, const char *str); +char* ui_textarea_get(UiText *text); +char* ui_textarea_getsubstr(UiText *text, int begin, int end); +void ui_textarea_insert(UiText *text, int pos, char *str); +void ui_textarea_setposition(UiText *text, int pos); +int ui_textarea_position(UiText *text); +void ui_textarea_setselection(UiText *text, int begin, int end); +void ui_textarea_selection(UiText *text, int *begin, int *end); +int ui_textarea_length(UiText *text); +void ui_textarea_remove(UiText *text, int begin, int end); + +char* ui_textfield_get(UiString *s); +void ui_textfield_set(UiString *s, const char *value);
--- a/ui/cocoa/text.m Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/cocoa/text.m Sun Jul 20 22:04:39 2025 +0200 @@ -31,7 +31,7 @@ #import "Container.h" #import <objc/runtime.h> -UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs args) { +UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) { NSTextView *textview = [[NSTextView alloc] init]; textview.autoresizingMask = NSViewWidthSizable; textview.minSize = NSMakeSize(0, 0); @@ -44,5 +44,161 @@ UiLayout layout = UI_INIT_LAYOUT(args); ui_container_add(obj, scrollview, &layout, TRUE); + + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_TEXT); + if(var) { + UiText *text = var->value; + text->obj = (__bridge void*)textview; + ui_textarea_restore(text); + + text->save = ui_textarea_save; + text->destroy = ui_textarea_destroy; + text->restore = ui_textarea_restore; + text->set = ui_textarea_set; + text->get = ui_textarea_get; + text->getsubstr = ui_textarea_getsubstr; + text->insert = ui_textarea_insert; + text->setposition = ui_textarea_setposition; + text->position = ui_textarea_position; + text->setselection = ui_textarea_setselection; + text->selection = ui_textarea_selection; + text->length = ui_textarea_length; + text->remove = ui_textarea_remove; + } + return (__bridge void*)scrollview; } + + + + +void ui_textarea_save(UiText *text) { + +} + +void ui_textarea_destroy(UiText *text) { + (void)(__bridge_transfer NSTextStorage*)text->data1; +} + +void ui_textarea_restore(UiText *text) { + NSTextView *textview = (__bridge NSTextView*)text->obj; + NSTextStorage *textStorage; + if(text->data1) { + textStorage = (__bridge NSTextStorage*)text->data1; + + } else { + textStorage = [[NSTextStorage alloc] init]; + } + [textview.layoutManager replaceTextStorage:textStorage]; + text->data1 = (__bridge_retained void*)textStorage; +} + +void ui_textarea_set(UiText *text, const char *str) { + +} + +char* ui_textarea_get(UiText *text) { + return NULL; +} + +char* ui_textarea_getsubstr(UiText *text, int begin, int end) { + return NULL; +} + +void ui_textarea_insert(UiText *text, int pos, char *str) { + +} + +void ui_textarea_setposition(UiText *text, int pos) { + +} + +int ui_textarea_position(UiText *text) { + return 0; +} + +void ui_textarea_setselection(UiText *text, int begin, int end) { + +} + +void ui_textarea_selection(UiText *text, int *begin, int *end) { + +} + +int ui_textarea_length(UiText *text) { + return 0; +} + +void ui_textarea_remove(UiText *text, int begin, int end) { + +} + + + +/* -------------------------- TextField -------------------------- */ + +static UIWIDGET textfield_create(UiObject *obj, UiTextFieldArgs *args, BOOL password, BOOL frameless) { + NSTextField *textfield; + if(password) { + textfield = [[NSSecureTextField alloc] init]; + } else { + textfield = [[NSTextField alloc] init]; + } + + if(frameless) { + [textfield setBezeled: NO]; + } + + UiLayout layout = UI_INIT_LAYOUT(args); + ui_container_add(obj, textfield, &layout, FALSE); + + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_STRING); + if(var) { + UiString *s = var->value; + if(s->value.ptr) { + textfield.stringValue = [[NSString alloc] initWithUTF8String:s->value.ptr]; + if(s->value.free) { + s->value.free(s->value.ptr); + } + } + s->obj = (__bridge void*)textfield; + s->get = ui_textfield_get; + s->set = ui_textfield_set; + } + + return (__bridge void*)textfield; +} + +UIWIDGET ui_textfield_create(UiObject *obj, UiTextFieldArgs *args) { + return textfield_create(obj, args, FALSE, FALSE); +} + +UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs *args) { + return textfield_create(obj, args, FALSE, TRUE); +} + +UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs *args) { + return textfield_create(obj, args, TRUE, FALSE); +} + +char* ui_textfield_get(UiString *s) { + NSTextField *textfield = (__bridge NSTextField*)s->obj; + NSString *str = textfield.stringValue; + const char *cstr = str.UTF8String; + if(s->value.free) { + s->value.free(s->value.ptr); + } + s->value.ptr = strdup(cstr); + s->value.free = free; + return s->value.ptr; +} + +void ui_textfield_set(UiString *s, const char *value) { + if(s->value.free) { + s->value.free(s->value.ptr); + } + s->value.ptr = NULL; + s->value.free = NULL; + NSTextField *textfield = (__bridge NSTextField*)s->obj; + textfield.stringValue = [[NSString alloc] initWithUTF8String:value]; +}
--- a/ui/cocoa/toolbar.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2014 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. - */ - -#import "../ui/toolbar.h" -#import "toolkit.h" -#import <stdarg.h> - - -@protocol UiToolItem -- (NSToolbarItem *) createItem:(NSToolbar*)toolbar - identifier:(NSString*)identifier - object:(UiObject*)obj; - -- (void) addGroup:(int)group; - -- (UcxList*) groups; - -@end - - -/* - * UiToolbarStockItem - * - * creates a toolbar item from stock description - */ -@interface UiToolbarStockItem : NSObject <UiToolItem> { - char *name; - char *stockid; - ui_callback callback; - void *userdata; - UcxList *groups; - BOOL isToggleButton; -} - -- (UiToolbarStockItem*) initWithIdentifier:(char*)identifier - stockID:(char*)sid - callback:(ui_callback)f - userdata:(void*)data; - -- (void) setIsToggleButton:(BOOL)t; - - -@end - -/* - * UiToolbarItem - * - * toolbar item with label and icon - */ -@interface UiToolbarItem : NSObject <UiToolItem> { - char *name; - char *label; - // icon - ui_callback callback; - void *userdata; - UcxList *groups; - BOOL isToggleButton; -} - -- (UiToolbarItem*) initWithIdentifier:(char*)identifier - label:(char*)lbl - callback:(ui_callback)f - userdata:(void*)data; - -- (void) setIsToggleButton:(BOOL)t; - - -@end - - - -/* - * UiToolbarDelegate - */ -@interface UiToolbarDelegate : NSObject <NSToolbarDelegate> { - NSMutableArray *allowedItems; - NSMutableArray *defaultItems; - NSMutableDictionary *items; -} - -- (UiToolbarDelegate*) init; - -- (void) addDefault:(NSString*)identifier; - -- (void) addItem: (NSString*) identifier - item: (NSObject<UiToolItem>*) item; - -@end - - -/* - * UiToolbar - */ -@interface UiToolbar : NSToolbar { - UiObject *obj; -} - -- (UiToolbar*) initWithObject:(UiObject*)object; - -- (UiObject*) object; - -@end - -void ui_toolbar_init(); -void ui_toolbar_stock_button(char *name, char *stockid, BOOL toggle, ui_callback f, void *udata, va_list ap); -NSToolbar* ui_create_toolbar(UiObject *obj);
--- a/ui/cocoa/toolbar.m Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,358 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2014 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. - */ - -#import <stdio.h> -#import <stdlib.h> -#import <string.h> -#import <inttypes.h> -#import <stdarg.h> - -#import "toolbar.h" -#import "window.h" -#import "stock.h" - - -static UiToolbarDelegate* toolbar_delegate; - -/* --------------------- UiToolbarStockItem --------------------- */ - -@implementation UiToolbarStockItem - -- (UiToolbarStockItem*) initWithIdentifier:(char*)identifier - stockID:(char*)sid - callback:(ui_callback)f - userdata:(void*)data -{ - name = identifier; - stockid = sid; - callback = f; - userdata = data; - groups = NULL; - isToggleButton = NO; - return self; -} - -- (void) setIsToggleButton:(BOOL)t { - isToggleButton = t; -} - -- (void) addGroup:(int)group { - groups = ucx_list_append(groups, (void*)(intptr_t)group); -} - - -- (NSToolbarItem *) createItem:(NSToolbar*)toolbar - identifier:(NSString*)identifier - object:(UiObject*)obj -{ - UiStockItem *s = ui_get_stock_item(stockid); - if(s == nil) { - printf("cannot find stock item\n"); - return nil; - } - - NSToolbarItem *item = [[[NSToolbarItem alloc] initWithItemIdentifier: - identifier] autorelease]; - //[item setLabel:[s label]]; - //[item setPaletteLabel:[s label]]; - [item setLabel:s->label]; - [item setPaletteLabel:@"Operation"]; - - // create button ... - NSRect frame = NSMakeRect(0, 0, 40, 22); - //NSSearchField *sf = [[NSSearchField alloc]initWithFrame:frame]; - NSButton *button = [[NSButton alloc]initWithFrame:frame]; - //[button setImage:[s buttonImage]]; - //[button setImage:[NSImage imageNamed: NSImageNameAddTemplate]]; - if(s->image) { - [button setImage:s->image]; - } else { - [button setImage:[NSImage imageNamed: NSImageNameRemoveTemplate]]; - } - [button setBezelStyle: NSTexturedRoundedBezelStyle]; - - // event - EventWrapper *event = [[EventWrapper alloc] - initWithData:userdata callback:callback]; - if(isToggleButton) { - [button setButtonType: NSPushOnPushOffButton]; - [button setAction:@selector(handleToggleEvent:)]; - } else { - [button setAction:@selector(handleEvent:)]; - } - [button setTarget:event]; - - if(groups) { - uic_add_group_widget(obj->ctx, item, groups); - } - - [item setView:button]; - return item; -} - -- (UcxList*) groups { - return groups; -} - -@end - - -/* --------------------- UiToolbarItem --------------------- */ - -@implementation UiToolbarItem - -- (UiToolbarItem*) initWithIdentifier:(char*)identifier - label:(char*)lbl - callback:(ui_callback)f - userdata:(void*)data -{ - name = identifier; - label = lbl; - callback = f; - userdata = data; - groups = NULL; - isToggleButton = NO; - return self; -} - -- (void) setIsToggleButton:(BOOL)t { - isToggleButton = t; -} - -- (void) addGroup:(int)group { - groups = ucx_list_append(groups, (void*)(intptr_t)group); -} - - -- (NSToolbarItem *) createItem:(NSToolbar*)toolbar - identifier:(NSString*)identifier - object:(UiObject*)obj -{ - NSToolbarItem *item = [[[NSToolbarItem alloc] initWithItemIdentifier: - identifier] autorelease]; - //[item setLabel:[s label]]; - //[item setPaletteLabel:[s label]]; - NSString *l = [[NSString alloc]initWithUTF8String:label]; - [item setLabel:l]; - [item setPaletteLabel:@"Operation"]; - - // create button ... - NSRect frame = NSMakeRect(0, 0, 40, 22); - //NSSearchField *sf = [[NSSearchField alloc]initWithFrame:frame]; - NSButton *button = [[NSButton alloc]initWithFrame:frame]; - //[button setImage:[s buttonImage]]; - //[button setImage:[NSImage imageNamed: NSImageNameAddTemplate]]; - - // TODO: image - [button setImage:[NSImage imageNamed: NSImageNameRemoveTemplate]]; - - [button setBezelStyle: NSTexturedRoundedBezelStyle]; - - // event - EventWrapper *event = [[EventWrapper alloc] - initWithData:userdata callback:callback]; - if(isToggleButton) { - [button setButtonType: NSPushOnPushOffButton]; - [button setAction:@selector(handleToggleEvent:)]; - } else { - [button setAction:@selector(handleEvent:)]; - } - [button setTarget:event]; - - if(groups) { - uic_add_group_widget(obj->ctx, item, groups); - } - - [item setView:button]; - return item; -} - -- (UcxList*) groups { - return groups; -} - -@end - - -/* --------------------- UiToolbarDelegate --------------------- */ - -@implementation UiToolbarDelegate - -- (UiToolbarDelegate*) init { - allowedItems = [[NSMutableArray alloc]initWithCapacity: 16]; - defaultItems = [[NSMutableArray alloc]initWithCapacity: 16]; - items = [[NSMutableDictionary alloc] init]; - return self; -} - -- (void) addDefault:(NSString*)identifier { - [defaultItems addObject: identifier]; -} - -- (void) addItem: (NSString*) identifier - item: (NSObject<UiToolItem>*) item -{ - [allowedItems addObject: identifier]; - [items setObject: item forKey:identifier]; -} - -/* -- (void) addStockItem:(char*)name - stockID:(char*)sid - callback:(ui_callback)f - data:(void*)userdata -{ - UiToolbarStockItem *item = [[UiToolbarStockItem alloc]initWithData:name - stockID:sid callback:f data:userdata]; - - NSString *s = [[NSString alloc]initWithUTF8String:name]; - [allowedItems addObject: s]; - [items setObject: item forKey:s]; -} -*/ - -// implementation of NSToolbarDelegate methods -- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar *)toolbar { - NSMutableArray *i = [[NSMutableArray alloc] - initWithCapacity:[allowedItems count] + 3]; - [i addObject: NSToolbarFlexibleSpaceItemIdentifier]; - [i addObject: NSToolbarSpaceItemIdentifier]; - [i addObject: NSToolbarSeparatorItemIdentifier]; - for(id item in allowedItems) { - [i addObject: item]; - } - - return i; -} - -- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar *)toolbar { - return defaultItems; -} - -- (NSToolbarItem *) toolbar:(NSToolbar*)toolbar - itemForItemIdentifier:(NSString*)identifier - willBeInsertedIntoToolbar:(BOOL)flag -{ - Protocol *item = @protocol(UiToolItem); - item = [items objectForKey: identifier]; - - // get UiObject from toolbar - UiObject *obj = [(UiToolbar*)toolbar object]; - - // create new NSToolbarItem - return [item createItem:toolbar identifier:identifier object:obj]; -} - -@end - - -@implementation UiToolbar - -- (UiToolbar*) initWithObject:(UiObject*)object { - [self initWithIdentifier: @"MainToolbar"]; - obj = object; - return self; -} - -- (UiObject*) object { - return obj; -} - -@end - - -/* --------------------- functions --------------------- */ - -void ui_toolbar_init() { - toolbar_delegate = [[UiToolbarDelegate alloc]init]; -} - -void ui_toolitem(char *name, char *label, ui_callback f, void *udata) { - UiToolbarItem *item = [[UiToolbarItem alloc] - initWithIdentifier: name - label: label - callback: f - userdata: udata]; - - NSString *identifier = [[NSString alloc]initWithUTF8String:name]; - [toolbar_delegate addItem: identifier item: item]; -} - -void ui_toolitem_st(char *name, char *stockid, ui_callback f, void *udata) { - ui_toolitem_stgr(name, stockid, f, udata, -1); -} - -void ui_toolitem_stgr(char *name, char *stockid, ui_callback f, void *udata, ...) { - va_list ap; - va_start(ap, udata); - ui_toolbar_stock_button(name, stockid, NO, f, udata, ap); - va_end(ap); -} - -void ui_toolitem_toggle_st(char *name, char *stockid, ui_callback f, void *udata) { - ui_toolitem_toggle_stgr(name, stockid, f, udata, -1); -} - -void ui_toolitem_toggle_stgr(char *name, char *stockid, ui_callback f, void *udata, ...) { - va_list ap; - va_start(ap, udata); - ui_toolbar_stock_button(name, stockid, YES, f, udata, ap); - va_end(ap); -} - - -void ui_toolbar_stock_button(char *name, char *stockid, BOOL toggle, ui_callback f, void *udata, va_list ap) { - UiToolbarStockItem *item = [[UiToolbarStockItem alloc] - initWithIdentifier: name - stockID: stockid - callback: f - userdata: udata]; - [item setIsToggleButton: toggle]; - NSString *identifier = [[NSString alloc]initWithUTF8String:name]; - [toolbar_delegate addItem: identifier item: item]; - - // add groups - int group; - while((group = va_arg(ap, int)) != -1) { - [item addGroup: group]; - } -} - - -void ui_toolbar_add_default(char *name) { - NSString *identifier = [[NSString alloc]initWithUTF8String:name]; - [toolbar_delegate addDefault: identifier]; -} - -NSToolbar* ui_create_toolbar(UiObject *obj) { - UiToolbar *toolbar = [[UiToolbar alloc] initWithObject:obj]; - [toolbar setDelegate: toolbar_delegate]; - [toolbar setAllowsUserCustomization: true]; - return toolbar; -} -
--- a/ui/cocoa/toolkit.m Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/cocoa/toolkit.m Sun Jul 20 22:04:39 2025 +0200 @@ -46,9 +46,11 @@ static ui_callback startup_func; static void *startup_data; static ui_callback open_func; -void *open_data; +static void *open_data; static ui_callback exit_func; -void *exit_data; +static void *exit_data; + +static UiBool exit_on_shutdown; /* ------------------- App Init / Event Loop functions ------------------- */ @@ -89,6 +91,10 @@ exit_data = userdata; } +void ui_app_exit_on_shutdown(UiBool exitapp) { + exit_on_shutdown = exitapp; +} + void ui_cocoa_onstartup(void) { UiEvent e; e.obj = NULL; @@ -127,6 +133,9 @@ void ui_main(void) { NSApplicationMain(app_argc, app_argv); + if(exit_on_shutdown) { + exit(0); + } } /* ------------------- Window Visibility functions ------------------- */
--- a/ui/cocoa/tree.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,47 +0,0 @@ -/* - * 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. - */ - - #import "../ui/tree.h" - #import "toolkit.h" - - -@interface UiTableDataSource : NSObject<NSTableViewDataSource, NSTableViewDelegate> { - UiList *data; - UiModelInfo *info; - UiListSelection *lastSelection; -} - -- (id)initWithData:(UiList*)list modelInfo:(UiModelInfo*)modelinfo; - -- (void)handleDoubleAction:(id)sender; - -@end - - -char* ui_type_to_string(UiModelType type, void *data, BOOL *free); -
--- a/ui/cocoa/tree.m Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,246 +0,0 @@ -/* - * 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. - */ - -#import <stdio.h> -#import <stdlib.h> - -#import "tree.h" -#import "container.h" -#import "window.h" -#import "../common/context.h" -#import <ucx/utils.h> - -@implementation UiTableDataSource - -- (id)initWithData:(UiList*)list modelInfo:(UiModelInfo*)modelinfo { - data = list; - info = modelinfo; - lastSelection = NULL; - return self; -} - -- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableview { - return data->count(data); -} - -- (id)tableView: (NSTableView*)tableview - objectValueForTableColumn:(NSTableColumn*)column - row:(NSInteger)row -{ - int column_index = [[column identifier]intValue]; - - void *row_data = data->get(data, row); - void *cell_data = info->getvalue(row_data, column_index); - - BOOL f = false; - char *str = ui_type_to_string(info->types[column_index], cell_data, &f); - NSString *s = [[NSString alloc]initWithUTF8String:str]; - return s; -} - -- (void)tableView:(NSTableView *)tableview - setObjectValue:(id)object - forTableColumn:(NSTableColumn *)column - row:(NSInteger)row -{ - int column_index = [[column identifier]intValue]; - - // TODO -} - -- (void)tableViewSelectionDidChange:(NSNotification *)notification { - NSTableView *tableview = (NSTableView*)notification.object; - - // create selection object - UiListSelection *selection = malloc(sizeof(UiListSelection)); - selection->count = [tableview numberOfSelectedRows]; - - selection->rows = calloc(selection->count, sizeof(int)); - NSIndexSet *indices = [tableview selectedRowIndexes]; - NSUInteger index = [indices firstIndex]; - int i=0; - while (index!=NSNotFound) { - selection->rows[i] = index; - index = [indices indexGreaterThanIndex:index]; - i++; - } - - // create event object - UiEvent event; - NSWindow *activeWindow = [NSApp keyWindow]; - if([activeWindow class] == [UiCocoaWindow class]) { - event.obj = [(UiCocoaWindow*)activeWindow object]; - event.window = event.obj->window; - event.document = event.obj->ctx->document; - } else { - event.window = NULL; - event.document = NULL; - } - event.eventdata = selection; - event.intval = selection->count == 0 ? -1 : selection->rows[0]; - - // callback - info->selection(&event, info->userdata); - - // cleanup - if(lastSelection) { - free(lastSelection->rows); - free(lastSelection); - } - lastSelection = selection; -} - -- (void)handleDoubleAction:(id)sender { - // create event object - UiEvent event; - NSWindow *activeWindow = [NSApp keyWindow]; - if([activeWindow class] == [UiCocoaWindow class]) { - event.obj = [(UiCocoaWindow*)activeWindow object]; - event.window = event.obj->window; - event.document = event.obj->ctx->document; - } else { - event.window = NULL; - event.document = NULL; - } - event.eventdata = lastSelection; - event.intval = lastSelection->count == 0 ? -1 : lastSelection->rows[0]; - - info->activate(&event, info->userdata); -} - -- (BOOL)tableView:(NSTableView *)tableview isGroupRow:(NSInteger)row { - return NO; -} - -@end - - -UIWIDGET ui_table(UiObject *obj, UiList *model, UiModelInfo *modelinfo) { - UiContainer *ct = uic_get_current_container(obj); - NSRect frame = ct->getframe(ct); - - NSScrollView *scrollview = [[NSScrollView alloc] initWithFrame:frame]; - [scrollview setHasVerticalScroller:YES]; - //[scrollvew setHasHorizontalScroller:YES]; - [scrollview setBorderType:NSNoBorder]; - //[scrollview setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable]; - - NSTableView *tableview = [[NSTableView alloc]initWithFrame:frame]; - [scrollview setDocumentView:tableview]; - [tableview setAllowsMultipleSelection: YES]; - //[tableview setSelectionHighlightStyle:NSTableViewSelectionHighlightStyleSourceList]; - - // add columns - for(int i=0;i<modelinfo->columns;i++) { - NSString *cid = [[NSString alloc]initWithFormat: @"%d", i]; - NSTableColumn *column = [[NSTableColumn alloc]initWithIdentifier:cid]; - - NSString *title = [[NSString alloc]initWithUTF8String: modelinfo->titles[i]]; - [[column headerCell] setStringValue:title]; - - [tableview addTableColumn:column]; - } - - UiTableDataSource *source = [[UiTableDataSource alloc]initWithData:model modelInfo:modelinfo]; - [tableview setDataSource:source]; - [tableview setDelegate:source]; - - [tableview setDoubleAction:@selector(handleDoubleAction:)]; - [tableview setTarget:source]; - - - ct->add(ct, scrollview); - return scrollview; -} - - -UIWIDGET ui_listview_var(UiObject *obj, UiListPtr *list, ui_model_getvalue_f getvalue, ui_callback f, void *udata) { - UiContainer *ct = uic_get_current_container(obj); - NSRect frame = ct->getframe(ct); - - NSScrollView *scrollview = [[NSScrollView alloc] initWithFrame:frame]; - [scrollview setHasVerticalScroller:YES]; - - [scrollview setBorderType:NSNoBorder]; - - NSTableView *tableview = [[NSTableView alloc]initWithFrame:frame]; - [scrollview setDocumentView:tableview]; - [tableview setAllowsMultipleSelection: NO]; - - // add single column - NSTableColumn *column = [[NSTableColumn alloc]initWithIdentifier:@"c"]; - [tableview addTableColumn:column]; - - // create model info - UiModelInfo *modelinfo = ui_model_info(obj->ctx, UI_STRING, -1); - - // add source - UiTableDataSource *source = [[UiTableDataSource alloc]initWithData:list->list modelInfo:modelinfo]; - - [tableview setDataSource:source]; - [tableview setDelegate:source]; - - [tableview setDoubleAction:@selector(handleDoubleAction:)]; - [tableview setTarget:source]; - - ct->add(ct, scrollview); - return scrollview; -} - -UIWIDGET ui_listview(UiObject *obj, UiList *list, ui_model_getvalue_f getvalue, ui_callback f, void *udata) { - UiListPtr *listptr = ucx_mempool_malloc(obj->ctx->mempool, sizeof(UiListPtr)); - listptr->list = list; - return ui_listview_var(obj, listptr, getvalue, f, udata); -} - -UIWIDGET ui_listview_nv(UiObject *obj, char *varname, ui_model_getvalue_f getvalue, ui_callback f, void *udata) { - UiVar *var = uic_connect_var(obj->ctx, varname, UI_VAR_LIST); - if(var) { - UiListVar *value = var->value; - return ui_listview_var(obj, value->listptr, getvalue, f, udata); - } else { - // TODO: error - } - return NULL; -} - - -// TODO: motif code duplicate -char* ui_type_to_string(UiModelType type, void *data, BOOL *free) { - switch(type) { - case UI_STRING: *free = FALSE; return data; - case UI_INTEGER: { - *free = TRUE; - int *val = data; - sstr_t str = ucx_asprintf(ucx_default_allocator(), "%d", *val); - return str.ptr; - } - } - *free = FALSE; - return NULL; -}
--- a/ui/cocoa/window.m Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/cocoa/window.m Sun Jul 20 22:04:39 2025 +0200 @@ -31,6 +31,8 @@ #import "MainWindow.h" #import "WindowManager.h" +#import <objc/runtime.h> + #include "../ui/window.h" #include "../ui/properties.h" #include "../common/context.h" @@ -39,6 +41,7 @@ #include <cx/mempool.h> + static UiObject* create_window(const char *title, BOOL simple) { CxMempool *mp = cxMempoolCreateSimple(256); UiObject *obj = cxCalloc(mp->allocator, 1, sizeof(UiObject)); @@ -52,6 +55,11 @@ obj->wobj = (__bridge void*)window; + MainWindowController *controller = [[MainWindowController alloc] initWithWindow:obj window:window]; + window.windowController = controller; + [window setNextResponder:(NSResponder*)controller]; + objc_setAssociatedObject(window, "windowcontroller", controller, OBJC_ASSOCIATION_RETAIN); + return obj; }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/common/args.c Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,1736 @@ +/* + * 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 <string.h> +#include <stdlib.h> + +#include "../ui/container.h" + + +/* ---------------------------- UiDialogArgs ---------------------------- */ + +UiDialogArgs* ui_dialog_args_new(void) { + UiDialogArgs *args = malloc(sizeof(UiDialogArgs)); + memset(args, 0, sizeof(UiDialogArgs)); + return args; +} + +void ui_dialog_args_set_title(UiDialogArgs *args, const char *title) { + args->title = strdup(title); +} + +void ui_dialog_args_set_content(UiDialogArgs *args, const char *str) { + args->content = strdup(str); +} + +void ui_dialog_args_set_button1_label(UiDialogArgs *args, const char *label) { + args->button1_label = strdup(label); +} + +void ui_dialog_args_set_button2_label(UiDialogArgs *args, const char *label) { + args->button2_label = strdup(label); +} + +void ui_dialog_args_set_closebutton_label(UiDialogArgs *args, const char *label) { + args->closebutton_label = strdup(label); +} + +void ui_dialog_args_set_input_value(UiDialogArgs *args, const char *value) { + args->input_value = strdup(value); +} + +void ui_dialog_args_set_input(UiDialogArgs *args, UiBool input) { + args->input = input; +} + +void ui_dialog_args_set_password(UiDialogArgs *args, UiBool password) { + args->password = password; +} + +void ui_dialog_args_set_result(UiDialogArgs *args, ui_callback cb) { + args->result = cb; +} + +void ui_dialog_args_set_resultdata(UiDialogArgs *args, void *userdata) { + args->resultdata = userdata; +} + +void ui_dialog_args_free(UiDialogArgs *args) { + free((void*)args->title); + free((void*)args->button1_label); + free((void*)args->button2_label); + free((void*)args->content); + free((void*)args->closebutton_label); + free((void*)args->input_value); + free(args); +} + + +/* -------------------------- UiDialogWindowArgs -------------------------- */ + +UiDialogWindowArgs* ui_dialogwindow_args_new(void) { + UiDialogWindowArgs *args = malloc(sizeof(UiDialogWindowArgs)); + memset(args, 0, sizeof(UiDialogWindowArgs)); + return args; +} + +void ui_dialogwindow_args_set_modal(UiDialogWindowArgs *args, UiTri value) { + args->modal = value; +} + +void ui_dialogwindow_args_set_titlebar_buttons(UiDialogWindowArgs *args, UiTri value) { + args->titlebar_buttons = value; +} + +void ui_dialogwindow_args_set_show_closebutton(UiDialogWindowArgs *args, UiTri value) { + args->show_closebutton = value; +} + +void ui_dialogwindow_args_set_title(UiDialogWindowArgs *args, const char *title) { + args->title = strdup(title); +} + +void ui_dialogwindow_args_set_lbutton1(UiDialogWindowArgs *args, const char *label) { + args->lbutton1 = strdup(label); +} + +void ui_dialogwindow_args_set_lbutton2(UiDialogWindowArgs *args, const char *label) { + args->lbutton2 = strdup(label); +} + +void ui_dialogwindow_args_set_rbutton3(UiDialogWindowArgs *args, const char *label) { + args->rbutton3 = strdup(label); +} + +void ui_dialogwindow_args_set_rbutton4(UiDialogWindowArgs *args, const char *label) { + args->rbutton4 = strdup(label); +} + +void ui_dialogwindow_args_set_lbutton1_states(UiDialogWindowArgs *args, const int *states) { + // TODO +} + +void ui_dialogwindow_args_set_lbutton2_states(UiDialogWindowArgs *args, const int *states) { + // TODO +} + +void ui_dialogwindow_args_set_rbutton3_states(UiDialogWindowArgs *args, const int *states) { + // TODO +} + +void ui_dialogwindow_args_set_rbutton4_states(UiDialogWindowArgs *args, const int *states) { + // TODO +} + +void ui_dialogwindow_args_set_default_button(UiDialogWindowArgs *args, int button) { + args->default_button = button; +} + +void ui_dialogwindow_args_set_width(UiDialogWindowArgs *args, int width) { + args->width = width; +} + +void ui_dialogwindow_args_set_height(UiDialogWindowArgs *args, int height) { + args->height = height; +} + +void ui_dialogwindow_args_set_onclick(UiDialogWindowArgs *args, ui_callback cb) { + args->onclick = cb; +} + +void ui_dialogwindow_args_set_onclickdata(UiDialogWindowArgs *args, void *userdata) { + args->onclickdata = userdata; +} + +void ui_dialogwindow_args_free(UiDialogWindowArgs *args) { + free((void*)args->title); + free((void*)args->lbutton1); + free((void*)args->lbutton2); + free((void*)args->rbutton3); + free((void*)args->rbutton4); + free((void*)args->lbutton1_groups); + free((void*)args->lbutton2_groups); + free((void*)args->rbutton3_groups); + free((void*)args->rbutton4_groups); + free(args); +} + + +/* ---------------------------- UiMenuItemArgs ---------------------------- */ + +UiMenuItemArgs* ui_menuitem_args_new(void) { + UiMenuItemArgs *args = malloc(sizeof(UiMenuItemArgs)); + memset(args, 0, sizeof(UiMenuItemArgs)); + return args; +} + +void ui_menuitem_args_set_label(UiMenuItemArgs *args, const char *label) { + args->label = strdup(label); +} + +void ui_menuitem_args_set_stockid(UiMenuItemArgs *args, const char *stockid) { + args->stockid = strdup(stockid); +} + +void ui_menuitem_args_set_icon(UiMenuItemArgs *args, const char *icon) { + args->icon = strdup(icon); +} + +void ui_menuitem_args_set_onclick(UiMenuItemArgs *args, ui_callback callback) { + args->onclick = callback; +} + +void ui_menuitem_args_set_onclickdata(UiMenuItemArgs *args, void *onclickdata) { + args->onclickdata = onclickdata; +} + +void ui_menuitem_args_free(UiMenuItemArgs *args) { + free((void*)args->label); + free((void*)args->stockid); + free((void*)args->icon); + free(args); +} + + +/* ---------------------------- UiMenuToggleItemArgs ---------------------------- */ + +UiMenuToggleItemArgs* ui_menutoggleitem_args_new(void) { + UiMenuToggleItemArgs *args = malloc(sizeof(UiMenuToggleItemArgs)); + memset(args, 0, sizeof(UiMenuToggleItemArgs)); + return args; +} + +void ui_menutoggleitem_args_set_label(UiMenuToggleItemArgs *args, const char *label) { + args->label = strdup(label); +} + +void ui_menutoggleitem_args_set_stockid(UiMenuToggleItemArgs *args, const char *stockid) { + args->stockid = strdup(stockid); +} + +void ui_menutoggleitem_args_set_icon(UiMenuToggleItemArgs *args, const char *icon) { + args->icon = strdup(icon); +} + +void ui_menutoggleitem_args_set_varname(UiMenuToggleItemArgs *args, const char *varname) { + args->varname = strdup(varname); +} + +void ui_menutoggleitem_args_set_onchange(UiMenuToggleItemArgs *args, ui_callback callback) { + args->onchange = callback; +} + +void ui_menutoggleitem_args_set_onchangedata(UiMenuToggleItemArgs *args, void *onclickdata) { + args->onchangedata = onclickdata; +} + +void ui_menutoggleitem_args_free(UiMenuToggleItemArgs *args) { + free((void*)args->label); + free((void*)args->stockid); + free((void*)args->icon); + free((void*)args->varname); + free(args); +} + +/* --------------------------- UiMenuItemListArgs --------------------------- */ + +UiMenuItemListArgs* ui_menuitemlist_args_new(void) { + UiMenuItemListArgs *args = malloc(sizeof(UiMenuItemListArgs)); + memset(args, 0, sizeof(UiMenuItemListArgs)); + return args; +} + +void ui_menuitemlist_args_set_varname(UiMenuItemListArgs *args, const char *varname) { + args->varname = strdup(varname); +} + +void ui_menuitemlist_args_set_getvalue(UiMenuItemListArgs *args, ui_getvaluefunc func) { + args->getvalue = func; +} + +void ui_menuitemlist_args_set_onselect(UiMenuItemListArgs *args, ui_callback callback) { + args->onselect = callback; +} + +void ui_menuitemlist_args_set_onselectdata(UiMenuItemListArgs *args, void *data){ + args->onselectdata = data; +} + +void ui_menuitemlist_args_set_addseparator(UiMenuItemListArgs *args, UiBool value) { + args->addseparator = value; +} + +void ui_menuitemlist_args_free(UiMenuItemListArgs *args){ + free((void*)args->varname); + free(args); +} + +/* --------------------------- UiToolbarItemArgs --------------------------- */ + +UiToolbarItemArgs* ui_toolbar_item_args_new(void) { + UiToolbarItemArgs *args = malloc(sizeof(UiToolbarItemArgs)); + memset(args, 0, sizeof(UiToolbarItemArgs)); + return args; +} + +void ui_toolbar_item_args_set_label(UiToolbarItemArgs *args, const char *label) { + args->label = strdup(label); +} + +void ui_toolbar_item_args_set_stockid(UiToolbarItemArgs *args, const char *stockid) { + args->stockid = strdup(stockid); +} + +void ui_toolbar_item_args_set_icon(UiToolbarItemArgs *args, const char *icon) { + args->icon = strdup(icon); +} + +void ui_toolbar_item_args_set_onclick(UiToolbarItemArgs *args, ui_callback callback) { + args->onclick = callback; +} + +void ui_toolbar_item_args_set_onclickdata(UiToolbarItemArgs *args, void *onclickdata) { + args->onclickdata = onclickdata; +} + +void ui_toolbar_item_args_set_groups(UiToolbarItemArgs *args, int *groups) { + // TODO +} +void ui_toolbar_item_args_free(UiToolbarItemArgs *args) { + free((void*)args->label); + free((void*)args->stockid); + free((void*)args->icon); + free(args); +} + +/* ---------------------------- UiToolbarToggleItemArgs ---------------------------- */ + +UiToolbarToggleItemArgs* ui_toolbar_toggleitem_args_new(void) { + UiToolbarToggleItemArgs *args = malloc(sizeof(UiToolbarToggleItemArgs)); + memset(args, 0, sizeof(UiToolbarToggleItemArgs)); + return args; +} + + +void ui_toolbar_toggleitem_args_set_label(UiToolbarToggleItemArgs *args, const char *label) { + args->label = strdup(label); +} + + +void ui_toolbar_toggleitem_args_set_stockid(UiToolbarToggleItemArgs *args, const char *stockid) { + args->stockid = strdup(stockid); +} + + +void ui_toolbar_toggleitem_args_set_icon(UiToolbarToggleItemArgs *args, const char *icon) { + args->icon = strdup(icon); +} + + +void ui_toolbar_toggleitem_args_set_varname(UiToolbarToggleItemArgs *args, const char *varname) { + args->varname = strdup(varname); +} + + +void ui_toolbar_toggleitem_args_set_onchange(UiToolbarToggleItemArgs *args, ui_callback callback) { + args->onchange = callback; +} + + +void ui_toolbar_toggleitem_args_set_onchangedata(UiToolbarToggleItemArgs *args, void *onchangedata) { + args->onchangedata = onchangedata; +} + + +void ui_toolbar_toggleitem_args_set_groups(UiToolbarToggleItemArgs *args, int *groups) { + // TODO +} + + +void ui_toolbar_toggleitem_args_free(UiToolbarToggleItemArgs *args) { + free((void*)args->label); + free((void*)args->stockid); + free((void*)args->icon); + free((void*)args->varname); + free(args); +} + +/* ---------------------------- UiToolbarMenuArgs ---------------------------- */ + + +UiToolbarMenuArgs* ui_toolbar_menu_args_new(void) { + UiToolbarMenuArgs *args = malloc(sizeof(UiToolbarMenuArgs)); + memset(args, 0, sizeof(UiToolbarMenuArgs)); + return args; +} + + +void ui_toolbar_menu_args_set_label(UiToolbarMenuArgs *args, const char *label) { + args->label = strdup(label); +} + + +void ui_toolbar_menu_args_set_stockid(UiToolbarMenuArgs *args, const char *stockid) { + args->stockid = strdup(stockid); +} + + +void ui_toolbar_menu_args_set_icon(UiToolbarMenuArgs *args, const char *icon) { + args->icon = strdup(icon); +} + + +void ui_toolbar_menu_args_free(UiToolbarMenuArgs *args) { + free((void*)args->label); + free((void*)args->stockid); + free((void*)args->icon); + free(args); +} + + +/* ---------------------------- UiContainerArgs ---------------------------- */ + +UiContainerArgs* ui_container_args_new(void) { + UiContainerArgs *args = malloc(sizeof(UiContainerArgs)); + memset(args, 0, sizeof(UiContainerArgs)); + return args; +} + +void ui_container_args_set_fill(UiContainerArgs *args, UiBool fill) { + args->fill = fill ? UI_ON : UI_OFF; +} + +void ui_container_args_set_hexpand(UiContainerArgs *args, UiBool value) { + args->hexpand = value; +} + + +void ui_container_args_set_vexpand(UiContainerArgs *args, UiBool value) { + args->vexpand = value; +} + + +void ui_container_args_set_hfill(UiContainerArgs *args, UiBool value) { + args->hfill = value; +} + + +void ui_container_args_set_vfill(UiContainerArgs *args, UiBool value) { + args->vfill = value; +} + + +void ui_container_args_set_override_defaults(UiContainerArgs *args, UiBool value) { + args->override_defaults = value; +} + + +void ui_container_args_set_colspan(UiContainerArgs *args, int colspan) { + args->colspan = colspan; +} + + +void ui_container_args_set_rowspan(UiContainerArgs *args, int rowspan) { + args->rowspan = rowspan; +} + + +void ui_container_args_set_def_hexpand(UiContainerArgs *args, UiBool value) { + args->def_hexpand = value; +} + + +void ui_container_args_set_def_vexpand(UiContainerArgs *args, UiBool value) { + args->def_vexpand = value; +} + + +void ui_container_args_set_def_hfill(UiContainerArgs *args, UiBool value) { + args->def_hfill = value; +} + + +void ui_container_args_set_def_vfill(UiContainerArgs *args, UiBool value) { + args->def_vfill = value; +} + + +void ui_container_args_set_name(UiContainerArgs *args, const char *name) { + args->name = strdup(name); +} + + +void ui_container_args_set_style_class(UiContainerArgs *args, const char *classname) { + args->style_class = strdup(classname); +} + + +void ui_container_args_set_margin(UiContainerArgs *args, int value) { + args->margin = value; +} + + +void ui_container_args_set_spacing(UiContainerArgs *args, int value) { + args->spacing = value; +} + + +void ui_container_args_set_columnspacing(UiContainerArgs *args, int value) { + args->columnspacing = value; +} + + +void ui_container_args_set_rowspacing(UiContainerArgs *args, int value) { + args->rowspacing = value; +} + + +void ui_container_args_free(UiContainerArgs *args) { + free((void*)args->name); + free((void*)args->style_class); + free(args); +} + + +/* ------------------------------- UiFrameArgs ------------------------------*/ + +UiFrameArgs* ui_frame_args_new(void) { + UiFrameArgs *args = malloc(sizeof(UiFrameArgs)); + memset(args, 0, sizeof(UiContainerArgs)); + return args; +} + + +void ui_frame_args_set_fill(UiFrameArgs *args, UiBool fill) { + args->fill = fill ? UI_ON : UI_OFF; +} + + +void ui_frame_args_set_hexpand(UiFrameArgs *args, UiBool value) { + args->hexpand = value; +} + + +void ui_frame_args_set_vexpand(UiFrameArgs *args, UiBool value) { + args->vexpand = value; +} + + +void ui_frame_args_set_hfill(UiFrameArgs *args, UiBool value) { + args->hfill = value; +} + + +void ui_frame_args_set_vfill(UiFrameArgs *args, UiBool value) { + args->vfill = value; +} + + +void ui_frame_args_set_override_defaults(UiFrameArgs *args, UiBool value) { + args->override_defaults = value; +} + + +void ui_frame_args_set_colspan(UiFrameArgs *args, int colspan) { + args->colspan = colspan; +} + + +void ui_frame_args_set_rowspan(UiFrameArgs *args, int rowspan) { + args->rowspan = rowspan; +} + + +void ui_frame_args_set_name(UiFrameArgs *args, const char *name) { + args->name = strdup(name); +} + + +void ui_frame_args_set_style_class(UiFrameArgs *args, const char *classname) { + args->style_class = strdup(classname); +} + + +void ui_frame_args_set_margin(UiFrameArgs *args, int value) { + args->margin = value; +} + + +void ui_frame_args_set_spacing(UiFrameArgs *args, int value) { + args->spacing = value; +} + + +void ui_frame_args_set_columnspacing(UiFrameArgs *args, int value) { + args->columnspacing = value; +} + + +void ui_frame_args_set_rowspacing(UiFrameArgs *args, int value) { + args->rowspacing = value; +} + + +void ui_frame_args_set_expanded(UiFrameArgs *args, UiBool value) { + args->isexpanded = value; +} + + +void ui_frame_args_set_label(UiFrameArgs *args, const char *label) { + args->label = strdup(label); +} + + +void ui_frame_args_free(UiFrameArgs *args) { + free((void*)args->name); + free((void*)args->style_class); + free((void*)args->label); + free(args); +} + + +/* ---------------------------- UiSidebarArgs -------------------------------*/ + +UiSidebarArgs* ui_sidebar_args_new(void) { + UiSidebarArgs *args = malloc(sizeof(UiSidebarArgs)); + memset(args, 0, sizeof(UiSidebarArgs)); + return args; +} + + +void ui_sidebar_args_set_name(UiSidebarArgs *args, const char *name) { + args->name = strdup(name); +} + + +void ui_sidebar_args_set_style_class(UiSidebarArgs *args, const char *classname) { + args->style_class = strdup(classname); +} + + +void ui_sidebar_args_set_margin(UiSidebarArgs *args, int value) { + args->margin = value; +} + + +void ui_sidebar_args_set_spacing(UiSidebarArgs *args, int value) { + args->spacing = value; +} + + +void ui_sidebar_args_free(UiSidebarArgs *args) { + free((void*)args->name); + free((void*)args->style_class); + free(args); +} + + +/* --------------------------- UiSplitPaneArgs ------------------------------*/ + +UiSplitPaneArgs* ui_splitpane_args_new(void) { + UiSplitPaneArgs *args = malloc(sizeof(UiSplitPaneArgs)); + memset(args, 0, sizeof(UiSplitPaneArgs)); + return args; +} + + +void ui_splitpane_args_set_fill(UiSplitPaneArgs *args, UiBool fill) { + args->fill = fill ? UI_ON : UI_OFF; +} + + +void ui_splitpane_args_set_hexpand(UiSplitPaneArgs *args, UiBool value) { + args->hexpand = value; +} + + +void ui_splitpane_args_set_vexpand(UiSplitPaneArgs *args, UiBool value) { + args->vexpand = value; +} + + +void ui_splitpane_args_set_hfill(UiSplitPaneArgs *args, UiBool value) { + args->hfill = value; +} + + +void ui_splitpane_args_set_vfill(UiSplitPaneArgs *args, UiBool value) { + args->vfill = value; +} + + +void ui_splitpane_args_set_override_defaults(UiSplitPaneArgs *args, UiBool value) { + args->override_defaults = value; +} + + +void ui_splitpane_args_set_colspan(UiSplitPaneArgs *args, int colspan) { + args->colspan = colspan; +} + + +void ui_splitpane_args_set_rowspan(UiSplitPaneArgs *args, int rowspan) { + args->rowspan = rowspan; +} + + +void ui_splitpane_args_set_name(UiSplitPaneArgs *args, const char *name) { + args->name = strdup(name); +} + + +void ui_splitpane_args_set_style_class(UiSplitPaneArgs *args, const char *classname) { + args->style_class = strdup(classname); +} + + +void ui_splitpane_args_set_margin(UiSplitPaneArgs *args, int value) { + args->margin = value; +} + + +void ui_splitpane_args_set_spacing(UiSplitPaneArgs *args, int value) { + args->spacing = value; +} + + +void ui_splitpane_args_set_columnspacing(UiSplitPaneArgs *args, int value) { + args->columnspacing = value; +} + + +void ui_splitpane_args_set_rowspacing(UiSplitPaneArgs *args, int value) { + args->rowspacing = value; +} + + +void ui_splitpane_args_set_initial_position(UiSplitPaneArgs *args, int pos) { + args->initial_position = pos; +} + + +void ui_splitpane_args_set_varname(UiSplitPaneArgs *args, const char *varname) { + args->varname = strdup(varname); +} + + +void ui_splitpane_args_set_value(UiSplitPaneArgs *args, UiInteger *value) { + args->value = value; +} + +void ui_splitpane_args_set_max_panes(UiSplitPaneArgs *args, int max) { + args->max_panes = max; +} + + +void ui_splitpane_args_free(UiSplitPaneArgs *args) { + free((void*)args->name); + free((void*)args->style_class); + free((void*)args->varname); + free(args); +} + + +/* ------------------------- UiLabelArgs ----------------------------*/ + + +UiLabelArgs* ui_label_args_new(void) { + UiLabelArgs *args = malloc(sizeof(UiLabelArgs)); + memset(args, 0, sizeof(UiLabelArgs)); + return args; +} + + +void ui_label_args_set_fill(UiLabelArgs *args, UiBool fill) { + args->fill = fill ? UI_ON : UI_OFF; +} + + +void ui_label_args_set_hexpand(UiLabelArgs *args, UiBool value) { + args->hexpand = value; +} + + +void ui_label_args_set_vexpand(UiLabelArgs *args, UiBool value) { + args->vexpand = value; +} + + +void ui_label_args_set_hfill(UiLabelArgs *args, UiBool value) { + args->hfill = value; +} + + +void ui_label_args_set_vfill(UiLabelArgs *args, UiBool value) { + args->vfill = value; +} + + +void ui_label_args_set_override_defaults(UiLabelArgs *args, UiBool value) { + args->override_defaults = value; +} + + +void ui_label_args_set_colspan(UiLabelArgs *args, int colspan) { + args->colspan = colspan; +} + + +void ui_label_args_set_rowspan(UiLabelArgs *args, int rowspan) { + args->rowspan = rowspan; +} + + +void ui_label_args_set_name(UiLabelArgs *args, const char *name) { + args->name = strdup(name); +} + + +void ui_label_args_set_style_class(UiLabelArgs *args, const char *classname) { + args->style_class = strdup(classname); +} + +void ui_label_args_set_label(UiLabelArgs *args, const char *label){ + args->label = strdup(label); +} + + +void ui_label_args_set_align(UiLabelArgs *args, UiAlignment align) { + args->align = align; +} + +void ui_label_args_set_style(UiLabelArgs *args, UiLabelStyle style) { + args->style = style; +} + +void ui_label_args_set_varname(UiLabelArgs *args, const char *varname) { + args->varname = strdup(varname); +} + +void ui_label_args_set_value(UiLabelArgs *args, UiString *value) { + args->value = value; +} + +void ui_label_args_free(UiLabelArgs *args) { + free((void*)args->name); + free((void*)args->style_class); + free((void*)args->label); + free((void*)args->varname); + free(args); +} + + +/* ------------------------- UiProgressbarArgs ----------------------------*/ + + +UiProgressbarArgs* ui_progressbar_args_new(void) { + UiProgressbarArgs *args = malloc(sizeof(UiProgressbarArgs)); + memset(args, 0, sizeof(UiProgressbarArgs)); + return args; +} + + +void ui_progressbar_args_set_fill(UiProgressbarArgs *args, UiBool fill) { + args->fill = fill ? UI_ON : UI_OFF; +} + + +void ui_progressbar_args_set_hexpand(UiProgressbarArgs *args, UiBool value) { + args->hexpand = value; +} + + +void ui_progressbar_args_set_vexpand(UiProgressbarArgs *args, UiBool value) { + args->vexpand = value; +} + + +void ui_progressbar_args_set_hfill(UiProgressbarArgs *args, UiBool value) { + args->hfill = value; +} + + +void ui_progressbar_args_set_vfill(UiProgressbarArgs *args, UiBool value) { + args->vfill = value; +} + + +void ui_progressbar_args_set_override_defaults(UiProgressbarArgs *args, UiBool value) { + args->override_defaults = value; +} + + +void ui_progressbar_args_set_colspan(UiProgressbarArgs *args, int colspan) { + args->colspan = colspan; +} + + +void ui_progressbar_args_set_rowspan(UiProgressbarArgs *args, int rowspan) { + args->rowspan = rowspan; +} + + +void ui_progressbar_args_set_name(UiProgressbarArgs *args, const char *name) { + args->name = strdup(name); +} + + +void ui_progressbar_args_set_style_class(UiProgressbarArgs *args, const char *classname) { + args->style_class = strdup(classname); +} + +void ui_progressbar_args_set_min(UiProgressbarArgs *args, double min) { + args->min = min; +} + +void ui_progressbar_args_set_max(UiProgressbarArgs *args, double max) { + args->max = max; +} + +void ui_progressbar_args_set_varname(UiProgressbarArgs *args, const char *varname) { + args->varname = strdup(varname); +} + +void ui_progressbar_args_set_value(UiProgressbarArgs *args, UiDouble *value) { + args->value = value; +} + +void ui_progressbar_args_free(UiProgressbarArgs *args) { + free((void*)args->name); + free((void*)args->style_class); + free((void*)args->varname); + free(args); +} + + +/* ------------------------- UiProgressbarSpinnerArgs ----------------------------*/ + +UiProgressbarSpinnerArgs* ui_progress_spinner_args_new(void) { + UiProgressbarSpinnerArgs *args = malloc(sizeof(UiProgressbarSpinnerArgs)); + memset(args, 0, sizeof(UiProgressbarSpinnerArgs)); + return args; +} + +void ui_progress_spinner_args_set_fill(UiProgressbarSpinnerArgs *args, UiBool fill) { + args->fill = fill ? UI_ON : UI_OFF; +} + +void ui_progress_spinner_args_set_hexpand(UiProgressbarSpinnerArgs *args, UiBool value) { + args->hexpand = value; +} + +void ui_progress_spinner_args_set_vexpand(UiProgressbarSpinnerArgs *args, UiBool value) { + args->vexpand = value; +} + +void ui_progress_spinner_args_set_hfill(UiProgressbarSpinnerArgs *args, UiBool value) { + args->hfill = value; +} + +void ui_progress_spinner_args_set_vfill(UiProgressbarSpinnerArgs *args, UiBool value) { + args->vfill = value; +} + +void ui_progress_spinner_args_set_override_defaults(UiProgressbarSpinnerArgs *args, UiBool value) { + args->override_defaults = value; +} + +void ui_progress_spinner_args_set_colspan(UiProgressbarSpinnerArgs *args, int colspan) { + args->colspan = colspan; +} + +void ui_progress_spinner_args_set_rowspan(UiProgressbarSpinnerArgs *args, int rowspan) { + args->rowspan = rowspan; +} + +void ui_progress_spinner_args_set_name(UiProgressbarSpinnerArgs *args, const char *name) { + args->name = strdup(name); +} + +void ui_progress_spinner_args_set_style_class(UiProgressbarSpinnerArgs *args, const char *classname) { + args->style_class = strdup(classname); +} + +void ui_progress_spinner_args_set_varname(UiProgressbarSpinnerArgs *args, const char *varname) { + args->varname = strdup(varname); +} + +void ui_progress_spinner_args_set_value(UiProgressbarSpinnerArgs *args, UiInteger *value) { + args->value = value; +} + +void ui_progress_spinner_args_free(UiProgressbarSpinnerArgs *args) { + free((void*)args->name); + free((void*)args->style_class); + free((void*)args->varname); + free(args); +} + + +/* ---------------------------- UiButtonArgs -------------------------------*/ + +UiButtonArgs* ui_button_args_new(void) { + UiButtonArgs *args = malloc(sizeof(UiButtonArgs)); + memset(args, 0, sizeof(UiButtonArgs)); + return args; +} + + +void ui_button_args_set_fill(UiButtonArgs *args, UiBool fill) { + args->fill = fill ? UI_ON : UI_OFF; +} + + +void ui_button_args_set_hexpand(UiButtonArgs *args, UiBool value) { + args->hexpand = value; +} + + +void ui_button_args_set_vexpand(UiButtonArgs *args, UiBool value) { + args->vexpand = value; +} + + +void ui_button_args_set_hfill(UiButtonArgs *args, UiBool value) { + args->hfill = value; +} + + +void ui_button_args_set_vfill(UiButtonArgs *args, UiBool value) { + args->vfill = value; +} + + +void ui_button_args_set_override_defaults(UiButtonArgs *args, UiBool value) { + args->override_defaults = value; +} + + +void ui_button_args_set_colspan(UiButtonArgs *args, int colspan) { + args->colspan = colspan; +} + + +void ui_button_args_set_rowspan(UiButtonArgs *args, int rowspan) { + args->rowspan = rowspan; +} + + +void ui_button_args_set_name(UiButtonArgs *args, const char *name) { + args->name = strdup(name); +} + + +void ui_button_args_set_style_class(UiButtonArgs *args, const char *classname) { + args->style_class = strdup(classname); +} + +void ui_button_args_set_label(UiButtonArgs *args, const char *label){ + args->label = strdup(label); +} + + +void ui_button_args_set_stockid(UiButtonArgs *args, const char *stockid){ + args->stockid = strdup(stockid); +} + + +void ui_button_args_set_icon(UiButtonArgs *args, const char *icon){ + args->icon = strdup(icon); +} + + +void ui_button_args_set_labeltype(UiButtonArgs *args, int labeltype){ + args->labeltype = labeltype; +} + +void ui_button_args_set_onclick(UiButtonArgs *args, ui_callback callback){ + args->onclick = callback; +} + + +void ui_button_args_set_onclickdata(UiButtonArgs *args, void *onclickdata){ + args->onclickdata = onclickdata; +} + +void ui_button_args_set_groups(UiButtonArgs *args, int *groups){ + // TODO +} + +void ui_button_args_free(UiButtonArgs *args) { + free((void*)args->name); + free((void*)args->style_class); + free((void*)args->label); + free((void*)args->stockid); + free((void*)args->icon); + free((void*)args->groups); + free(args); +} + + +/* ------------------------- UiToggleArgs ----------------------------*/ + + +UiToggleArgs* ui_toggle_args_new(void) { + UiToggleArgs *args = malloc(sizeof(UiToggleArgs)); + memset(args, 0, sizeof(UiToggleArgs)); + return args; +} + + +void ui_toggle_args_set_fill(UiToggleArgs *args, UiBool fill) { + args->fill = fill ? UI_ON : UI_OFF; +} + + +void ui_toggle_args_set_hexpand(UiToggleArgs *args, UiBool value) { + args->hexpand = value; +} + + +void ui_toggle_args_set_vexpand(UiToggleArgs *args, UiBool value) { + args->vexpand = value; +} + + +void ui_toggle_args_set_hfill(UiToggleArgs *args, UiBool value) { + args->hfill = value; +} + + +void ui_toggle_args_set_vfill(UiToggleArgs *args, UiBool value) { + args->vfill = value; +} + + +void ui_toggle_args_set_override_defaults(UiToggleArgs *args, UiBool value) { + args->override_defaults = value; +} + + +void ui_toggle_args_set_colspan(UiToggleArgs *args, int colspan) { + args->colspan = colspan; +} + + +void ui_toggle_args_set_rowspan(UiToggleArgs *args, int rowspan) { + args->rowspan = rowspan; +} + + +void ui_toggle_args_set_name(UiToggleArgs *args, const char *name) { + args->name = strdup(name); +} + + +void ui_toggle_args_set_style_class(UiToggleArgs *args, const char *classname) { + args->style_class = strdup(classname); +} + +void ui_toggle_args_set_label(UiToggleArgs *args, const char *label){ + args->label = strdup(label); +} + + +void ui_toggle_args_set_stockid(UiToggleArgs *args, const char *stockid){ + args->stockid = strdup(stockid); +} + + +void ui_toggle_args_set_icon(UiToggleArgs *args, const char *icon){ + args->icon = strdup(icon); +} + + +void ui_toggle_args_set_labeltype(UiToggleArgs *args, int labeltype){ + args->labeltype = labeltype; +} + +void ui_toggle_args_set_onchange(UiToggleArgs *args, ui_callback callback){ + args->onchange = callback; +} + + +void ui_toggle_args_set_onchangedata(UiToggleArgs *args, void *onchangedata){ + args->onchangedata = onchangedata; +} + +void ui_toggle_args_set_varname(UiToggleArgs *args, const char *varname) { + args->varname = strdup(varname); +} + +void ui_toggle_args_set_value(UiToggleArgs *args, UiInteger *value) { + args->value = value; +} + +void ui_toggle_args_set_enablegroup(UiToggleArgs *args, int group) { + args->enable_group = group; +} + +void ui_toggle_args_set_groups(UiToggleArgs *args, int *groups){ + // TODO +} + +void ui_toggle_args_free(UiToggleArgs *args) { + free((void*)args->name); + free((void*)args->style_class); + free((void*)args->label); + free((void*)args->stockid); + free((void*)args->icon); + free((void*)args->varname); + free((void*)args->groups); + free(args); +} + + +/* ------------------------- UiListArgs ----------------------------*/ + +UiListArgs* ui_list_args_new(void) { + UiListArgs *args = malloc(sizeof(UiListArgs)); + memset(args, 0, sizeof(UiListArgs)); + return args; +} + +void ui_list_args_set_fill(UiListArgs *args, UiBool fill) { + args->fill = fill ? UI_ON : UI_OFF; +} + +void ui_list_args_set_hexpand(UiListArgs *args, UiBool value) { + args->hexpand = value; +} + +void ui_list_args_set_vexpand(UiListArgs *args, UiBool value) { + args->vexpand = value; +} + +void ui_list_args_set_hfill(UiListArgs *args, UiBool value) { + args->hfill = value; +} + +void ui_list_args_set_vfill(UiListArgs *args, UiBool value) { + args->vfill = value; +} + +void ui_list_args_set_override_defaults(UiListArgs *args, UiBool value) { + args->override_defaults = value; +} + +void ui_list_args_set_colspan(UiListArgs *args, int colspan) { + args->colspan = colspan; +} + +void ui_list_args_set_rowspan(UiListArgs *args, int rowspan) { + args->rowspan = rowspan; +} + +void ui_list_args_set_name(UiListArgs *args, const char *name) { + args->name = strdup(name); +} + +void ui_list_args_set_style_class(UiListArgs *args, const char *classname) { + args->style_class = classname; +} + +void ui_list_args_set_varname(UiListArgs *args, const char *varname) { + args->varname = strdup(varname); +} + +void ui_list_args_set_value(UiListArgs *args, UiList *value) { + args->list = value; +} + +void ui_list_args_set_model(UiListArgs *args, UiModel *model) { + args->model = model; +} + +void ui_list_args_set_static_elements(UiListArgs *args, char **strarray, size_t nelm) { + char **array = calloc(nelm, sizeof(char*)); + for(int i=0;i<nelm;i++) { + array[i] = strdup(strarray[i]); + } + args->static_elements = array; + args->static_nelm = nelm; +} + +void ui_list_args_set_getvalue_func(UiListArgs *args, ui_getvaluefunc getvalue) { + args->getvalue = getvalue; +} + +void ui_list_args_set_getvalue_func2(UiListArgs *args, ui_getvaluefunc2 getvalue) { + args->getvalue2 = getvalue; +} + +void ui_list_args_set_getvalue_data(UiListArgs *args, void *userdata) { + args->getvalue2data = userdata; +} + +void ui_list_args_set_onactivate(UiListArgs *args, ui_callback callback) { + args->onactivate = callback; +} + +void ui_list_args_set_onactivatedata(UiListArgs *args, void *userdata) { + args->onactivatedata = userdata; +} + +void ui_list_args_set_onselection(UiListArgs *args, ui_callback callback) { + args->onselection = callback; +} + +void ui_list_args_set_onselectiondata(UiListArgs *args, void *userdata) { + args->onselectiondata = userdata; +} + +void ui_list_args_set_ondragstart(UiListArgs *args, ui_callback callback) { + args->ondragstart = callback; +} + +void ui_list_args_set_ondragstartdata(UiListArgs *args, void *userdata) { + args->ondragstartdata = userdata; +} + +void ui_list_args_set_ondragcomplete(UiListArgs *args, ui_callback callback) { + args->ondragcomplete = callback; +} + +void ui_list_args_set_ondragcompletedata(UiListArgs *args, void *userdata) { + args->ondragcompletedata = userdata; +} + +void ui_list_args_set_ondrop(UiListArgs *args, ui_callback callback) { + args->ondrop = callback; +} + +void ui_list_args_set_ondropdata(UiListArgs *args, void *userdata) { + args->ondropdata = userdata; +} + +void ui_list_args_set_multiselection(UiListArgs *args, UiBool multiselection) { + args->multiselection = multiselection; +} + +void ui_list_args_set_contextmenu(UiListArgs *args, UiMenuBuilder *menubuilder) { + args->contextmenu = menubuilder; +} + +void ui_list_args_set_groups(UiListArgs *args, int *groups) { + // TODO +} + +void ui_list_args_free(UiListArgs *args) { + free((void*)args->name); + free((void*)args->style_class); + free((void*)args->varname); + if(args->static_elements) { + for(int i=0;i<args->static_nelm;i++) { + free(args->static_elements[i]); + } + free(args->static_elements); + } + free(args); +} + + + +/* ---------------------- SurceList ------------------------------------- */ + +UiSourceListArgs* ui_sourcelist_args_new(void) { + UiSourceListArgs *args = malloc(sizeof(UiSourceListArgs)); + memset(args, 0, sizeof(UiSourceListArgs)); + return args; +} + + +void ui_sourcelist_args_set_fill(UiSourceListArgs *args, UiBool fill) { + args->fill = fill ? UI_ON : UI_OFF; +} + + +void ui_sourcelist_args_set_hexpand(UiSourceListArgs *args, UiBool value) { + args->hexpand = value; +} + + +void ui_sourcelist_args_set_vexpand(UiSourceListArgs *args, UiBool value) { + args->vexpand = value; +} + + +void ui_sourcelist_args_set_hfill(UiSourceListArgs *args, UiBool value) { + args->hfill = value; +} + + +void ui_sourcelist_args_set_vfill(UiSourceListArgs *args, UiBool value) { + args->vfill = value; +} + + +void ui_sourcelist_args_set_override_defaults(UiSourceListArgs *args, UiBool value) { + args->override_defaults = value; +} + + +void ui_sourcelist_args_set_colspan(UiSourceListArgs *args, int colspan) { + args->colspan = colspan; +} + + +void ui_sourcelist_args_set_rowspan(UiSourceListArgs *args, int rowspan) { + args->rowspan = rowspan; +} + + +void ui_sourcelist_args_set_name(UiSourceListArgs *args, const char *name) { + args->name = strdup(name); +} + + +void ui_sourcelist_args_set_style_class(UiSourceListArgs *args, const char *classname) { + args->style_class = strdup(classname); +} + +UIEXPORT void ui_sourcelist_args_set_static_sublists(UiSourceListArgs *args, UiSubList *sublists, size_t numsublists) { + args->sublists = calloc(numsublists, sizeof(UiSubList)); + memcpy(args->sublists, sublists, numsublists * sizeof(UiSubList)); + args->numsublists = numsublists; +} + +void ui_sourcelist_args_set_varname(UiSourceListArgs *args, const char *varname) { + args->varname = strdup(varname); +} + + +void ui_sourcelist_args_set_dynamic_sublists(UiSourceListArgs *args, UiList *value) { + args->dynamic_sublist = value; +} + + +void ui_sourcelist_args_set_getvalue_func(UiSourceListArgs *args, ui_sublist_getvalue_func getvalue) { + args->getvalue = getvalue; +} + +void ui_sourcelist_args_set_getvalue_userdata(UiSourceListArgs *args, void *userdata) { + args->getvaluedata = userdata; +} + +void ui_sourcelist_args_set_onactivate(UiSourceListArgs *args, ui_callback callback) { + args->onactivate = callback; +} + + +void ui_sourcelist_args_set_onactivatedata(UiSourceListArgs *args, void *userdata) { + args->onactivatedata = userdata; +} + + +void ui_sourcelist_args_set_onbuttonclick(UiSourceListArgs *args, ui_callback callback) { + args->onbuttonclick = callback; + +} + + +void ui_sourcelist_args_set_onbuttonclickdata(UiSourceListArgs *args, void *userdata) { + args->onbuttonclickdata = userdata; +} + + +void ui_sourcelist_args_free(UiSourceListArgs *args) { + free((void*)args->name); + free((void*)args->style_class); + free((void*)args->varname); + free((void*)args->sublists); + free(args); +} + + +/* ------------------------- UiTextAreaArgs ----------------------------*/ + +UiTextAreaArgs* ui_textarea_args_new(void) { + UiTextAreaArgs *args = malloc(sizeof(UiTextAreaArgs)); + memset(args, 0, sizeof(UiTextAreaArgs)); + return args; +} + + +void ui_textarea_args_set_fill(UiTextAreaArgs *args, UiBool fill) { + args->fill = fill ? UI_ON : UI_OFF; +} + + +void ui_textarea_args_set_hexpand(UiTextAreaArgs *args, UiBool value) { + args->hexpand = value; +} + + +void ui_textarea_args_set_vexpand(UiTextAreaArgs *args, UiBool value) { + args->vexpand = value; +} + + +void ui_textarea_args_set_hfill(UiTextAreaArgs *args, UiBool value) { + args->hfill = value; +} + + +void ui_textarea_args_set_vfill(UiTextAreaArgs *args, UiBool value) { + args->vfill = value; +} + + +void ui_textarea_args_set_override_defaults(UiTextAreaArgs *args, UiBool value) { + args->override_defaults = value; +} + + +void ui_textarea_args_set_colspan(UiTextAreaArgs *args, int colspan) { + args->colspan = colspan; +} + + +void ui_textarea_args_set_rowspan(UiTextAreaArgs *args, int rowspan) { + args->rowspan = rowspan; +} + + +void ui_textarea_args_set_name(UiTextAreaArgs *args, const char *name) { + args->name = strdup(name); +} + + +void ui_textarea_args_set_style_class(UiTextAreaArgs *args, const char *classname) { + args->style_class = strdup(classname); +} + +void ui_textarea_args_set_onchange(UiTextAreaArgs *args, ui_callback callback){ + args->onchange = callback; +} + + +void ui_textarea_args_set_onchangedata(UiTextAreaArgs *args, void *onchangedata){ + args->onchangedata = onchangedata; +} + +void ui_textarea_args_set_varname(UiTextAreaArgs *args, const char *varname) { + args->varname = strdup(varname); +} + +void ui_textarea_args_set_value(UiTextAreaArgs *args, UiText *value) { + args->value = value; +} + +void ui_textarea_args_set_groups(UiTextAreaArgs *args, int *groups){ + // TODO +} + +void ui_textarea_args_free(UiTextAreaArgs *args) { + free((void*)args->name); + free((void*)args->style_class); + free((void*)args->varname); + free((void*)args->groups); + free(args); +} + + + +/* ------------------------- UiTextFieldArgs ----------------------------*/ + +UiTextFieldArgs* ui_textfield_args_new(void) { + UiTextFieldArgs *args = malloc(sizeof(UiTextFieldArgs)); + memset(args, 0, sizeof(UiTextFieldArgs)); + return args; +} + + +void ui_textfield_args_set_fill(UiTextFieldArgs *args, UiBool fill) { + args->fill = fill ? UI_ON : UI_OFF; +} + + +void ui_textfield_args_set_hexpand(UiTextFieldArgs *args, UiBool value) { + args->hexpand = value; +} + + +void ui_textfield_args_set_vexpand(UiTextFieldArgs *args, UiBool value) { + args->vexpand = value; +} + + +void ui_textfield_args_set_hfill(UiTextFieldArgs *args, UiBool value) { + args->hfill = value; +} + + +void ui_textfield_args_set_vfill(UiTextFieldArgs *args, UiBool value) { + args->vfill = value; +} + + +void ui_textfield_args_set_override_defaults(UiTextFieldArgs *args, UiBool value) { + args->override_defaults = value; +} + + +void ui_textfield_args_set_colspan(UiTextFieldArgs *args, int colspan) { + args->colspan = colspan; +} + + +void ui_textfield_args_set_rowspan(UiTextFieldArgs *args, int rowspan) { + args->rowspan = rowspan; +} + + +void ui_textfield_args_set_name(UiTextFieldArgs *args, const char *name) { + args->name = strdup(name); +} + + +void ui_textfield_args_set_style_class(UiTextFieldArgs *args, const char *classname) { + args->style_class = strdup(classname); +} + +void ui_textfield_args_set_onchange(UiTextFieldArgs *args, ui_callback callback){ + args->onchange = callback; +} + + +void ui_textfield_args_set_onchangedata(UiTextFieldArgs *args, void *onchangedata){ + args->onchangedata = onchangedata; +} + +void ui_textfield_args_set_onactivate(UiTextFieldArgs *args, ui_callback callback){ + args->onactivate = callback; +} + + +void ui_textfield_args_set_onactivatedata(UiTextFieldArgs *args, void *onactivatedata){ + args->onactivatedata = onactivatedata; +} + +void ui_textfield_args_set_varname(UiTextFieldArgs *args, const char *varname) { + args->varname = strdup(varname); +} + +void ui_textfield_args_set_value(UiTextFieldArgs *args, UiString *value) { + args->value = value; +} + +void ui_textfield_args_set_groups(UiTextFieldArgs *args, int *groups){ + // TODO +} + +void ui_textfield_args_free(UiTextFieldArgs *args) { + free((void*)args->name); + free((void*)args->style_class); + free((void*)args->varname); + free((void*)args->groups); + free(args); +} + + +/* ------------------------- UiWebviewArgs ----------------------------*/ + +UiWebviewArgs* ui_webview_args_new(void) { + UiWebviewArgs *args = malloc(sizeof(UiWebviewArgs)); + memset(args, 0, sizeof(UiWebviewArgs)); + return args; +} + + +void ui_webview_args_set_fill(UiWebviewArgs *args, UiBool fill) { + args->fill = fill ? UI_ON : UI_OFF; +} + + +void ui_webview_args_set_hexpand(UiWebviewArgs *args, UiBool value) { + args->hexpand = value; +} + + +void ui_webview_args_set_vexpand(UiWebviewArgs *args, UiBool value) { + args->vexpand = value; +} + + +void ui_webview_args_set_hfill(UiWebviewArgs *args, UiBool value) { + args->hfill = value; +} + + +void ui_webview_args_set_vfill(UiWebviewArgs *args, UiBool value) { + args->vfill = value; +} + + +void ui_webview_args_set_override_defaults(UiWebviewArgs *args, UiBool value) { + args->override_defaults = value; +} + + +void ui_webview_args_set_colspan(UiWebviewArgs *args, int colspan) { + args->colspan = colspan; +} + + +void ui_webview_args_set_rowspan(UiWebviewArgs *args, int rowspan) { + args->rowspan = rowspan; +} + + +void ui_webview_args_set_name(UiWebviewArgs *args, const char *name) { + args->name = strdup(name); +} + + +void ui_webview_args_set_style_class(UiWebviewArgs *args, const char *classname) { + args->style_class = strdup(classname); +} + +void ui_webview_args_set_varname(UiWebviewArgs *args, const char *varname) { + args->varname = strdup(varname); +} + +void ui_webview_args_set_value(UiWebviewArgs *args, UiGeneric *value) { + args->value = value; +} + +void ui_webview_args_set_groups(UiWebviewArgs *args, int *groups){ + // TODO +} + +void ui_webview_args_free(UiWebviewArgs *args) { + free((void*)args->name); + free((void*)args->style_class); + free((void*)args->varname); + free((void*)args->groups); + free(args); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/common/args.h Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,405 @@ +/* + * 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 UIC_ARGS_H +#define UIC_ARGS_H + +#include "../ui/window.h" +#include "../ui/container.h" +#include "../ui/display.h" +#include "../ui/button.h" +#include "../ui/menu.h" +#include "../ui/toolbar.h" +#include "../ui/tree.h" +#include "../ui/text.h" +#include "../ui/webview.h" + +#ifdef __cplusplus +extern "C" { +#endif + +UIEXPORT UiDialogArgs* ui_dialog_args_new(void); +UIEXPORT void ui_dialog_args_set_title(UiDialogArgs *args, const char *title); +UIEXPORT void ui_dialog_args_set_content(UiDialogArgs *args, const char *str); +UIEXPORT void ui_dialog_args_set_button1_label(UiDialogArgs *args, const char *label); +UIEXPORT void ui_dialog_args_set_button2_label(UiDialogArgs *args, const char *label); +UIEXPORT void ui_dialog_args_set_closebutton_label(UiDialogArgs *args, const char *label); +UIEXPORT void ui_dialog_args_set_input_value(UiDialogArgs *args, const char *value); +UIEXPORT void ui_dialog_args_set_input(UiDialogArgs *args, UiBool input); +UIEXPORT void ui_dialog_args_set_password(UiDialogArgs *args, UiBool password); +UIEXPORT void ui_dialog_args_set_result(UiDialogArgs *args, ui_callback cb); +UIEXPORT void ui_dialog_args_set_resultdata(UiDialogArgs *args, void *userdata); +UIEXPORT void ui_dialog_args_free(UiDialogArgs *args); + +UIEXPORT UiDialogWindowArgs* ui_dialogwindow_args_new(void); +UIEXPORT void ui_dialogwindow_args_set_modal(UiDialogWindowArgs *args, UiTri value); +UIEXPORT void ui_dialogwindow_args_set_titlebar_buttons(UiDialogWindowArgs *args, UiTri value); +UIEXPORT void ui_dialogwindow_args_set_show_closebutton(UiDialogWindowArgs *args, UiTri value); +UIEXPORT void ui_dialogwindow_args_set_title(UiDialogWindowArgs *args, const char *title); +UIEXPORT void ui_dialogwindow_args_set_lbutton1(UiDialogWindowArgs *args, const char *label); +UIEXPORT void ui_dialogwindow_args_set_lbutton2(UiDialogWindowArgs *args, const char *label); +UIEXPORT void ui_dialogwindow_args_set_rbutton3(UiDialogWindowArgs *args, const char *label); +UIEXPORT void ui_dialogwindow_args_set_rbutton4(UiDialogWindowArgs *args, const char *label); +UIEXPORT void ui_dialogwindow_args_set_lbutton1_states(UiDialogWindowArgs *args, const int *states); +UIEXPORT void ui_dialogwindow_args_set_lbutton2_states(UiDialogWindowArgs *args, const int *states); +UIEXPORT void ui_dialogwindow_args_set_rbutton3_states(UiDialogWindowArgs *args, const int *states); +UIEXPORT void ui_dialogwindow_args_set_rbutton4_states(UiDialogWindowArgs *args, const int *states); +UIEXPORT void ui_dialogwindow_args_set_default_button(UiDialogWindowArgs *args, int button); +UIEXPORT void ui_dialogwindow_args_set_width(UiDialogWindowArgs *args, int width); +UIEXPORT void ui_dialogwindow_args_set_height(UiDialogWindowArgs *args, int height); +UIEXPORT void ui_dialogwindow_args_set_onclick(UiDialogWindowArgs *args, ui_callback cb); +UIEXPORT void ui_dialogwindow_args_set_onclickdata(UiDialogWindowArgs *args, void *userdata); +UIEXPORT void ui_dialogwindow_args_free(UiDialogWindowArgs *args); + +UIEXPORT UiMenuItemArgs* ui_menuitem_args_new(void); +UIEXPORT void ui_menuitem_args_set_label(UiMenuItemArgs *args, const char *label); +UIEXPORT void ui_menuitem_args_set_stockid(UiMenuItemArgs *args, const char *stockid); +UIEXPORT void ui_menuitem_args_set_icon(UiMenuItemArgs *args, const char *icon); +UIEXPORT void ui_menuitem_args_set_onclick(UiMenuItemArgs *args, ui_callback callback); +UIEXPORT void ui_menuitem_args_set_onclickdata(UiMenuItemArgs *args, void *onclickdata); +UIEXPORT void ui_menuitem_args_free(UiMenuItemArgs *args); + +UIEXPORT UiMenuToggleItemArgs* ui_menutoggleitem_args_new(void); +UIEXPORT void ui_menutoggleitem_args_set_label(UiMenuToggleItemArgs *args, const char *label); +UIEXPORT void ui_menutoggleitem_args_set_stockid(UiMenuToggleItemArgs *args, const char *stockid); +UIEXPORT void ui_menutoggleitem_args_set_icon(UiMenuToggleItemArgs *args, const char *icon); +UIEXPORT void ui_menutoggleitem_args_set_varname(UiMenuToggleItemArgs *args, const char *varname); +UIEXPORT void ui_menutoggleitem_args_set_onchange(UiMenuToggleItemArgs *args, ui_callback callback); +UIEXPORT void ui_menutoggleitem_args_set_onchangedata(UiMenuToggleItemArgs *args, void *onchangedata); +UIEXPORT void ui_menutoggleitem_args_free(UiMenuToggleItemArgs *args); + +UIEXPORT UiMenuItemListArgs* ui_menuitemlist_args_new(void); +UIEXPORT void ui_menuitemlist_args_set_varname(UiMenuItemListArgs *args, const char *varname); +UIEXPORT void ui_menuitemlist_args_set_getvalue(UiMenuItemListArgs *args, ui_getvaluefunc func); +UIEXPORT void ui_menuitemlist_args_set_onselect(UiMenuItemListArgs *args, ui_callback callback); +UIEXPORT void ui_menuitemlist_args_set_onselectdata(UiMenuItemListArgs *args, void *data); +UIEXPORT void ui_menuitemlist_args_set_addseparator(UiMenuItemListArgs *args, UiBool value); +UIEXPORT void ui_menuitemlist_args_free(UiMenuItemListArgs *args); + +UIEXPORT UiToolbarItemArgs* ui_toolbar_item_args_new(void); +UIEXPORT void ui_toolbar_item_args_set_label(UiToolbarItemArgs *args, const char *label); +UIEXPORT void ui_toolbar_item_args_set_stockid(UiToolbarItemArgs *args, const char *stockid); +UIEXPORT void ui_toolbar_item_args_set_icon(UiToolbarItemArgs *args, const char *icon); +UIEXPORT void ui_toolbar_item_args_set_onclick(UiToolbarItemArgs *args, ui_callback callback); +UIEXPORT void ui_toolbar_item_args_set_onclickdata(UiToolbarItemArgs *args, void *onclickdata); +UIEXPORT void ui_toolbar_item_args_set_groups(UiToolbarItemArgs *args, int *groups); +UIEXPORT void ui_toolbar_item_args_free(UiToolbarItemArgs *args); + +UIEXPORT UiToolbarToggleItemArgs* ui_toolbar_toggleitem_args_new(void); +UIEXPORT void ui_toolbar_toggleitem_args_set_label(UiToolbarToggleItemArgs *args, const char *label); +UIEXPORT void ui_toolbar_toggleitem_args_set_stockid(UiToolbarToggleItemArgs *args, const char *stockid); +UIEXPORT void ui_toolbar_toggleitem_args_set_icon(UiToolbarToggleItemArgs *args, const char *icon); +UIEXPORT void ui_toolbar_toggleitem_args_set_varname(UiToolbarToggleItemArgs *args, const char *varname); +UIEXPORT void ui_toolbar_toggleitem_args_set_onchange(UiToolbarToggleItemArgs *args, ui_callback callback); +UIEXPORT void ui_toolbar_toggleitem_args_set_onchangedata(UiToolbarToggleItemArgs *args, void *onchangedata); +UIEXPORT void ui_toolbar_toggleitem_args_set_groups(UiToolbarToggleItemArgs *args, int *groups); +UIEXPORT void ui_toolbar_toggleitem_args_free(UiToolbarToggleItemArgs *args); + +UIEXPORT UiToolbarMenuArgs* ui_toolbar_menu_args_new(void); +UIEXPORT void ui_toolbar_menu_args_set_label(UiToolbarMenuArgs *args, const char *label); +UIEXPORT void ui_toolbar_menu_args_set_stockid(UiToolbarMenuArgs *args, const char *stockid); +UIEXPORT void ui_toolbar_menu_args_set_icon(UiToolbarMenuArgs *args, const char *icon); +UIEXPORT void ui_toolbar_menu_args_free(UiToolbarMenuArgs *args); + +UIEXPORT UiContainerArgs* ui_container_args_new(void); +UIEXPORT void ui_container_args_set_fill(UiContainerArgs *args, UiBool fill); +UIEXPORT void ui_container_args_set_hexpand(UiContainerArgs *args, UiBool value); +UIEXPORT void ui_container_args_set_vexpand(UiContainerArgs *args, UiBool value); +UIEXPORT void ui_container_args_set_hfill(UiContainerArgs *args, UiBool value); +UIEXPORT void ui_container_args_set_vfill(UiContainerArgs *args, UiBool value); +UIEXPORT void ui_container_args_set_override_defaults(UiContainerArgs *args, UiBool value); +UIEXPORT void ui_container_args_set_colspan(UiContainerArgs *args, int colspan); +UIEXPORT void ui_container_args_set_rowspan(UiContainerArgs *args, int rowspan); +UIEXPORT void ui_container_args_set_def_hexpand(UiContainerArgs *args, UiBool value); +UIEXPORT void ui_container_args_set_def_vexpand(UiContainerArgs *args, UiBool value); +UIEXPORT void ui_container_args_set_def_hfill(UiContainerArgs *args, UiBool value); +UIEXPORT void ui_container_args_set_def_vfill(UiContainerArgs *args, UiBool value); +UIEXPORT void ui_container_args_set_name(UiContainerArgs *args, const char *name); +UIEXPORT void ui_container_args_set_style_class(UiContainerArgs *args, const char *classname); +UIEXPORT void ui_container_args_set_margin(UiContainerArgs *args, int value); +UIEXPORT void ui_container_args_set_spacing(UiContainerArgs *args, int value); +UIEXPORT void ui_container_args_set_columnspacing(UiContainerArgs *args, int value); +UIEXPORT void ui_container_args_set_rowspacing(UiContainerArgs *args, int value); +UIEXPORT void ui_container_args_free(UiContainerArgs *args); + + +UIEXPORT UiFrameArgs* ui_frame_args_new(void); +UIEXPORT void ui_frame_args_set_fill(UiFrameArgs *args, UiBool fill); +UIEXPORT void ui_frame_args_set_hexpand(UiFrameArgs *args, UiBool value); +UIEXPORT void ui_frame_args_set_vexpand(UiFrameArgs *args, UiBool value); +UIEXPORT void ui_frame_args_set_hfill(UiFrameArgs *args, UiBool value); +UIEXPORT void ui_frame_args_set_vfill(UiFrameArgs *args, UiBool value); +UIEXPORT void ui_frame_args_set_override_defaults(UiFrameArgs *args, UiBool value); +UIEXPORT void ui_frame_args_set_colspan(UiFrameArgs *args, int colspan); +UIEXPORT void ui_frame_args_set_rowspan(UiFrameArgs *args, int rowspan); +UIEXPORT void ui_frame_args_set_name(UiFrameArgs *args, const char *name); +UIEXPORT void ui_frame_args_set_style_class(UiFrameArgs *args, const char *classname); +UIEXPORT void ui_frame_args_set_margin(UiFrameArgs *args, int value); +UIEXPORT void ui_frame_args_set_spacing(UiFrameArgs *args, int value); +UIEXPORT void ui_frame_args_set_columnspacing(UiFrameArgs *args, int value); +UIEXPORT void ui_frame_args_set_rowspacing(UiFrameArgs *args, int value); +UIEXPORT void ui_frame_args_set_expanded(UiFrameArgs *args, UiBool value); +UIEXPORT void ui_frame_args_set_label(UiFrameArgs *args, const char *label); +UIEXPORT void ui_frame_args_free(UiFrameArgs *args); + +UIEXPORT UiSidebarArgs* ui_sidebar_args_new(void); +UIEXPORT void ui_sidebar_args_set_name(UiSidebarArgs *args, const char *name); +UIEXPORT void ui_sidebar_args_set_style_class(UiSidebarArgs *args, const char *classname); +UIEXPORT void ui_sidebar_args_set_margin(UiSidebarArgs *args, int value); +UIEXPORT void ui_sidebar_args_set_spacing(UiSidebarArgs *args, int value); +UIEXPORT void ui_sidebar_args_free(UiSidebarArgs *args); + +UIEXPORT UiSplitPaneArgs* ui_splitpane_args_new(void); +UIEXPORT void ui_splitpane_args_set_fill(UiSplitPaneArgs *args, UiBool fill); +UIEXPORT void ui_splitpane_args_set_hexpand(UiSplitPaneArgs *args, UiBool value); +UIEXPORT void ui_splitpane_args_set_vexpand(UiSplitPaneArgs *args, UiBool value); +UIEXPORT void ui_splitpane_args_set_hfill(UiSplitPaneArgs *args, UiBool value); +UIEXPORT void ui_splitpane_args_set_vfill(UiSplitPaneArgs *args, UiBool value); +UIEXPORT void ui_splitpane_args_set_override_defaults(UiSplitPaneArgs *args, UiBool value); +UIEXPORT void ui_splitpane_args_set_colspan(UiSplitPaneArgs *args, int colspan); +UIEXPORT void ui_splitpane_args_set_rowspan(UiSplitPaneArgs *args, int rowspan); +UIEXPORT void ui_splitpane_args_set_name(UiSplitPaneArgs *args, const char *name); +UIEXPORT void ui_splitpane_args_set_style_class(UiSplitPaneArgs *args, const char *classname); +UIEXPORT void ui_splitpane_args_set_margin(UiSplitPaneArgs *args, int value); +UIEXPORT void ui_splitpane_args_set_spacing(UiSplitPaneArgs *args, int value); +UIEXPORT void ui_splitpane_args_set_columnspacing(UiSplitPaneArgs *args, int value); +UIEXPORT void ui_splitpane_args_set_rowspacing(UiSplitPaneArgs *args, int value); +UIEXPORT void ui_splitpane_args_set_initial_position(UiSplitPaneArgs *args, int pos); +UIEXPORT void ui_splitpane_args_set_varname(UiSplitPaneArgs *args, const char *varname); +UIEXPORT void ui_splitpane_args_set_value(UiSplitPaneArgs *args, UiInteger *value); +UIEXPORT void ui_splitpane_args_set_max_panes(UiSplitPaneArgs *args, int max); +UIEXPORT void ui_splitpane_args_free(UiSplitPaneArgs *args); + +UIEXPORT UiLabelArgs* ui_label_args_new(void); +UIEXPORT void ui_label_args_set_fill(UiLabelArgs *args, UiBool fill); +UIEXPORT void ui_label_args_set_hexpand(UiLabelArgs *args, UiBool value); +UIEXPORT void ui_label_args_set_vexpand(UiLabelArgs *args, UiBool value); +UIEXPORT void ui_label_args_set_hfill(UiLabelArgs *args, UiBool value); +UIEXPORT void ui_label_args_set_vfill(UiLabelArgs *args, UiBool value); +UIEXPORT void ui_label_args_set_override_defaults(UiLabelArgs *args, UiBool value); +UIEXPORT void ui_label_args_set_colspan(UiLabelArgs *args, int colspan); +UIEXPORT void ui_label_args_set_rowspan(UiLabelArgs *args, int rowspan); +UIEXPORT void ui_label_args_set_name(UiLabelArgs *args, const char *name); +UIEXPORT void ui_label_args_set_style_class(UiLabelArgs *args, const char *classname); +UIEXPORT void ui_label_args_set_label(UiLabelArgs *args, const char *label); +UIEXPORT void ui_label_args_set_align(UiLabelArgs *args, UiAlignment align); +UIEXPORT void ui_label_args_set_style(UiLabelArgs *args, UiLabelStyle style); +UIEXPORT void ui_label_args_set_value(UiLabelArgs *args, UiString *value); +UIEXPORT void ui_label_args_set_varname(UiLabelArgs *args, const char *varname); +UIEXPORT void ui_label_args_free(UiLabelArgs *args); + +UIEXPORT UiProgressbarArgs* ui_progressbar_args_new(void); +UIEXPORT void ui_progressbar_args_set_fill(UiProgressbarArgs *args, UiBool fill); +UIEXPORT void ui_progressbar_args_set_hexpand(UiProgressbarArgs *args, UiBool value); +UIEXPORT void ui_progressbar_args_set_vexpand(UiProgressbarArgs *args, UiBool value); +UIEXPORT void ui_progressbar_args_set_hfill(UiProgressbarArgs *args, UiBool value); +UIEXPORT void ui_progressbar_args_set_vfill(UiProgressbarArgs *args, UiBool value); +UIEXPORT void ui_progressbar_args_set_override_defaults(UiProgressbarArgs *args, UiBool value); +UIEXPORT void ui_progressbar_args_set_colspan(UiProgressbarArgs *args, int colspan); +UIEXPORT void ui_progressbar_args_set_rowspan(UiProgressbarArgs *args, int rowspan); +UIEXPORT void ui_progressbar_args_set_name(UiProgressbarArgs *args, const char *name); +UIEXPORT void ui_progressbar_args_set_style_class(UiProgressbarArgs *args, const char *classname); +UIEXPORT void ui_progressbar_args_set_min(UiProgressbarArgs *args, double min); +UIEXPORT void ui_progressbar_args_set_max(UiProgressbarArgs *args, double max); +UIEXPORT void ui_progressbar_args_set_value(UiProgressbarArgs *args, UiDouble *value); +UIEXPORT void ui_progressbar_args_set_varname(UiProgressbarArgs *args, const char *varname); +UIEXPORT void ui_progressbar_args_free(UiProgressbarArgs *args); + +UIEXPORT UiProgressbarSpinnerArgs* ui_progress_spinner_args_new(void); +UIEXPORT void ui_progress_spinner_args_set_fill(UiProgressbarSpinnerArgs *args, UiBool fill); +UIEXPORT void ui_progress_spinner_args_set_hexpand(UiProgressbarSpinnerArgs *args, UiBool value); +UIEXPORT void ui_progress_spinner_args_set_vexpand(UiProgressbarSpinnerArgs *args, UiBool value); +UIEXPORT void ui_progress_spinner_args_set_hfill(UiProgressbarSpinnerArgs *args, UiBool value); +UIEXPORT void ui_progress_spinner_args_set_vfill(UiProgressbarSpinnerArgs *args, UiBool value); +UIEXPORT void ui_progress_spinner_args_set_override_defaults(UiProgressbarSpinnerArgs *args, UiBool value); +UIEXPORT void ui_progress_spinner_args_set_colspan(UiProgressbarSpinnerArgs *args, int colspan); +UIEXPORT void ui_progress_spinner_args_set_rowspan(UiProgressbarSpinnerArgs *args, int rowspan); +UIEXPORT void ui_progress_spinner_args_set_name(UiProgressbarSpinnerArgs *args, const char *name); +UIEXPORT void ui_progress_spinner_args_set_style_class(UiProgressbarSpinnerArgs *args, const char *classname); +UIEXPORT void ui_progress_spinner_args_set_value(UiProgressbarSpinnerArgs *args, UiInteger *value); +UIEXPORT void ui_progress_spinner_args_set_varname(UiProgressbarSpinnerArgs *args, const char *varname); +UIEXPORT void ui_progress_spinner_args_free(UiProgressbarSpinnerArgs *args); + +UIEXPORT UiButtonArgs* ui_button_args_new(void); +UIEXPORT void ui_button_args_set_fill(UiButtonArgs *args, UiBool fill); +UIEXPORT void ui_button_args_set_hexpand(UiButtonArgs *args, UiBool value); +UIEXPORT void ui_button_args_set_vexpand(UiButtonArgs *args, UiBool value); +UIEXPORT void ui_button_args_set_hfill(UiButtonArgs *args, UiBool value); +UIEXPORT void ui_button_args_set_vfill(UiButtonArgs *args, UiBool value); +UIEXPORT void ui_button_args_set_override_defaults(UiButtonArgs *args, UiBool value); +UIEXPORT void ui_button_args_set_colspan(UiButtonArgs *args, int colspan); +UIEXPORT void ui_button_args_set_rowspan(UiButtonArgs *args, int rowspan); +UIEXPORT void ui_button_args_set_name(UiButtonArgs *args, const char *name); +UIEXPORT void ui_button_args_set_style_class(UiButtonArgs *args, const char *classname); +UIEXPORT void ui_button_args_set_label(UiButtonArgs *args, const char *label); +UIEXPORT void ui_button_args_set_stockid(UiButtonArgs *args, const char *stockid); +UIEXPORT void ui_button_args_set_icon(UiButtonArgs *args, const char *icon); +UIEXPORT void ui_button_args_set_labeltype(UiButtonArgs *args, int labeltype); +UIEXPORT void ui_button_args_set_onclick(UiButtonArgs *args, ui_callback callback); +UIEXPORT void ui_button_args_set_onclickdata(UiButtonArgs *args, void *onclickdata); +UIEXPORT void ui_button_args_set_groups(UiButtonArgs *args, int *groups); +UIEXPORT void ui_button_args_free(UiButtonArgs *args); + +UIEXPORT UiToggleArgs* ui_toggle_args_new(void); +UIEXPORT void ui_toggle_args_set_fill(UiToggleArgs *args, UiBool fill); +UIEXPORT void ui_toggle_args_set_hexpand(UiToggleArgs *args, UiBool value); +UIEXPORT void ui_toggle_args_set_vexpand(UiToggleArgs *args, UiBool value); +UIEXPORT void ui_toggle_args_set_hfill(UiToggleArgs *args, UiBool value); +UIEXPORT void ui_toggle_args_set_vfill(UiToggleArgs *args, UiBool value); +UIEXPORT void ui_toggle_args_set_override_defaults(UiToggleArgs *args, UiBool value); +UIEXPORT void ui_toggle_args_set_colspan(UiToggleArgs *args, int colspan); +UIEXPORT void ui_toggle_args_set_rowspan(UiToggleArgs *args, int rowspan); +UIEXPORT void ui_toggle_args_set_name(UiToggleArgs *args, const char *name); +UIEXPORT void ui_toggle_args_set_style_class(UiToggleArgs *args, const char *classname); +UIEXPORT void ui_toggle_args_set_label(UiToggleArgs *args, const char *label); +UIEXPORT void ui_toggle_args_set_stockid(UiToggleArgs *args, const char *stockid); +UIEXPORT void ui_toggle_args_set_icon(UiToggleArgs *args, const char *icon); +UIEXPORT void ui_toggle_args_set_labeltype(UiToggleArgs *args, int labeltype); +UIEXPORT void ui_toggle_args_set_onchange(UiToggleArgs *args, ui_callback callback); +UIEXPORT void ui_toggle_args_set_onchangedata(UiToggleArgs *args, void *onchangedata); +UIEXPORT void ui_toggle_args_set_varname(UiToggleArgs *args, const char *varname); +UIEXPORT void ui_toggle_args_set_value(UiToggleArgs *args, UiInteger *value); +UIEXPORT void ui_toggle_args_set_enablegroup(UiToggleArgs *args, int group); +UIEXPORT void ui_toggle_args_set_groups(UiToggleArgs *args, int *groups); +UIEXPORT void ui_toggle_args_free(UiToggleArgs *args); + +UIEXPORT UiListArgs* ui_list_args_new(void); +UIEXPORT void ui_list_args_set_fill(UiListArgs *args, UiBool fill); +UIEXPORT void ui_list_args_set_hexpand(UiListArgs *args, UiBool value); +UIEXPORT void ui_list_args_set_vexpand(UiListArgs *args, UiBool value); +UIEXPORT void ui_list_args_set_hfill(UiListArgs *args, UiBool value); +UIEXPORT void ui_list_args_set_vfill(UiListArgs *args, UiBool value); +UIEXPORT void ui_list_args_set_override_defaults(UiListArgs *args, UiBool value); +UIEXPORT void ui_list_args_set_colspan(UiListArgs *args, int colspan); +UIEXPORT void ui_list_args_set_rowspan(UiListArgs *args, int rowspan); +UIEXPORT void ui_list_args_set_name(UiListArgs *args, const char *name); +UIEXPORT void ui_list_args_set_style_class(UiListArgs *args, const char *classname); +UIEXPORT void ui_list_args_set_varname(UiListArgs *args, const char *varname); +UIEXPORT void ui_list_args_set_value(UiListArgs *args, UiList *value); +UIEXPORT void ui_list_args_set_model(UiListArgs *args, UiModel *model); +UIEXPORT void ui_list_args_set_static_elements(UiListArgs *args, char **strarray, size_t nelm); +UIEXPORT void ui_list_args_set_getvalue_func(UiListArgs *args, ui_getvaluefunc getvalue); +UIEXPORT void ui_list_args_set_getvalue_func2(UiListArgs *args, ui_getvaluefunc2 getvalue); +UIEXPORT void ui_list_args_set_getvalue_data(UiListArgs *args, void *userdata); +UIEXPORT void ui_list_args_set_onactivate(UiListArgs *args, ui_callback callback); +UIEXPORT void ui_list_args_set_onactivatedata(UiListArgs *args, void *userdata); +UIEXPORT void ui_list_args_set_onselection(UiListArgs *args, ui_callback callback); +UIEXPORT void ui_list_args_set_onselectiondata(UiListArgs *args, void *userdata); +UIEXPORT void ui_list_args_set_ondragstart(UiListArgs *args, ui_callback callback); +UIEXPORT void ui_list_args_set_ondragstartdata(UiListArgs *args, void *userdata); +UIEXPORT void ui_list_args_set_ondragcomplete(UiListArgs *args, ui_callback callback); +UIEXPORT void ui_list_args_set_ondragcompletedata(UiListArgs *args, void *userdata); +UIEXPORT void ui_list_args_set_ondrop(UiListArgs *args, ui_callback callback); +UIEXPORT void ui_list_args_set_ondropdata(UiListArgs *args, void *userdata); +UIEXPORT void ui_list_args_set_multiselection(UiListArgs *args, UiBool multiselection); +UIEXPORT void ui_list_args_set_contextmenu(UiListArgs *args, UiMenuBuilder *menubuilder); +UIEXPORT void ui_list_args_set_groups(UiListArgs *args, int *groups); +UIEXPORT void ui_list_args_free(UiListArgs *args); + +UIEXPORT UiSourceListArgs* ui_sourcelist_args_new(void); +UIEXPORT void ui_sourcelist_args_set_fill(UiSourceListArgs *args, UiBool fill); +UIEXPORT void ui_sourcelist_args_set_hexpand(UiSourceListArgs *args, UiBool value); +UIEXPORT void ui_sourcelist_args_set_vexpand(UiSourceListArgs *args, UiBool value); +UIEXPORT void ui_sourcelist_args_set_hfill(UiSourceListArgs *args, UiBool value); +UIEXPORT void ui_sourcelist_args_set_vfill(UiSourceListArgs *args, UiBool value); +UIEXPORT void ui_sourcelist_args_set_override_defaults(UiSourceListArgs *args, UiBool value); +UIEXPORT void ui_sourcelist_args_set_colspan(UiSourceListArgs *args, int colspan); +UIEXPORT void ui_sourcelist_args_set_rowspan(UiSourceListArgs *args, int rowspan); +UIEXPORT void ui_sourcelist_args_set_name(UiSourceListArgs *args, const char *name); +UIEXPORT void ui_sourcelist_args_set_style_class(UiSourceListArgs *args, const char *classname); +UIEXPORT void ui_sourcelist_args_set_static_sublists(UiSourceListArgs *args, UiSubList *sublists, size_t numsublists); +UIEXPORT void ui_sourcelist_args_set_varname(UiSourceListArgs *args, const char *varname); +UIEXPORT void ui_sourcelist_args_set_dynamic_sublists(UiSourceListArgs *args, UiList *value); +UIEXPORT void ui_sourcelist_args_set_getvalue_func(UiSourceListArgs *args, ui_sublist_getvalue_func getvalue); +UIEXPORT void ui_sourcelist_args_set_getvalue_userdata(UiSourceListArgs *args, void *userdata); +UIEXPORT void ui_sourcelist_args_set_onactivate(UiSourceListArgs *args, ui_callback callback); +UIEXPORT void ui_sourcelist_args_set_onactivatedata(UiSourceListArgs *args, void *userdata); +UIEXPORT void ui_sourcelist_args_set_onbuttonclick(UiSourceListArgs *args, ui_callback callback); +UIEXPORT void ui_sourcelist_args_set_onbuttonclickdata(UiSourceListArgs *args, void *userdata); +UIEXPORT void ui_sourcelist_args_free(UiSourceListArgs *args); + +UIEXPORT UiTextAreaArgs* ui_textarea_args_new(void); +UIEXPORT void ui_textarea_args_set_fill(UiTextAreaArgs *args, UiBool fill); +UIEXPORT void ui_textarea_args_set_hexpand(UiTextAreaArgs *args, UiBool value); +UIEXPORT void ui_textarea_args_set_vexpand(UiTextAreaArgs *args, UiBool value); +UIEXPORT void ui_textarea_args_set_hfill(UiTextAreaArgs *args, UiBool value); +UIEXPORT void ui_textarea_args_set_vfill(UiTextAreaArgs *args, UiBool value); +UIEXPORT void ui_textarea_args_set_override_defaults(UiTextAreaArgs *args, UiBool value); +UIEXPORT void ui_textarea_args_set_colspan(UiTextAreaArgs *args, int colspan); +UIEXPORT void ui_textarea_args_set_rowspan(UiTextAreaArgs *args, int rowspan); +UIEXPORT void ui_textarea_args_set_name(UiTextAreaArgs *args, const char *name); +UIEXPORT void ui_textarea_args_set_style_class(UiTextAreaArgs *args, const char *classname); +UIEXPORT void ui_textarea_args_set_onchange(UiTextAreaArgs *args, ui_callback callback); +UIEXPORT void ui_textarea_args_set_onchangedata(UiTextAreaArgs *args, void *onchangedata); +UIEXPORT void ui_textarea_args_set_varname(UiTextAreaArgs *args, const char *varname); +UIEXPORT void ui_textarea_args_set_value(UiTextAreaArgs *args, UiText *value); +UIEXPORT void ui_textarea_args_set_groups(UiTextAreaArgs *args, int *groups); +UIEXPORT void ui_textarea_args_free(UiTextAreaArgs *args); + +UIEXPORT UiTextFieldArgs* ui_textfield_args_new(void); +UIEXPORT void ui_textfield_args_set_fill(UiTextFieldArgs *args, UiBool fill); +UIEXPORT void ui_textfield_args_set_hexpand(UiTextFieldArgs *args, UiBool value); +UIEXPORT void ui_textfield_args_set_vexpand(UiTextFieldArgs *args, UiBool value); +UIEXPORT void ui_textfield_args_set_hfill(UiTextFieldArgs *args, UiBool value); +UIEXPORT void ui_textfield_args_set_vfill(UiTextFieldArgs *args, UiBool value); +UIEXPORT void ui_textfield_args_set_override_defaults(UiTextFieldArgs *args, UiBool value); +UIEXPORT void ui_textfield_args_set_colspan(UiTextFieldArgs *args, int colspan); +UIEXPORT void ui_textfield_args_set_rowspan(UiTextFieldArgs *args, int rowspan); +UIEXPORT void ui_textfield_args_set_name(UiTextFieldArgs *args, const char *name); +UIEXPORT void ui_textfield_args_set_style_class(UiTextFieldArgs *args, const char *classname); +UIEXPORT void ui_textfield_args_set_onchange(UiTextFieldArgs *args, ui_callback callback); +UIEXPORT void ui_textfield_args_set_onchangedata(UiTextFieldArgs *args, void *onchangedata); +UIEXPORT void ui_textfield_args_set_onactivate(UiTextFieldArgs *args, ui_callback callback); +UIEXPORT void ui_textfield_args_set_onactivatedata(UiTextFieldArgs *args, void *onactivatedata); +UIEXPORT void ui_textfield_args_set_varname(UiTextFieldArgs *args, const char *varname); +UIEXPORT void ui_textfield_args_set_value(UiTextFieldArgs *args, UiString *value); +UIEXPORT void ui_textfield_args_set_groups(UiTextFieldArgs *args, int *groups); +UIEXPORT void ui_textfield_args_free(UiTextFieldArgs *args); + +UIEXPORT UiWebviewArgs* ui_webview_args_new(void); +UIEXPORT void ui_webview_args_set_fill(UiWebviewArgs *args, UiBool fill); +UIEXPORT void ui_webview_args_set_hexpand(UiWebviewArgs *args, UiBool value); +UIEXPORT void ui_webview_args_set_vexpand(UiWebviewArgs *args, UiBool value); +UIEXPORT void ui_webview_args_set_hfill(UiWebviewArgs *args, UiBool value); +UIEXPORT void ui_webview_args_set_vfill(UiWebviewArgs *args, UiBool value); +UIEXPORT void ui_webview_args_set_override_defaults(UiWebviewArgs *args, UiBool value); +UIEXPORT void ui_webview_args_set_colspan(UiWebviewArgs *args, int colspan); +UIEXPORT void ui_webview_args_set_rowspan(UiWebviewArgs *args, int rowspan); +UIEXPORT void ui_webview_args_set_name(UiWebviewArgs *args, const char *name); +UIEXPORT void ui_webview_args_set_style_class(UiWebviewArgs *args, const char *classname); +UIEXPORT void ui_webview_args_set_varname(UiWebviewArgs *args, const char *varname); +UIEXPORT void ui_webview_args_set_value(UiWebviewArgs *args, UiGeneric *value); +UIEXPORT void ui_webview_args_set_groups(UiWebviewArgs *args, int *groups); +UIEXPORT void ui_webview_args_free(UiWebviewArgs *args); + +#ifdef __cplusplus +} +#endif + +#endif /* UIC_ARGS_H */ +
--- a/ui/common/context.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/common/context.c Sun Jul 20 22:04:39 2025 +0200 @@ -58,6 +58,7 @@ memset(ctx, 0, sizeof(UiContext)); ctx->mp = mp; ctx->allocator = mp->allocator; + ctx->destroy_handler = cxArrayListCreate(ctx->allocator, NULL, sizeof(UiDestroyHandler), 16); ctx->obj = toplevel; ctx->vars = cxHashMapCreate(mp->allocator, CX_STORE_POINTERS, 16); @@ -66,7 +67,7 @@ ctx->groups = cxArrayListCreate(mp->allocator, cx_cmp_int, sizeof(int), 32); ctx->attach_document = uic_context_attach_document; - ctx->detach_document2 = uic_context_detach_document2; + ctx->detach_document2 = uic_context_detach_document; #if UI_GTK2 || UI_GTK3 if(toplevel && toplevel->widget) { @@ -82,6 +83,13 @@ return ctx->parent ? uic_root_context(ctx->parent) : ctx; } +void uic_context_add_destructor(UiContext *ctx, cx_destructor_func func, void *data) { + UiDestroyHandler handler; + handler.destructor = func; + handler.data = data; + cxListAdd(ctx->destroy_handler, &handler); +} + void uic_context_prepare_close(UiContext *ctx) { cxListClear(ctx->groups); cxListClear(ctx->group_widgets); @@ -120,11 +128,12 @@ CxMapIterator mi = cxMapIterator(ctx->vars); cx_foreach(CxMapEntry*, entry, mi) { UiVar *var = entry->value; - if(var->from && var->from_ctx && var->from_ctx != ctx) { + // var->from && var->from_ctx && var->from_ctx != ctx + if(var->from) { uic_save_var2(var); uic_copy_binding(var, var->from, FALSE); - cxMapPut(var->from_ctx->vars_unbound, *entry->key, var->from); - var->from_ctx = ctx; + cxMapPut(var->from->from_ctx->vars_unbound, *entry->key, var->from); + var->from = NULL; } } @@ -137,7 +146,7 @@ } } -void uic_context_detach_document2(UiContext *ctx, void *document) { +void uic_context_detach_document(UiContext *ctx, void *document) { // find the document in the documents list size_t docIndex = cxListFind(ctx->documents, document); if(!cxListIndexValid(ctx->documents, docIndex)) { @@ -209,6 +218,7 @@ var = ui_malloc(ctx, sizeof(UiVar)); var->type = type; var->value = uic_create_value(ctx, type); + var->original_value = NULL; var->from = NULL; var->from_ctx = ctx; @@ -227,6 +237,7 @@ var->from = NULL; var->from_ctx = ctx; var->value = value; + var->original_value = NULL; var->type = UI_VAR_SPECIAL; return var; } @@ -286,10 +297,19 @@ } void *fromvalue = from->value; + void *tovalue = to->value; // update var if(copytodoc) { - to->from = from; - to->from_ctx = from->from_ctx; + to->from = from; // from which UiVar are the bindings copied + from->original_value = fromvalue; // save original value otherwise it would be lost + // widgets store a reference to the UiVar with their value + // the UiVar object must be updated to contain the current value object + from->value = tovalue; + } else { + if(to->original_value) { + to->value = to->original_value; + tovalue = to->value; + } } ui_setop_enable(TRUE); @@ -301,7 +321,7 @@ case UI_VAR_SPECIAL: break; case UI_VAR_INTEGER: { UiInteger *f = fromvalue; - UiInteger *t = to->value; + UiInteger *t = tovalue; if(!f->obj) break; uic_int_copy(f, t); t->set(t, t->value); @@ -309,7 +329,7 @@ } case UI_VAR_DOUBLE: { UiDouble *f = fromvalue; - UiDouble *t = to->value; + UiDouble *t = tovalue; if(!f->obj) break; uic_double_copy(f, t); t->set(t, t->value); @@ -317,48 +337,32 @@ } case UI_VAR_STRING: { UiString *f = fromvalue; - UiString *t = to->value; + UiString *t = tovalue; if(!f->obj) break; uic_string_copy(f, t); char *tvalue = t->value.ptr ? t->value.ptr : ""; + char *fvalue = f->value.ptr ? f->value.ptr : ""; t->set(t, tvalue); break; } case UI_VAR_TEXT: { UiText *f = fromvalue; - UiText *t = to->value; + UiText *t = tovalue; if(!f->obj) break; uic_text_copy(f, t); t->restore(t); break; } - case UI_VAR_LIST: { - // TODO: not sure how correct this is - - UiList *f = from->value; - UiList *t = to->value; - if (f->obj) { - t->obj = f->obj; - t->update = f->update; - t->getselection = f->getselection; - t->setselection = f->setselection; - } - - UiVar tmp = *from; - *from = *to; - *to = tmp; - - UiList* t2 = to->value; - if(t->update) { - t->update(t, -1); - } - ui_notify(t2->observers, NULL); // TODO: why not t? - + case UI_VAR_LIST: { + UiList *f = fromvalue; + UiList *t = tovalue; + uic_list_copy(f, t); + ui_list_update(t); break; } case UI_VAR_RANGE: { UiRange *f = fromvalue; - UiRange *t = to->value; + UiRange *t = tovalue; if(!f->obj) break; uic_range_copy(f, t); t->setextent(t, t->extent); @@ -368,7 +372,7 @@ } case UI_VAR_GENERIC: { UiGeneric *f = fromvalue; - UiGeneric *t = to->value; + UiGeneric *t = tovalue; if(!f->obj) break; uic_generic_copy(f, t); t->set(t, t->value, t->type); @@ -405,7 +409,7 @@ } } -void uic_reg_var(UiContext *ctx, char *name, UiVarType type, void *value) { +void uic_reg_var(UiContext *ctx, const char *name, UiVarType type, void *value) { // TODO: do we need/want this? Why adding vars to a context after // widgets reference these? Workarounds: // 1. add vars to ctx before creating ui @@ -463,8 +467,8 @@ uic_context_attach_document(ctx, document); } -void ui_detach_document2(UiContext *ctx, void *document) { - uic_context_detach_document2(ctx, document); +void ui_detach_document(UiContext *ctx, void *document) { + uic_context_detach_document(ctx, document); } void ui_context_closefunc(UiContext *ctx, ui_callback fnc, void *udata) { @@ -472,10 +476,18 @@ ctx->close_data = udata; } -UIEXPORT void ui_context_destroy(UiContext *ctx) { +void ui_context_destroy(UiContext *ctx) { + CxIterator i = cxListIterator(ctx->destroy_handler); + cx_foreach(UiDestroyHandler *, h, i) { + h->destructor(h->data); + } cxMempoolFree(ctx->mp); } +UiContext* ui_context_parent(UiContext *ctx) { + return ctx->parent; +} + void ui_set_group(UiContext *ctx, int group) { if(!cxListIndexValid(ctx->groups, cxListFind(ctx->groups, &group))) {
--- a/ui/common/context.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/common/context.h Sun Jul 20 22:04:39 2025 +0200 @@ -40,10 +40,11 @@ extern "C" { #endif -typedef struct UiVar UiVar; -typedef struct UiListPtr UiListPtr; -typedef struct UiListVar UiListVar; -typedef struct UiGroupWidget UiGroupWidget; +typedef struct UiVar UiVar; +typedef struct UiListPtr UiListPtr; +typedef struct UiListVar UiListVar; +typedef struct UiGroupWidget UiGroupWidget; +typedef struct UiDestroyHandler UiDestroyHandler; typedef enum UiVarType { UI_VAR_SPECIAL = 0, @@ -61,6 +62,7 @@ UiObject *obj; CxMempool *mp; const CxAllocator *allocator; + CxList *destroy_handler; void *document; CxList *documents; @@ -93,8 +95,9 @@ // UiVar replacement, rename it to UiVar when finished struct UiVar { void *value; + void *original_value; UiVarType type; - UiVar *from; + UiVar *from; UiContext *from_ctx; }; @@ -105,18 +108,24 @@ int numgroups; }; +struct UiDestroyHandler { + cx_destructor_func destructor; + void *data; +}; + void uic_init_global_context(void); UiContext* uic_context(UiObject *toplevel, CxMempool *mp); UiContext* uic_root_context(UiContext *ctx); -void uic_context_set_document(UiContext *ctx, void *document); // deprecated -void uic_context_detach_document(UiContext *ctx); // deprecated +void uic_context_add_destructor(UiContext *ctx, cx_destructor_func func, void *data); void uic_context_prepare_close(UiContext *ctx); void uic_context_attach_document(UiContext *ctx, void *document); -void uic_context_detach_document2(UiContext *ctx, void *document); +void uic_context_detach_document(UiContext *ctx, void *document); +void uic_context_attach_context(UiContext *ctx, UiContext *doc_ctx); // TODO +void uic_context_detach_context(UiContext *ctx, UiContext *doc_ctx); // TODO void uic_context_detach_all(UiContext *ctx); UiVar* uic_get_var(UiContext *ctx, const char *name); @@ -130,7 +139,7 @@ void uic_save_var2(UiVar *var); void uic_unbind_var(UiVar *var); -void uic_reg_var(UiContext *ctx, char *name, UiVarType type, void *value); +void uic_reg_var(UiContext *ctx, const char *name, UiVarType type, void *value); void uic_remove_bound_var(UiContext *ctx, UiVar *var);
--- a/ui/common/document.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/common/document.c Sun Jul 20 22:04:39 2025 +0200 @@ -44,46 +44,8 @@ } } -void ui_set_document(UiObject *obj, void *document) { - uic_context_detach_all(obj->ctx); - obj->ctx->attach_document(obj->ctx, document); -} - -void ui_detach_document(UiObject *obj) { - uic_context_detach_all(obj->ctx); -} - -void* ui_get_document(UiObject *obj) { - return obj->ctx->document; -} - -void ui_set_subdocument(void *document, void *sub) { - UiContext *ctx = ui_document_context(document); - if(!ctx) { - fprintf(stderr, "UI Error: pointer is not a document\n"); - } - // TODO -} - -void ui_detach_subdocument(void *document, void *sub) { - UiContext *ctx = ui_document_context(document); - if(!ctx) { - fprintf(stderr, "UI Error: pointer is not a document\n"); - } - // TODO -} - -void* ui_get_subdocument(void *document) { - UiContext *ctx = ui_document_context(document); - if(!ctx) { - fprintf(stderr, "UI Error: pointer is not a document\n"); - } - // TODO - return NULL; -} - void* ui_document_new(size_t size) { - CxMempool *mp = cxMempoolCreate(256, NULL); + CxMempool *mp = cxMempoolCreateSimple(256); const CxAllocator *a = mp->allocator; UiContext *ctx = uic_context(NULL, mp); @@ -100,6 +62,7 @@ ev.document = doc; ev.obj = NULL; ev.eventdata = NULL; + ev.eventdatatype = 0; ev.intval = 0; if(ctx->close_callback) {
--- a/ui/common/menu.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/common/menu.c Sun Jul 20 22:04:39 2025 +0200 @@ -125,19 +125,19 @@ -void ui_menuitem_create(UiMenuItemArgs args) { +void ui_menuitem_create(UiMenuItemArgs *args) { UiMenuItem* item = malloc(sizeof(UiMenuItem)); mitem_set_id(&item->item); item->item.prev = NULL; item->item.next = NULL; item->item.type = UI_MENU_ITEM; - item->label = nl_strdup(args.label); - item->stockid = nl_strdup(args.stockid); - item->icon = nl_strdup(args.icon); - item->userdata = args.onclickdata; - item->callback = args.onclick; - item->groups = uic_copy_groups(args.groups, &item->ngroups); + item->label = nl_strdup(args->label); + item->stockid = nl_strdup(args->stockid); + item->icon = nl_strdup(args->icon); + item->userdata = args->onclickdata; + item->callback = args->onclick; + item->groups = uic_copy_groups(args->groups, &item->ngroups); add_item((UiMenuItemI*)item); } @@ -152,79 +152,79 @@ add_item((UiMenuItemI*)item); } -void ui_menu_toggleitem_create(UiMenuToggleItemArgs args) { +void ui_menu_toggleitem_create(UiMenuToggleItemArgs *args) { UiMenuCheckItem *item = malloc(sizeof(UiMenuCheckItem)); mitem_set_id(&item->item); item->item.prev = NULL; item->item.next = NULL; item->item.type = UI_MENU_CHECK_ITEM; - item->label = nl_strdup(args.label); - item->stockid = nl_strdup(args.stockid); - item->icon = nl_strdup(args.icon); - item->varname = nl_strdup(args.varname); - item->userdata = args.onchangedata; - item->callback = args.onchange; - item->groups = uic_copy_groups(args.groups, &item->ngroups); + item->label = nl_strdup(args->label); + item->stockid = nl_strdup(args->stockid); + item->icon = nl_strdup(args->icon); + item->varname = nl_strdup(args->varname); + item->userdata = args->onchangedata; + item->callback = args->onchange; + item->groups = uic_copy_groups(args->groups, &item->ngroups); add_item((UiMenuItemI*)item); } -void ui_menu_radioitem_create(UiMenuToggleItemArgs args) { +void ui_menu_radioitem_create(UiMenuToggleItemArgs *args) { UiMenuCheckItem* item = malloc(sizeof(UiMenuCheckItem)); mitem_set_id(&item->item); item->item.prev = NULL; item->item.next = NULL; item->item.type = UI_MENU_RADIO_ITEM; - item->label = nl_strdup(args.label); - item->stockid = nl_strdup(args.stockid); - item->icon = nl_strdup(args.icon); - item->varname = nl_strdup(args.varname); - item->userdata = args.onchangedata; - item->callback = args.onchange; - item->groups = uic_copy_groups(args.groups, &item->ngroups); + item->label = nl_strdup(args->label); + item->stockid = nl_strdup(args->stockid); + item->icon = nl_strdup(args->icon); + item->varname = nl_strdup(args->varname); + item->userdata = args->onchangedata; + item->callback = args->onchange; + item->groups = uic_copy_groups(args->groups, &item->ngroups); add_item((UiMenuItemI*)item); } -void ui_menu_itemlist_create(UiMenuItemListArgs args) { +void ui_menu_itemlist_create(UiMenuItemListArgs *args) { UiMenuItemList*item = malloc(sizeof(UiMenuItemList)); mitem_set_id(&item->item); item->item.prev = NULL; item->item.next = NULL; item->item.type = UI_MENU_ITEM_LIST; - item->getvalue = args.getvalue; - item->callback = args.onselect; - item->userdata = args.onselectdata; - item->varname = nl_strdup(args.varname); - item->addseparator = args.addseparator; + item->getvalue = args->getvalue; + item->callback = args->onselect; + item->userdata = args->onselectdata; + item->varname = nl_strdup(args->varname); + item->addseparator = args->addseparator; add_item((UiMenuItemI*)item); } -void ui_menu_checkitemlist_create(UiMenuItemListArgs args) { +void ui_menu_checkitemlist_create(UiMenuItemListArgs *args) { UiMenuItemList* item = malloc(sizeof(UiMenuItemList)); mitem_set_id(&item->item); item->item.prev = NULL; item->item.next = NULL; item->item.type = UI_MENU_CHECKITEM_LIST; - item->callback = args.onselect; - item->userdata = args.onselectdata; - item->varname = nl_strdup(args.varname); + item->callback = args->onselect; + item->userdata = args->onselectdata; + item->varname = nl_strdup(args->varname); add_item((UiMenuItemI*)item); } -void ui_menu_radioitemlist_create(UiMenuItemListArgs args) { +void ui_menu_radioitemlist_create(UiMenuItemListArgs *args) { UiMenuItemList* item = malloc(sizeof(UiMenuItemList)); mitem_set_id(&item->item); item->item.prev = NULL; item->item.next = NULL; item->item.type = UI_MENU_RADIOITEM_LIST; - item->callback = args.onselect; - item->userdata = args.onselectdata; - item->varname = nl_strdup(args.varname); + item->callback = args->onselect; + item->userdata = args->onselectdata; + item->varname = nl_strdup(args->varname); add_item((UiMenuItemI*)item); }
--- a/ui/common/object.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/common/object.c Sun Jul 20 22:04:39 2025 +0200 @@ -32,8 +32,48 @@ #include "object.h" #include "context.h" +#include <cx/linked_list.h> + #include "../ui/container.h" +static CxList *creation_callbacks; +static CxList *destruction_callbacks; + +typedef struct objcallback { + ui_object_callback func; + void *userdata; +} objcallback; + +void ui_register_object_creation_callback(ui_object_callback func, void *userdata) { + if(!creation_callbacks) { + creation_callbacks = cxLinkedListCreateSimple(sizeof(objcallback)); + } + objcallback cb = { func, userdata }; + cxListAdd(creation_callbacks, &cb); +} + +void ui_register_object_destruction_callback(ui_object_callback func, void *userdata) { + if(!destruction_callbacks) { + destruction_callbacks = cxLinkedListCreateSimple(sizeof(objcallback)); + } + objcallback cb = { func, userdata }; + cxListAdd(destruction_callbacks, &cb); +} + +void uic_object_created(UiObject *obj) { + CxIterator i = cxListIterator(creation_callbacks); + cx_foreach(objcallback *, cb, i) { + cb->func(obj, cb->userdata); + } +} + +void uic_object_destroyed(UiObject *obj) { + CxIterator i = cxListIterator(destruction_callbacks); + cx_foreach(objcallback *, cb, i) { + cb->func(obj, cb->userdata); + } +} + void ui_end(UiObject *obj) { if(!obj->next) { return; @@ -84,12 +124,22 @@ ev.document = obj->ctx->document; ev.obj = obj; ev.eventdata = NULL; + ev.eventdatatype = 0; ev.intval = 0; obj->ctx->close_callback(&ev, obj->ctx->close_data); } + uic_object_destroyed(obj); cxMempoolFree(obj->ctx->mp); } +UiObject* uic_object_new_toplevel(void) { + CxMempool *mp = cxMempoolCreateSimple(256); + UiObject *obj = cxCalloc(mp->allocator, 1, sizeof(UiObject)); + obj->ctx = uic_context(obj, mp); + uic_object_created(obj); + return obj; +} + UiObject* uic_object_new(UiObject *toplevel, UIWIDGET widget) { return uic_ctx_object_new(toplevel->ctx, widget); } @@ -98,7 +148,7 @@ UiObject *newobj = cxCalloc(ctx->allocator, 1, sizeof(UiObject)); newobj->ctx = ctx; newobj->widget = widget; - + uic_object_created(newobj); return newobj; }
--- a/ui/common/object.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/common/object.h Sun Jul 20 22:04:39 2025 +0200 @@ -35,8 +35,17 @@ extern "C" { #endif +typedef void (*ui_object_callback)(UiObject *obj, void *userdata); + +void ui_register_object_creation_callback(ui_object_callback func, void *userdata); +void ui_register_object_destruction_callback(ui_object_callback func, void *userdata); + +void uic_object_created(UiObject *obj); +void uic_object_destroyed(UiObject *obj); + void uic_object_destroy(UiObject *obj); +UiObject* uic_object_new_toplevel(void); UiObject* uic_object_new(UiObject *toplevel, UIWIDGET widget); UiObject* uic_ctx_object_new(UiContext *ctx, UIWIDGET widget); void uic_obj_add(UiObject *toplevel, UiObject *ctobj);
--- a/ui/common/objs.mk Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/common/objs.mk Sun Jul 20 22:04:39 2025 +0200 @@ -33,13 +33,14 @@ COMMON_OBJ += document$(OBJ_EXT) COMMON_OBJ += object$(OBJ_EXT) COMMON_OBJ += types$(OBJ_EXT) -COMMON_OBJ += menu$(OBJ_EXT) COMMON_OBJ += properties$(OBJ_EXT) COMMON_OBJ += menu$(OBJ_EXT) COMMON_OBJ += toolbar$(OBJ_EXT) COMMON_OBJ += ucx_properties$(OBJ_EXT) COMMON_OBJ += threadpool$(OBJ_EXT) COMMON_OBJ += condvar$(OBJ_EXT) +COMMON_OBJ += args$(OBJ_EXT) +COMMON_OBJ += wrapper$(OBJ_EXT) TOOLKITOBJS += $(COMMON_OBJ:%=$(COMMON_OBJPRE)uic_%) TOOLKITSOURCE += $(COMMON_OBJ:%$(OBJ_EXT)=common/%.c)
--- a/ui/common/properties.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/common/properties.c Sun Jul 20 22:04:39 2025 +0200 @@ -32,6 +32,10 @@ #include <sys/stat.h> #include <errno.h> +#ifdef _WIN32 +#include <direct.h> +#endif + #include "../ui/toolkit.h" @@ -187,6 +191,11 @@ return ret; } +// public +int ui_app_save_settings(void) { + return uic_store_app_properties(); +} + const char* ui_get_property(const char *name) { return cxMapGet(application_properties, name);
--- a/ui/common/threadpool.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/common/threadpool.c Sun Jul 20 22:04:39 2025 +0200 @@ -165,6 +165,7 @@ event.document = job->obj->ctx->document; event.intval = 0; event.eventdata = NULL; + event.eventdatatype = 0; job->finish_callback(&event, job->finish_data); free(job); return 0;
--- a/ui/common/toolbar.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/common/toolbar.c Sun Jul 20 22:04:39 2025 +0200 @@ -49,18 +49,18 @@ return str ? strdup(str) : NULL; } -static UiToolbarItemArgs itemargs_copy(UiToolbarItemArgs args, size_t *ngroups) { +static UiToolbarItemArgs itemargs_copy(UiToolbarItemArgs *args, size_t *ngroups) { UiToolbarItemArgs newargs; - newargs.label = nl_strdup(args.label); - newargs.stockid = nl_strdup(args.stockid); - newargs.icon = nl_strdup(args.icon); - newargs.onclick = args.onclick; - newargs.onclickdata = args.onclickdata; - newargs.groups = uic_copy_groups(args.groups, ngroups); + newargs.label = nl_strdup(args->label); + newargs.stockid = nl_strdup(args->stockid); + newargs.icon = nl_strdup(args->icon); + newargs.onclick = args->onclick; + newargs.onclickdata = args->onclickdata; + newargs.groups = uic_copy_groups(args->groups, ngroups); return newargs; } -void ui_toolbar_item_create(const char* name, UiToolbarItemArgs args) { +void ui_toolbar_item_create(const char* name, UiToolbarItemArgs *args) { UiToolbarItem* item = malloc(sizeof(UiToolbarItem)); item->item.type = UI_TOOLBAR_ITEM; item->args = itemargs_copy(args, &item->ngroups); @@ -68,34 +68,34 @@ } -static UiToolbarToggleItemArgs toggleitemargs_copy(UiToolbarToggleItemArgs args, size_t *ngroups) { +static UiToolbarToggleItemArgs toggleitemargs_copy(UiToolbarToggleItemArgs *args, size_t *ngroups) { UiToolbarToggleItemArgs newargs; - newargs.label = nl_strdup(args.label); - newargs.stockid = nl_strdup(args.stockid); - newargs.icon = nl_strdup(args.icon); - newargs.varname = nl_strdup(args.varname); - newargs.onchange = args.onchange; - newargs.onchangedata = args.onchangedata; - newargs.groups = uic_copy_groups(args.groups, ngroups); + newargs.label = nl_strdup(args->label); + newargs.stockid = nl_strdup(args->stockid); + newargs.icon = nl_strdup(args->icon); + newargs.varname = nl_strdup(args->varname); + newargs.onchange = args->onchange; + newargs.onchangedata = args->onchangedata; + newargs.groups = uic_copy_groups(args->groups, ngroups); return newargs; } -void ui_toolbar_toggleitem_create(const char* name, UiToolbarToggleItemArgs args) { +void ui_toolbar_toggleitem_create(const char* name, UiToolbarToggleItemArgs *args) { UiToolbarToggleItem* item = malloc(sizeof(UiToolbarToggleItem)); item->item.type = UI_TOOLBAR_TOGGLEITEM; item->args = toggleitemargs_copy(args, &item->ngroups); cxMapPut(toolbar_items, name, item); } -static UiToolbarMenuArgs menuargs_copy(UiToolbarMenuArgs args) { +static UiToolbarMenuArgs menuargs_copy(UiToolbarMenuArgs *args) { UiToolbarMenuArgs newargs; - newargs.label = nl_strdup(args.label); - newargs.stockid = nl_strdup(args.stockid); - newargs.icon = nl_strdup(args.icon); + newargs.label = nl_strdup(args->label); + newargs.stockid = nl_strdup(args->stockid); + newargs.icon = nl_strdup(args->icon); return newargs; } -UIEXPORT void ui_toolbar_menu_create(const char* name, UiToolbarMenuArgs args) { +UIEXPORT void ui_toolbar_menu_create(const char* name, UiToolbarMenuArgs *args) { UiToolbarMenuItem* item = malloc(sizeof(UiToolbarMenuItem)); item->item.type = UI_TOOLBAR_MENU; memset(&item->menu, 0, sizeof(UiMenu));
--- a/ui/common/types.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/common/types.c Sun Jul 20 22:04:39 2025 +0200 @@ -36,8 +36,10 @@ #include "../ui/tree.h" #include "types.h" #include "context.h" +#include "../ui/image.h" - +static ui_list_init_func default_list_init; +static void *default_list_init_userdata; UiObserver* ui_observer_new(ui_callback f, void *data) { UiObserver *observer = malloc(sizeof(UiObserver)); @@ -75,6 +77,7 @@ evt.window = NULL; evt.document = NULL; evt.eventdata = data; + evt.eventdatatype = UI_EVENT_DATA_POINTER; evt.intval = 0; while(observer) { @@ -94,20 +97,22 @@ /* --------------------------- UiList --------------------------- */ -UiList* ui_list_new(UiContext *ctx, char *name) { - UiList *list = malloc(sizeof(UiList)); +void uic_ucx_list_init(UiContext *ctx, UiList *list, void *unused) { + list->data = cxArrayListCreate(ctx->mp->allocator, NULL, CX_STORE_POINTERS, 32); list->first = ui_list_first; list->next = ui_list_next; list->get = ui_list_get; list->count = ui_list_count; - list->observers = NULL; - - list->data = cxArrayListCreate(cxDefaultAllocator, NULL, CX_STORE_POINTERS, 32); - list->iter = NULL; - - list->update = NULL; - list->getselection = NULL; - list->obj = NULL; +} + +UiList* ui_list_new(UiContext *ctx, const char *name) { + return ui_list_new2(ctx, name, default_list_init ? default_list_init : uic_ucx_list_init, default_list_init_userdata); +} + +UiList* ui_list_new2(UiContext *ctx, const char *name, ui_list_init_func listinit, void *userdata) { + UiList *list = cxMalloc(ctx->mp->allocator, sizeof(UiList)); + memset(list, 0, sizeof(UiList)); + listinit(ctx, list, userdata); if(name) { uic_reg_var(ctx, name, UI_VAR_LIST, list); @@ -248,7 +253,7 @@ // types // public functions -UiInteger* ui_int_new(UiContext *ctx, char *name) { +UiInteger* ui_int_new(UiContext *ctx, const char *name) { UiInteger *i = ui_malloc(ctx, sizeof(UiInteger)); memset(i, 0, sizeof(UiInteger)); if(name) { @@ -257,7 +262,7 @@ return i; } -UiDouble* ui_double_new(UiContext *ctx, char *name) { +UiDouble* ui_double_new(UiContext *ctx, const char *name) { UiDouble *d = ui_malloc(ctx, sizeof(UiDouble)); memset(d, 0, sizeof(UiDouble)); if(name) { @@ -266,7 +271,7 @@ return d; } -UiString* ui_string_new(UiContext *ctx, char *name) { +UiString* ui_string_new(UiContext *ctx, const char *name) { UiString *s = ui_malloc(ctx, sizeof(UiString)); memset(s, 0, sizeof(UiString)); if(name) { @@ -275,7 +280,7 @@ return s; } -UiText* ui_text_new(UiContext *ctx, char *name) { +UiText* ui_text_new(UiContext *ctx, const char *name) { UiText *t = ui_malloc(ctx, sizeof(UiText)); memset(t, 0, sizeof(UiText)); if(name) { @@ -284,7 +289,7 @@ return t; } -UiRange* ui_range_new(UiContext *ctx, char *name) { +UiRange* ui_range_new(UiContext *ctx, const char *name) { UiRange *r = ui_malloc(ctx, sizeof(UiRange)); memset(r, 0, sizeof(UiRange)); if(name) { @@ -293,7 +298,7 @@ return r; } -UIEXPORT UiGeneric* ui_generic_new(UiContext *ctx, char *name) { +UIEXPORT UiGeneric* ui_generic_new(UiContext *ctx, const char *name) { UiGeneric *g = ui_malloc(ctx, sizeof(UiGeneric)); memset(g, 0, sizeof(UiGeneric)); if(name) { @@ -404,6 +409,30 @@ } } +void ui_generic_set_image(UiGeneric *g, void *img) { + if(g->set) { + g->set(g, img, UI_IMAGE_OBJECT_TYPE); + } else { + if(g->value) { + ui_image_unref(g->value); + } + ui_image_ref(img); + g->value = img; + g->type = UI_IMAGE_OBJECT_TYPE; + } +} + +void* ui_generic_get_image(UiGeneric *g) { + if(g->type) { + if(!strcmp(g->type, UI_IMAGE_OBJECT_TYPE)) { + return g->value; + } else { + return NULL; + } + } + return g->value; +} + // private functions void uic_int_copy(UiInteger *from, UiInteger *to) { @@ -452,6 +481,8 @@ void uic_list_copy(UiList *from, UiList *to) { to->update = from->update; + to->getselection = from->getselection; + to->setselection = from->setselection; to->obj = from->obj; } @@ -634,3 +665,34 @@ int ui_get_setop(void) { return ui_set_op; } + +/* ---------------- List initializers and wrapper functions ---------------- */ + +void ui_global_list_initializer(ui_list_init_func func, void *userdata) { + default_list_init = func; + default_list_init_userdata = userdata; +} + +void ui_list_class_set_first(UiList *list, void*(*first)(UiList *list)) { + list->first = first; +} + +void ui_list_class_set_next(UiList *list, void*(*next)(UiList *list)) { + list->next = next; +} + +void ui_list_class_set_get(UiList *list, void*(*get)(UiList *list, int i)) { + list->get = get; +} + +void ui_list_class_set_count(UiList *list, int(*count)(UiList *list)) { + list->count = count; +} + +void ui_list_class_set_data(UiList *list, void *data) { + list->data = data; +} + +void ui_list_class_set_iter(UiList *list, void *iter) { + list->iter = iter; +}
--- a/ui/common/types.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/common/types.h Sun Jul 20 22:04:39 2025 +0200 @@ -34,8 +34,9 @@ #ifdef __cplusplus extern "C" { #endif - - + +void uic_ucx_list_init(UiContext *ctx, UiList *list, void *unused); + void uic_int_copy(UiInteger *from, UiInteger *to); void uic_double_copy(UiDouble *from, UiDouble *to); void uic_string_copy(UiString *from, UiString *to);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/common/wrapper.c Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,220 @@ +/* + * 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 "wrapper.h" +#include "types.h" +#include <cx/list.h> +#include <string.h> + +/* ---------------------------- UiObject ---------------------------- */ + +UiContext* ui_object_get_context(UiObject *obj) { + return obj->ctx; +} + +void* ui_object_get_windowdata(UiObject *obj) { + return obj->window; +} + +void ui_object_set_windowdata(UiObject *obj, void *windowdata) { + obj->window = windowdata; +} + + +/* ---------------------------- UiList ---------------------------- */ + +void* ui_list_get_data(UiList *list) { + return list->data; +} + +void ui_list_set_data(UiList *list, void *data) { + list->data = data; +} + +void* ui_list_get_iter(UiList *list) { + return list->iter; +} + +void ui_list_set_iter(UiList *list, void *iter) { + list->iter = iter; +} + + +/* ------------------------------ UiSublist ------------------------------ */ + +UiSubList* ui_sublist_new(void) { + UiSubList *sublist = malloc(sizeof(UiSubList)); + memset(sublist, 0, sizeof(UiSubList)); + return sublist; +} + +void ui_sublist_set_value(UiSubList *sublist, UiList *value) { + sublist->value = value; +} + +void ui_sublist_set_varname(UiSubList *sublist, const char *varname) { + free((void*)sublist->varname); + sublist->varname = strdup(varname); +} + +void ui_sublist_set_header(UiSubList *sublist, const char *header) { + free((void*)sublist->header); + sublist->header = strdup(header); +} + +void ui_sublist_set_separator(UiSubList *sublist, UiBool separator) { + sublist->separator = separator; +} + +void ui_sublist_set_userdata(UiSubList *sublist, void *userdata) { + sublist->userdata = userdata; +} + +void ui_sublist_free(UiSubList *sublist) { + free((void*)sublist->varname); + free((void*)sublist->header); + free(sublist); +} + + +/* -------------------- Source list (UiList<UiSublist>) -------------------- */ + +UiList* ui_srclist_new(UiContext *ctx, const char *name) { + UiList *list = ui_list_new2(ctx, name, uic_ucx_list_init, NULL); + CxList *cxlist = list->data; + cxlist->collection.simple_destructor = (cx_destructor_func)ui_sublist_free; + return list; +} + +void ui_srclist_add(UiList *list, UiSubList *item) { + ui_list_append(list, item); +} + +void ui_srclist_insert(UiList *list, int index, UiSubList *item) { + CxList *cxlist = list->data; + cxListInsert(cxlist, index, item); +} + +void ui_srclist_remove(UiList *list, int index) { + CxList *cxlist = list->data; + cxListRemove(cxlist, index); +} + +void ui_srclist_clear(UiList *list) { + CxList *cxlist = list->data; + cxListClear(cxlist); +} + +int ui_srclist_size(UiList *list) { + return ui_list_count(list); +} + + +/* ---------------------------- UiSubListEventData ---------------------------- */ + +UiList* ui_sublist_event_get_list(UiSubListEventData *event) { + return event->list; +} + +int ui_sublist_event_get_sublist_index(UiSubListEventData *event) { + return event->sublist_index; +} + +int ui_sublist_event_get_row_index(UiSubListEventData *event) { + return event->row_index; +} + +void* ui_sublist_event_get_row_data(UiSubListEventData *event) { + return event->row_data; +} + +void* ui_sublist_event_get_sublist_userdata(UiSubListEventData *event) { + return event->sublist_userdata; +} + +void* ui_sublist_event_get_event_data(UiSubListEventData *event) { + return event->event_data; +} + + +/* ---------------------------- UiEvent ---------------------------- */ + +UiObject* ui_event_get_obj(UiEvent *event) { + return event->obj; +} + +void* ui_event_get_document(UiEvent *event) { + return event->document; +} + +void* ui_event_get_windowdata(UiEvent *event) { + return event->window; +} + +void* ui_event_get_eventdata(UiEvent *event) { + return event->eventdata; +} + +int ui_event_get_eventdatatype(UiEvent *event) { + return event->eventdatatype; +} + +int ui_event_get_int(UiEvent *event) { + return event->intval; +} + +int ui_event_get_set(UiEvent *event) { + return event->set; +} + + +/* ------------------------- SubListItem (public) ------------------------- */ + +void ui_sublist_item_set_icon(UiSubListItem *item, const char *icon) { + item->icon = icon ? strdup(icon) : NULL; +} + +void ui_sublist_item_set_label(UiSubListItem *item, const char *label) { + item->label = label ? strdup(label) : NULL; +} + +void ui_sublist_item_set_button_icon(UiSubListItem *item, const char *button_icon) { + item->button_icon = button_icon ? strdup(button_icon) : NULL; +} + +void ui_sublist_item_set_button_label(UiSubListItem *item, const char *button_label) { + item->button_label = button_label ? strdup(button_label) : NULL; +} + +void ui_sublist_item_set_badge(UiSubListItem *item, const char *badge) { + item->badge = badge ? strdup(badge) : NULL; +} + +void ui_sublist_item_set_eventdata(UiSubListItem *item, void *eventdata) { + item->eventdata = NULL; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/common/wrapper.h Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,84 @@ +/* + * 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 UIC_WRAPPER_H +#define UIC_WRAPPER_H + +#include "../ui/toolkit.h" +#include "../ui/tree.h" + +#ifdef __cplusplus +extern "C" { +#endif + +UIEXPORT UiContext* ui_object_get_context(UiObject *obj); +UIEXPORT void* ui_object_get_windowdata(UiObject *obj); +UIEXPORT void ui_object_set_windowdata(UiObject *obj, void *windowdata); + +UIEXPORT void* ui_list_get_data(UiList *list); +UIEXPORT void* ui_list_get_iter(UiList *list); +UIEXPORT void ui_list_set_iter(UiList *list, void *iter); + +UIEXPORT UiSubList* ui_sublist_new(void); +UIEXPORT void ui_sublist_set_value(UiSubList *sublist, UiList *value); +UIEXPORT void ui_sublist_set_varname(UiSubList *sublist, const char *varname); +UIEXPORT void ui_sublist_set_header(UiSubList *sublist, const char *header); +UIEXPORT void ui_sublist_set_separator(UiSubList *sublist, UiBool separator); +UIEXPORT void ui_sublist_set_userdata(UiSubList *sublist, void *userdata); +UIEXPORT void ui_sublist_free(UiSubList *sublist); + +UIEXPORT UiList* ui_srclist_new(UiContext *ctx, const char *name); +UIEXPORT void ui_srclist_add(UiList *list, UiSubList *item); +UIEXPORT void ui_srclist_insert(UiList *list, int index, UiSubList *item); +UIEXPORT void ui_srclist_remove(UiList *list, int index); +UIEXPORT void ui_srclist_clear(UiList *list); +UIEXPORT int ui_srclist_size(UiList *list); + +UIEXPORT UiList* ui_sublist_event_get_list(UiSubListEventData *event); +UIEXPORT int ui_sublist_event_get_sublist_index(UiSubListEventData *event); +UIEXPORT int ui_sublist_event_get_row_index(UiSubListEventData *event); +UIEXPORT void* ui_sublist_event_get_row_data(UiSubListEventData *event); +UIEXPORT void* ui_sublist_event_get_sublist_userdata(UiSubListEventData *event); +UIEXPORT void* ui_sublist_event_get_event_data(UiSubListEventData *event); + +UIEXPORT UiObject* ui_event_get_obj(UiEvent *event); +UIEXPORT void* ui_event_get_document(UiEvent *event); +UIEXPORT void* ui_event_get_windowdata(UiEvent *event); +UIEXPORT void* ui_event_get_eventdata(UiEvent *event); +UIEXPORT int ui_event_get_eventdatatype(UiEvent *event); +UIEXPORT int ui_event_get_int(UiEvent *event); +UIEXPORT int ui_event_get_set(UiEvent *event); + + + +#ifdef __cplusplus +} +#endif + +#endif /* UIC_WRAPPER_H */ +
--- a/ui/gtk/Makefile Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/Makefile Sun Jul 20 22:04:39 2025 +0200 @@ -27,8 +27,10 @@ # $(GTK_OBJPRE)%.o: gtk/%.c - $(CC) -o $@ -c -I../ucx $(CFLAGS) $(TK_CFLAGS) $< + $(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
--- a/ui/gtk/button.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/button.c Sun Jul 20 22:04:39 2025 +0200 @@ -73,6 +73,7 @@ event->callback = onclick; event->value = event_value; event->customdata = NULL; + event->customint = 0; g_signal_connect( button, @@ -96,13 +97,13 @@ return button; } -UIWIDGET ui_button_create(UiObject *obj, UiButtonArgs args) { +UIWIDGET ui_button_create(UiObject *obj, UiButtonArgs *args) { UiObject* current = uic_current_obj(obj); - GtkWidget *button = ui_create_button(obj, args.label, args.icon, args.onclick, args.onclickdata, 0, FALSE); - ui_set_name_and_style(button, args.name, args.style_class); - ui_set_widget_groups(obj->ctx, button, args.groups); - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, button, FALSE); + GtkWidget *button = ui_create_button(obj, args->label, args->icon, args->onclick, args->onclickdata, 0, FALSE); + ui_set_name_and_style(button, args->name, args->style_class); + ui_set_widget_groups(obj->ctx, button, args->groups); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, button); return button; } @@ -113,6 +114,7 @@ e.window = event->obj->window; e.document = event->obj->ctx->document; e.eventdata = NULL; + e.eventdatatype = 0; e.intval = event->value; e.set = ui_get_setop(); event->callback(&e, event->userdata); @@ -137,6 +139,7 @@ e.window = event->obj->window; e.document = event->obj->ctx->document; e.eventdata = event->var->value; + e.eventdatatype = UI_EVENT_DATA_INTEGER_VALUE; e.intval = i->get(i); e.set = ui_get_setop(); @@ -149,6 +152,7 @@ e.window = event->obj->window; e.document = event->obj->ctx->document; e.eventdata = NULL; + e.eventdatatype = 0; e.intval = gtk_toggle_button_get_active(widget); e.set = ui_get_setop(); event->callback(&e, event->userdata); @@ -240,6 +244,7 @@ event->callback = onchange; event->value = 0; event->customdata = NULL; + event->customint = 0; g_signal_connect( widget, @@ -260,6 +265,7 @@ event->callback = NULL; event->value = enable_state; event->customdata = NULL; + event->customint = 0; g_signal_connect( widget, @@ -274,29 +280,29 @@ } } -static UIWIDGET togglebutton_create(UiObject *obj, GtkWidget *widget, UiToggleArgs args) { +static UIWIDGET togglebutton_create(UiObject *obj, GtkWidget *widget, UiToggleArgs *args) { UiObject* current = uic_current_obj(obj); ui_setup_togglebutton( obj, widget, - args.label, - args.icon, - args.varname, - args.value, - args.onchange, - args.onchangedata, - args.enable_group); - ui_set_name_and_style(widget, args.name, args.style_class); - ui_set_widget_groups(obj->ctx, widget, args.groups); + args->label, + args->icon, + args->varname, + args->value, + args->onchange, + args->onchangedata, + args->enable_group); + ui_set_name_and_style(widget, args->name, args->style_class); + ui_set_widget_groups(obj->ctx, widget, args->groups); - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, widget, FALSE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, widget); return widget; } -UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs args) { +UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs *args) { return togglebutton_create(obj, gtk_toggle_button_new(), args); } @@ -320,6 +326,7 @@ e.window = event->obj->window; e.document = event->obj->ctx->document; e.eventdata = NULL; + e.eventdatatype = 0; e.intval = gtk_check_button_get_active(widget); e.set = ui_get_setop(); event->callback(&e, event->userdata); @@ -333,39 +340,39 @@ } } -UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs args) { +UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs *args) { UiObject* current = uic_current_obj(obj); - GtkWidget *widget = gtk_check_button_new_with_label(args.label); + GtkWidget *widget = gtk_check_button_new_with_label(args->label); ui_bind_togglebutton( obj, widget, ui_check_button_get, ui_check_button_set, - args.varname, - args.value, + args->varname, + args->value, (ui_toggled_func)ui_checkbox_callback, - args.onchange, - args.onchangedata, + args->onchange, + args->onchangedata, (ui_toggled_func)ui_checkbox_enable_state, - args.enable_group); + args->enable_group); - ui_set_name_and_style(widget, args.name, args.style_class); - ui_set_widget_groups(obj->ctx, widget, args.groups); + ui_set_name_and_style(widget, args->name, args->style_class); + ui_set_widget_groups(obj->ctx, widget, args->groups); - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, widget, FALSE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, widget); return widget; } #else -UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs args) { +UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs *args) { return togglebutton_create(obj, gtk_check_button_new(), args); } #endif -UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs args) { +UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs *args) { #ifdef UI_GTK3 return NULL; // TODO #else @@ -391,6 +398,7 @@ e.window = event->obj->window; e.document = event->obj->ctx->document; e.eventdata = NULL; + e.eventdatatype = 0; e.intval = RADIOBUTTON_GET_ACTIVE(widget); e.set = ui_get_setop(); event->callback(&e, event->userdata); @@ -415,13 +423,13 @@ free(data); } -UIWIDGET ui_radiobutton_create(UiObject *obj, UiToggleArgs args) { +UIWIDGET ui_radiobutton_create(UiObject *obj, UiToggleArgs *args) { UiObject* current = uic_current_obj(obj); GSList *rg = NULL; UiInteger *rgroup; - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_INTEGER); UiBool first = FALSE; if(var) { @@ -432,9 +440,9 @@ } } - GtkWidget *rbutton = RADIOBUTTON_NEW(rg, args.label); - ui_set_name_and_style(rbutton, args.name, args.style_class); - ui_set_widget_groups(obj->ctx, rbutton, args.groups); + GtkWidget *rbutton = RADIOBUTTON_NEW(rg, args->label); + ui_set_name_and_style(rbutton, args->name, args->style_class); + ui_set_widget_groups(obj->ctx, rbutton, args->groups); if(rgroup) { #if GTK_MAJOR_VERSION >= 4 if(rg) { @@ -476,13 +484,14 @@ rbdata); } - if(args.onchange) { + if(args->onchange) { UiEventData *event = malloc(sizeof(UiEventData)); event->obj = obj; - event->userdata = args.onchangedata; - event->callback = args.onchange; + event->userdata = args->onchangedata; + event->callback = args->onchange; event->value = 0; event->customdata = NULL; + event->customint = 0; g_signal_connect( rbutton, @@ -496,8 +505,8 @@ event); } - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, rbutton, FALSE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, rbutton); return rbutton; } @@ -510,6 +519,7 @@ e.window = event->obj->window; e.document = event->obj->ctx->document; e.eventdata = NULL; + e.eventdatatype = 0; e.intval = i->get(i); ui_notify_evt(i->observers, &e);
--- a/ui/gtk/container.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/container.c Sun Jul 20 22:04:39 2025 +0200 @@ -120,12 +120,9 @@ return (UiContainer*)ct; } -void ui_box_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) { +void ui_box_container_add(UiContainer *ct, GtkWidget *widget) { UiBoxContainer *bc = (UiBoxContainer*)ct; - if(ct->layout.fill != UI_LAYOUT_UNDEFINED) { - fill = ui_lb2bool(ct->layout.fill); - } - + UiBool fill = ct->layout.fill; if(bc->has_fill && fill) { fprintf(stderr, "UiError: container has 2 filled widgets"); fill = FALSE; @@ -180,7 +177,7 @@ } #if GTK_MAJOR_VERSION >= 3 -void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) { +void ui_grid_container_add(UiContainer *ct, GtkWidget *widget) { UiGridContainer *grid = (UiGridContainer*)ct; if(ct->layout.newline) { @@ -208,9 +205,7 @@ } } - if(ct->layout.fill != UI_LAYOUT_UNDEFINED) { - fill = ui_lb2bool(ct->layout.fill); - } + UiBool fill = ct->layout.fill; if(ct->layout.hexpand) { hexpand = TRUE; hfill = TRUE; @@ -249,7 +244,7 @@ } #endif #ifdef UI_GTK2 -void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) { +void ui_grid_container_add(UiContainer *ct, GtkWidget *widget) { UiGridContainer *grid = (UiGridContainer*)ct; if(ct->layout.newline) { @@ -277,9 +272,7 @@ } } - if(ct->layout.fill != UI_LAYOUT_UNDEFINED) { - fill = ui_lb2bool(ct->layout.fill); - } + UiBool fill = ct->layout.fill; if(ct->layout.hexpand) { hexpand = TRUE; hfill = TRUE; @@ -340,7 +333,7 @@ return ct; } -void ui_frame_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) { +void ui_frame_container_add(UiContainer *ct, GtkWidget *widget) { FRAME_SET_CHILD(ct->widget, widget); } @@ -354,11 +347,11 @@ return ct; } -void ui_expander_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) { +void ui_expander_container_add(UiContainer *ct, GtkWidget *widget) { EXPANDER_SET_CHILD(ct->widget, widget); } -void ui_scrolledwindow_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) { +void ui_scrolledwindow_container_add(UiContainer *ct, GtkWidget *widget) { // TODO: check if the widget implements GtkScrollable SCROLLEDWINDOW_SET_CHILD(ct->widget, widget); ui_reset_layout(ct->layout); @@ -385,7 +378,7 @@ return (UiContainer*)ct; } -void ui_tabview_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) { +void ui_tabview_container_add(UiContainer *ct, GtkWidget *widget) { UiGtkTabView *data = ui_widget_get_tabview_data(ct->widget); if(!data) { fprintf(stderr, "UI Error: widget is not a tabview"); @@ -420,15 +413,15 @@ return ret; } -UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs args, UiSubContainerType type) { +UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs *args, UiSubContainerType type) { UiObject *current = uic_current_obj(obj); UiContainer *ct = current->container; - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); - GtkWidget *box = type == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args.spacing) : ui_gtk_hbox_new(args.spacing); - ui_set_name_and_style(box, args.name, args.style_class); - GtkWidget *widget = args.margin > 0 ? ui_box_set_margin(box, args.margin) : box; - ct->add(ct, widget, TRUE); + GtkWidget *box = type == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args->spacing) : ui_gtk_hbox_new(args->spacing); + ui_set_name_and_style(box, args->name, args->style_class); + GtkWidget *widget = args->margin > 0 ? ui_box_set_margin(box, args->margin) : box; + ct->add(ct, widget); UiObject *newobj = uic_object_new(obj, box); newobj->container = ui_box_container(obj, box, type); @@ -437,11 +430,11 @@ return widget; } -UIEXPORT UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs args) { +UIEXPORT UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs *args) { return ui_box_create(obj, args, UI_CONTAINER_VBOX); } -UIEXPORT UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs args) { +UIEXPORT UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs *args) { return ui_box_create(obj, args, UI_CONTAINER_HBOX); } @@ -458,74 +451,74 @@ return grid; } -UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs args) { +UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) { UiObject* current = uic_current_obj(obj); - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); GtkWidget *widget; - GtkWidget *grid = ui_create_grid_widget(args.columnspacing, args.rowspacing); - ui_set_name_and_style(grid, args.name, args.style_class); - widget = ui_box_set_margin(grid, args.margin); - current->container->add(current->container, widget, TRUE); + GtkWidget *grid = ui_create_grid_widget(args->columnspacing, args->rowspacing); + ui_set_name_and_style(grid, args->name, args->style_class); + widget = ui_box_set_margin(grid, args->margin); + current->container->add(current->container, widget); UiObject *newobj = uic_object_new(obj, grid); - newobj->container = ui_grid_container(obj, grid, args.def_hexpand, args.def_vexpand, args.def_hfill, args.def_vfill); + newobj->container = ui_grid_container(obj, grid, args->def_hexpand, args->def_vexpand, args->def_hfill, args->def_vfill); uic_obj_add(obj, newobj); return widget; } -UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs args) { +UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args) { UiObject* current = uic_current_obj(obj); - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); - GtkWidget *frame = gtk_frame_new(args.label); + GtkWidget *frame = gtk_frame_new(args->label); UiObject *newobj = uic_object_new(obj, frame); - GtkWidget *sub = ui_subcontainer_create(args.subcontainer, newobj, args.spacing, args.columnspacing, args.rowspacing, args.margin); + GtkWidget *sub = ui_subcontainer_create(args->subcontainer, newobj, args->spacing, args->columnspacing, args->rowspacing, args->margin); if(sub) { FRAME_SET_CHILD(frame, sub); } else { newobj->widget = frame; newobj->container = ui_frame_container(obj, frame); } - current->container->add(current->container, frame, FALSE); + current->container->add(current->container, frame); uic_obj_add(obj, newobj); return frame; } -UIEXPORT UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs args) { +UIEXPORT UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs *args) { UiObject* current = uic_current_obj(obj); - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); - GtkWidget *expander = gtk_expander_new(args.label); - gtk_expander_set_expanded(GTK_EXPANDER(expander), args.isexpanded); + GtkWidget *expander = gtk_expander_new(args->label); + gtk_expander_set_expanded(GTK_EXPANDER(expander), args->isexpanded); UiObject *newobj = uic_object_new(obj, expander); - GtkWidget *sub = ui_subcontainer_create(args.subcontainer, newobj, args.spacing, args.columnspacing, args.rowspacing, args.margin); + GtkWidget *sub = ui_subcontainer_create(args->subcontainer, newobj, args->spacing, args->columnspacing, args->rowspacing, args->margin); if(sub) { EXPANDER_SET_CHILD(expander, sub); } else { newobj->widget = expander; newobj->container = ui_expander_container(obj, expander); } - current->container->add(current->container, expander, FALSE); + current->container->add(current->container, expander); uic_obj_add(obj, newobj); return expander; } -UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs args) { +UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs *args) { UiObject* current = uic_current_obj(obj); - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); GtkWidget *sw = SCROLLEDWINDOW_NEW(); - ui_set_name_and_style(sw, args.name, args.style_class); - GtkWidget *widget = ui_box_set_margin(sw, args.margin); - current->container->add(current->container, widget, TRUE); + ui_set_name_and_style(sw, args->name, args->style_class); + GtkWidget *widget = ui_box_set_margin(sw, args->margin); + current->container->add(current->container, widget); UiObject *newobj = uic_object_new(obj, sw); - GtkWidget *sub = ui_subcontainer_create(args.subcontainer, newobj, args.spacing, args.columnspacing, args.rowspacing, args.margin); + GtkWidget *sub = ui_subcontainer_create(args->subcontainer, newobj, args->spacing, args->columnspacing, args->rowspacing, args->margin); if(sub) { SCROLLEDWINDOW_SET_CHILD(sw, sub); } else { @@ -689,22 +682,71 @@ return g_object_get_data(G_OBJECT(tabview), "ui_tabview"); } +static void tabview_switch_page( + GtkNotebook *self, + GtkWidget *page, + guint page_num, + gpointer userdata) +{ + UiGtkTabView *tabview = userdata; + if(!tabview->onchange) { + return; + } + + UiEvent event; + event.obj = tabview->obj; + event.window = event.obj->window; + event.document = event.obj->ctx->document; + event.set = ui_get_setop(); + event.eventdata = NULL; + event.eventdatatype = 0; + event.intval = page_num; + + tabview->onchange(&event, tabview->onchange); +} + +#if GTK_CHECK_VERSION(3, 10, 0) + +static void tabview_stack_changed( + GObject *object, + GParamSpec *pspec, + UiGtkTabView *tabview) +{ + if(!tabview->onchange) { + return; + } + + UiEvent event; + event.obj = tabview->obj; + event.window = event.obj->window; + event.document = event.obj->ctx->document; + event.set = ui_get_setop(); + event.eventdata = NULL; + event.eventdatatype = 0; + event.intval = 0; + + tabview->onchange(&event, tabview->onchange); +} + +#endif + typedef int64_t(*ui_tabview_get_func)(UiInteger*); typedef void (*ui_tabview_set_func)(UiInteger*, int64_t); -UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs args) { +UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs *args) { UiGtkTabView *data = malloc(sizeof(UiGtkTabView)); - data->margin = args.margin; - data->spacing = args.spacing; - data->columnspacing = args.columnspacing; - data->rowspacing = args.rowspacing; + memset(data, 0, sizeof(UiGtkTabView)); + data->margin = args->margin; + data->spacing = args->spacing; + data->columnspacing = args->columnspacing; + data->rowspacing = args->rowspacing; ui_tabview_get_func getfunc = NULL; ui_tabview_set_func setfunc = NULL; GtkWidget *widget = NULL; GtkWidget *data_widget = NULL; - switch(args.tabview) { + switch(args->tabview) { case UI_TABVIEW_DOC: { // TODO break; @@ -715,6 +757,7 @@ GtkWidget *sidebar = gtk_stack_sidebar_new(); BOX_ADD(widget, sidebar); GtkWidget *stack = gtk_stack_new(); + g_signal_connect(stack, "notify::visible-child", G_CALLBACK(tabview_stack_changed), data); gtk_stack_set_transition_type (GTK_STACK(stack), GTK_STACK_TRANSITION_TYPE_SLIDE_UP_DOWN); gtk_stack_sidebar_set_stack(GTK_STACK_SIDEBAR(sidebar), GTK_STACK(stack)); BOX_ADD_EXPAND(widget, stack); @@ -734,13 +777,18 @@ case UI_TABVIEW_INVISIBLE: /* fall through */ case UI_TABVIEW_NAVIGATION_TOP2: { widget = gtk_notebook_new(); + g_signal_connect( + widget, + "switch-page", + G_CALLBACK(tabview_switch_page), + data); data_widget = widget; data->select_tab = ui_notebook_tab_select; data->remove_tab = ui_notebook_tab_remove; data->add_tab = ui_notebook_tab_add; getfunc = ui_notebook_get; setfunc = ui_notebook_set; - if(args.tabview == UI_TABVIEW_INVISIBLE) { + if(args->tabview == UI_TABVIEW_INVISIBLE) { gtk_notebook_set_show_tabs(GTK_NOTEBOOK(widget), FALSE); gtk_notebook_set_show_border(GTK_NOTEBOOK(widget), FALSE); } @@ -749,8 +797,8 @@ } UiObject* current = uic_current_obj(obj); - if(args.value || args.varname) { - UiVar *var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER); + if(args->value || args->varname) { + UiVar *var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_INTEGER); UiInteger *i = var->value; i->get = getfunc; i->set = setfunc; @@ -759,10 +807,10 @@ g_object_set_data(G_OBJECT(widget), "ui_tabview", data); data->widget = data_widget; - data->subcontainer = args.subcontainer; + data->subcontainer = args->subcontainer; - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, widget, TRUE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, widget); UiObject *newobj = uic_object_new(obj, widget); newobj->container = ui_tabview_container(obj, widget); @@ -872,14 +920,14 @@ hb_set_part(obj, 1); } -UIWIDGET ui_headerbar_fallback_create(UiObject *obj, UiHeaderbarArgs args) { +UIWIDGET ui_headerbar_fallback_create(UiObject *obj, UiHeaderbarArgs *args) { UiObject *current = uic_current_obj(obj); UiContainer *ct = current->container; - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); - GtkWidget *box = ui_gtk_hbox_new(args.alt_spacing); - ui_set_name_and_style(box, args.name, args.style_class); - ct->add(ct, box, FALSE); + GtkWidget *box = ui_gtk_hbox_new(args->alt_spacing); + ui_set_name_and_style(box, args->name, args->style_class); + ct->add(ct, box); UiObject *newobj = uic_object_new(obj, box); newobj->container = ui_headerbar_fallback_container(obj, box); @@ -910,14 +958,14 @@ return (UiContainer*)ct; } -void ui_headerbar_fallback_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) { +void ui_headerbar_fallback_container_add(UiContainer *ct, GtkWidget *widget) { UiHeaderbarContainer *hb = (UiHeaderbarContainer*)ct; BOX_ADD(ct->widget, widget); } #if GTK_CHECK_VERSION(3, 10, 0) -UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args) { +UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs *args) { GtkWidget *headerbar = g_object_get_data(G_OBJECT(obj->widget), "ui_headerbar"); if(!headerbar) { return ui_headerbar_fallback_create(obj, args); @@ -940,7 +988,7 @@ return (UiContainer*)ct; } -void ui_headerbar_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) { +void ui_headerbar_container_add(UiContainer *ct, GtkWidget *widget) { UiHeaderbarContainer *hb = (UiHeaderbarContainer*)ct; if(hb->part == 0) { UI_HEADERBAR_PACK_START(ct->widget, widget); @@ -958,7 +1006,7 @@ #else -UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args) { +UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs *args) { return ui_headerbar_fallback_create(obj, args); } @@ -967,15 +1015,15 @@ /* -------------------- Sidebar -------------------- */ #ifdef UI_LIBADWAITA -UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs args) { +UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs *args) { GtkWidget *sidebar_toolbar_view = g_object_get_data(G_OBJECT(obj->widget), "ui_sidebar"); if(!sidebar_toolbar_view) { fprintf(stderr, "Error: window is not configured for sidebar\n"); return NULL; } - GtkWidget *box = ui_gtk_vbox_new(args.spacing); - ui_box_set_margin(box, args.margin); + GtkWidget *box = ui_gtk_vbox_new(args->spacing); + ui_box_set_margin(box, args->margin); adw_toolbar_view_set_content(ADW_TOOLBAR_VIEW(sidebar_toolbar_view), box); UiObject *newobj = uic_object_new(obj, box); @@ -985,11 +1033,11 @@ return box; } #else -UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs args) { +UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs *args) { GtkWidget *sidebar_vbox = g_object_get_data(G_OBJECT(obj->widget), "ui_sidebar"); - GtkWidget *box = ui_gtk_vbox_new(args.spacing); - ui_box_set_margin(box, args.margin); + GtkWidget *box = ui_gtk_vbox_new(args->spacing); + ui_box_set_margin(box, args->margin); BOX_ADD_EXPAND(sidebar_vbox, box); UiObject *newobj = uic_object_new(obj, box); @@ -1019,18 +1067,18 @@ -static UIWIDGET splitpane_create(UiObject *obj, UiOrientation orientation, UiSplitPaneArgs args) { +static UIWIDGET splitpane_create(UiObject *obj, UiOrientation orientation, UiSplitPaneArgs *args) { UiObject* current = uic_current_obj(obj); GtkWidget *pane0 = create_paned(orientation); - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, pane0, TRUE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, pane0); - int max = args.max_panes == 0 ? 2 : args.max_panes; + int max = args->max_panes == 0 ? 2 : args->max_panes; UiObject *newobj = uic_object_new(obj, pane0); - newobj->container = ui_splitpane_container(obj, pane0, orientation, max, args.initial_position); + newobj->container = ui_splitpane_container(obj, pane0, orientation, max, args->initial_position); uic_obj_add(obj, newobj); g_object_set_data(G_OBJECT(pane0), "ui_splitpane", newobj->container); @@ -1038,11 +1086,11 @@ return pane0; } -UIWIDGET ui_hsplitpane_create(UiObject *obj, UiSplitPaneArgs args) { +UIWIDGET ui_hsplitpane_create(UiObject *obj, UiSplitPaneArgs *args) { return splitpane_create(obj, UI_HORIZONTAL, args); } -UIWIDGET ui_vsplitpane_create(UiObject *obj, UiSplitPaneArgs args) { +UIWIDGET ui_vsplitpane_create(UiObject *obj, UiSplitPaneArgs *args) { return splitpane_create(obj, UI_VERTICAL, args); } @@ -1058,7 +1106,7 @@ return (UiContainer*)ct; } -void ui_splitpane_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) { +void ui_splitpane_container_add(UiContainer *ct, GtkWidget *widget) { UiSplitPaneContainer *s = (UiSplitPaneContainer*)ct; if(s->nchildren >= s->max) { @@ -1151,7 +1199,7 @@ UiObject *item_obj = cxMapGet(ct->current_items, key); if(item_obj) { // re-add previously created widget - ui_box_container_add(ct->container, item_obj->widget, FALSE); + ui_box_container_add(ct->container, item_obj->widget); } else { // create new widget and object for this list element CxMempool *mp = cxMempoolCreateSimple(256); @@ -1166,7 +1214,7 @@ ct->columnspacing, ct->rowspacing, ct->margin); - ui_box_container_add(ct->container, obj->widget, FALSE); + ui_box_container_add(ct->container, obj->widget); if(ct->create_ui) { ct->create_ui(obj, index, elm, ct->userdata); } @@ -1175,6 +1223,10 @@ elm = list->next(list); index++; } + +#if GTK_MAJOR_VERSION < 4 + gtk_widget_show_all(ct->widget); +#endif } static void destroy_itemlist_container(GtkWidget *w, UiGtkItemListContainer *container) { @@ -1183,33 +1235,33 @@ free(container); } -UIWIDGET ui_itemlist_create(UiObject *obj, UiItemListContainerArgs args) { +UIWIDGET ui_itemlist_create(UiObject *obj, UiItemListContainerArgs *args) { UiObject *current = uic_current_obj(obj); UiContainer *ct = current->container; - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); - GtkWidget *box = args.container == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args.spacing) : ui_gtk_hbox_new(args.spacing); - ui_set_name_and_style(box, args.name, args.style_class); - GtkWidget *widget = args.margin > 0 ? ui_box_set_margin(box, args.margin) : box; - ct->add(ct, widget, TRUE); + GtkWidget *box = args->container == UI_CONTAINER_VBOX ? ui_gtk_vbox_new(args->spacing) : ui_gtk_hbox_new(args->spacing); + ui_set_name_and_style(box, args->name, args->style_class); + GtkWidget *widget = args->margin > 0 ? ui_box_set_margin(box, args->margin) : box; + ct->add(ct, widget); UiGtkItemListContainer *container = malloc(sizeof(UiGtkItemListContainer)); container->parent = obj; container->widget = box; - container->container = ui_box_container(current, box, args.container); - container->create_ui = args.create_ui; - container->userdata = args.userdata; - container->subcontainer = args.subcontainer; + container->container = ui_box_container(current, box, args->container); + container->create_ui = args->create_ui; + container->userdata = args->userdata; + container->subcontainer = args->subcontainer; container->current_items = cxHashMapCreateSimple(CX_STORE_POINTERS); container->current_items->collection.advanced_destructor = remove_item; container->current_items->collection.destructor_data = container; - container->margin = args.sub_margin; - container->spacing = args.sub_spacing; - container->columnspacing = args.sub_columnspacing; - container->rowspacing = args.sub_rowspacing; + container->margin = args->sub_margin; + container->spacing = args->sub_spacing; + container->columnspacing = args->sub_columnspacing; + container->rowspacing = args->sub_rowspacing; container->remove_items = TRUE; - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_LIST); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_LIST); if(var) { UiList *list = var->value; list->obj = container; @@ -1236,7 +1288,7 @@ void ui_layout_fill(UiObject *obj, UiBool fill) { UiContainer *ct = uic_get_current_container(obj); - ct->layout.fill = ui_bool2lb(fill); + ct->layout.fill = fill; } void ui_layout_hexpand(UiObject *obj, UiBool expand) {
--- a/ui/gtk/container.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/container.h Sun Jul 20 22:04:39 2025 +0200 @@ -44,23 +44,15 @@ #endif #define ui_reset_layout(layout) memset(&(layout), 0, sizeof(UiLayout)) -#define ui_lb2bool(b) ((b) == UI_LAYOUT_TRUE ? TRUE : FALSE) -#define ui_bool2lb(b) ((b) ? UI_LAYOUT_TRUE : UI_LAYOUT_FALSE) -typedef void (*ui_container_add_f)(UiContainer*, GtkWidget*, UiBool); +typedef void (*ui_container_add_f)(UiContainer*, GtkWidget*); typedef struct UiDocumentView UiDocumentView; -typedef enum UiLayoutBool { - UI_LAYOUT_UNDEFINED = 0, - UI_LAYOUT_TRUE, - UI_LAYOUT_FALSE, -} UiLayoutBool; - typedef struct UiLayout UiLayout; struct UiLayout { - UiLayoutBool fill; + UiBool fill; UiBool newline; char *label; UiBool hexpand; @@ -78,7 +70,7 @@ UIMENU menu; GtkWidget *current; - void (*add)(UiContainer*, GtkWidget*, UiBool); + void (*add)(UiContainer*, GtkWidget*); UiLayout layout; int close; @@ -122,6 +114,8 @@ int spacing; int columnspacing; int rowspacing; + ui_callback onchange; + void *onchangedata; } UiGtkTabView; @@ -170,13 +164,13 @@ int margin); UiContainer* ui_frame_container(UiObject *obj, GtkWidget *frame); -void ui_frame_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill); +void ui_frame_container_add(UiContainer *ct, GtkWidget *widget); GtkWidget* ui_box_set_margin(GtkWidget *box, int margin); -UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs args, UiSubContainerType type); +UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs *args, UiSubContainerType type); UiContainer* ui_box_container(UiObject *obj, GtkWidget *box, UiSubContainerType type); -void ui_box_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill); +void ui_box_container_add(UiContainer *ct, GtkWidget *widget); GtkWidget* ui_create_grid_widget(int colspacing, int rowspacing); UiContainer* ui_grid_container( @@ -186,22 +180,22 @@ UiBool def_vexpand, UiBool def_hfill, UiBool def_vfill); -void ui_grid_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill); +void ui_grid_container_add(UiContainer *ct, GtkWidget *widget); UiContainer* ui_frame_container(UiObject *obj, GtkWidget *frame); -void ui_frame_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill); +void ui_frame_container_add(UiContainer *ct, GtkWidget *widget); UiContainer* ui_expander_container(UiObject *obj, GtkWidget *expander); -void ui_expander_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill); +void ui_expander_container_add(UiContainer *ct, GtkWidget *widget); UiContainer* ui_scrolledwindow_container(UiObject *obj, GtkWidget *scrolledwindow); -void ui_scrolledwindow_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill); +void ui_scrolledwindow_container_add(UiContainer *ct, GtkWidget *widget); UiContainer* ui_tabview_container(UiObject *obj, GtkWidget *tabview); -void ui_tabview_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill); +void ui_tabview_container_add(UiContainer *ct, GtkWidget *widget); UiContainer* ui_splitpane_container(UiObject *obj, GtkWidget *pane, UiOrientation orientation, int max, int init); -void ui_splitpane_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill); +void ui_splitpane_container_add(UiContainer *ct, GtkWidget *widget); UiGtkTabView* ui_widget_get_tabview_data(UIWIDGET tabview); @@ -210,11 +204,11 @@ #if GTK_CHECK_VERSION(3, 10, 0) UiContainer* ui_headerbar_container(UiObject *obj, GtkWidget *headerbar); -void ui_headerbar_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill); +void ui_headerbar_container_add(UiContainer *ct, GtkWidget *widget); #endif UiContainer* ui_headerbar_fallback_container(UiObject *obj, GtkWidget *headerbar); -void ui_headerbar_fallback_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill); +void ui_headerbar_fallback_container_add(UiContainer *ct, GtkWidget *widget); #ifdef __cplusplus }
--- a/ui/gtk/display.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/display.c Sun Jul 20 22:04:39 2025 +0200 @@ -46,19 +46,19 @@ #endif } -UIWIDGET ui_label_create(UiObject *obj, UiLabelArgs args) { +UIWIDGET ui_label_create(UiObject *obj, UiLabelArgs *args) { UiObject* current = uic_current_obj(obj); const char *css_class = NULL; char *markup = NULL; - if(args.label) { + if(args->label) { #if GTK_MAJOR_VERSION < 3 - switch(args.style) { + switch(args->style) { case UI_LABEL_STYLE_DEFAULT: break; case UI_LABEL_STYLE_TITLE: { - cxmutstr m = cx_asprintf("<b>%s</b>", args.label); + cxmutstr m = cx_asprintf("<b>%s</b>", args->label); markup = m.ptr; - args.label = NULL; + args->label = NULL; } case UI_LABEL_STYLE_SUBTITLE: { break; @@ -68,7 +68,7 @@ } } # else - switch(args.style) { + switch(args->style) { case UI_LABEL_STYLE_DEFAULT: break; case UI_LABEL_STYLE_TITLE: { css_class = "ui_label_title"; @@ -87,7 +87,7 @@ } - GtkWidget *widget = gtk_label_new(args.label); + GtkWidget *widget = gtk_label_new(args->label); if(markup) { gtk_label_set_markup(GTK_LABEL(widget), markup); free(markup); @@ -97,7 +97,7 @@ WIDGET_ADD_CSS_CLASS(widget, css_class); } - switch(args.align) { + switch(args->align) { case UI_ALIGN_DEFAULT: break; case UI_ALIGN_LEFT: set_alignment(widget, 0, .5); break; case UI_ALIGN_RIGHT: set_alignment(widget, 1, .5); break; @@ -105,7 +105,7 @@ } - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_STRING); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_STRING); if(var) { UiString* value = (UiString*)var->value; value->obj = widget; @@ -113,19 +113,19 @@ value->set = ui_label_set; } - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, widget, FALSE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, widget); return widget; } -UIWIDGET ui_llabel_create(UiObject* obj, UiLabelArgs args) { - args.align = UI_ALIGN_LEFT; +UIWIDGET ui_llabel_create(UiObject* obj, UiLabelArgs *args) { + args->align = UI_ALIGN_LEFT; return ui_label_create(obj, args); } -UIWIDGET ui_rlabel_create(UiObject* obj, UiLabelArgs args) { - args.align = UI_ALIGN_RIGHT; +UIWIDGET ui_rlabel_create(UiObject* obj, UiLabelArgs *args) { + args->align = UI_ALIGN_RIGHT; return ui_label_create(obj, args); } @@ -150,7 +150,7 @@ UIWIDGET ui_space_deprecated(UiObject *obj) { GtkWidget *widget = gtk_label_new(""); UiContainer *ct = uic_get_current_container(obj); - ct->add(ct, widget, TRUE); + ct->add(ct, widget); return widget; } @@ -162,7 +162,7 @@ GtkWidget *widget = gtk_hseparator_new(); #endif UiContainer *ct = uic_get_current_container(obj); - ct->add(ct, widget, FALSE); + ct->add(ct, widget); return widget; } @@ -174,14 +174,14 @@ double max; } UiProgressBarRange; -UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs args) { +UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs *args) { UiObject* current = uic_current_obj(obj); GtkWidget *progressbar = gtk_progress_bar_new(); - if(args.max > args.min) { + if(args->max > args->min) { UiProgressBarRange *range = malloc(sizeof(UiProgressBarRange)); - range->min = args.min; - range->max = args.max; + range->min = args->min; + range->max = args->max; g_signal_connect( progressbar, "destroy", @@ -191,7 +191,7 @@ } - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_DOUBLE); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_DOUBLE); if(var && var->value) { UiDouble *value = var->value; value->get = ui_progressbar_get; @@ -200,8 +200,8 @@ ui_progressbar_set(value, value->value); } - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, progressbar, FALSE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, progressbar); return progressbar; } @@ -228,12 +228,12 @@ /* ------------------------- progress spinner ------------------------- */ -UIWIDGET ui_progressspinner_create(UiObject* obj, UiProgressbarSpinnerArgs args) { +UIWIDGET ui_progressspinner_create(UiObject* obj, UiProgressbarSpinnerArgs *args) { UiObject* current = uic_current_obj(obj); GtkWidget *spinner = gtk_spinner_new(); - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_INTEGER); if(var && var->value) { UiInteger *value = var->value; value->get = ui_spinner_get; @@ -242,8 +242,8 @@ ui_spinner_set(value, value->value); } - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, spinner, FALSE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, spinner); return spinner; }
--- a/ui/gtk/entry.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/entry.c Sun Jul 20 22:04:39 2025 +0200 @@ -35,24 +35,24 @@ #include "entry.h" -UIWIDGET ui_spinner_create(UiObject *obj, UiSpinnerArgs args) { +UIWIDGET ui_spinner_create(UiObject *obj, UiSpinnerArgs *args) { double min = 0; double max = 1000; UiObject* current = uic_current_obj(obj); UiVar *var = NULL; - if(args.varname) { - var = uic_get_var(obj->ctx, args.varname); + if(args->varname) { + var = uic_get_var(obj->ctx, args->varname); } if(!var) { - if(args.intvalue) { - var = uic_widget_var(obj->ctx, current->ctx, args.intvalue, NULL, UI_VAR_INTEGER); - } else if(args.doublevalue) { - var = uic_widget_var(obj->ctx, current->ctx, args.doublevalue, NULL, UI_VAR_DOUBLE); - } else if(args.rangevalue) { - var = uic_widget_var(obj->ctx, current->ctx, args.rangevalue, NULL, UI_VAR_RANGE); + if(args->intvalue) { + var = uic_widget_var(obj->ctx, current->ctx, args->intvalue, NULL, UI_VAR_INTEGER); + } else if(args->doublevalue) { + var = uic_widget_var(obj->ctx, current->ctx, args->doublevalue, NULL, UI_VAR_DOUBLE); + } else if(args->rangevalue) { + var = uic_widget_var(obj->ctx, current->ctx, args->rangevalue, NULL, UI_VAR_RANGE); } } @@ -61,18 +61,18 @@ min = r->min; max = r->max; } - if(args.step == 0) { - args.step = 1; + if(args->step == 0) { + args->step = 1; } #ifdef UI_GTK2LEGACY if(min == max) { max = min + 1; } #endif - GtkWidget *spin = gtk_spin_button_new_with_range(min, max, args.step); - ui_set_name_and_style(spin, args.name, args.style_class); - ui_set_widget_groups(obj->ctx, spin, args.groups); - gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), args.digits); + GtkWidget *spin = gtk_spin_button_new_with_range(min, max, args->step); + ui_set_name_and_style(spin, args->name, args->style_class); + ui_set_widget_groups(obj->ctx, spin, args->groups); + gtk_spin_button_set_digits(GTK_SPIN_BUTTON(spin), args->digits); UiObserver **obs = NULL; if(var) { double value = 0; @@ -115,8 +115,8 @@ event->obj = obj; event->var = var; event->observers = obs; - event->callback = args.onchange; - event->userdata = args.onchangedata; + event->callback = args->onchange; + event->userdata = args->onchangedata; g_signal_connect( spin, @@ -129,8 +129,8 @@ G_CALLBACK(ui_destroy_vardata), event); - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, spin, FALSE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, spin); return spin; } @@ -150,7 +150,8 @@ e.obj = event->obj; e.window = event->obj->window; e.document = event->obj->ctx->document; - e.eventdata = &value; + e.eventdata = NULL; + e.eventdatatype = 0; e.intval = (int64_t)value; if(event->callback) {
--- a/ui/gtk/graphics.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/graphics.c Sun Jul 20 22:04:39 2025 +0200 @@ -45,7 +45,7 @@ } UiContainer *ct = uic_get_current_container(obj); - ct->add(ct, widget, TRUE); + ct->add(ct, widget); return widget; }
--- a/ui/gtk/image.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/image.c Sun Jul 20 22:04:39 2025 +0200 @@ -63,7 +63,7 @@ #endif -UIWIDGET ui_imageviewer_create(UiObject *obj, UiImageViewerArgs args) { +UIWIDGET ui_imageviewer_create(UiObject *obj, UiImageViewerArgs *args) { UiObject *current = uic_current_obj(obj); GtkWidget *drawingarea = gtk_drawing_area_new(); @@ -78,10 +78,10 @@ widget = eventbox; #endif - if(args.scrollarea) { + if(args->scrollarea) { toplevel = SCROLLEDWINDOW_NEW(); SCROLLEDWINDOW_SET_CHILD(toplevel, widget); - args.adjustwidgetsize = TRUE; + args->adjustwidgetsize = TRUE; } else { toplevel = widget; } @@ -89,29 +89,29 @@ UiImageViewer *imgviewer = malloc(sizeof(UiImageViewer)); memset(imgviewer, 0, sizeof(UiImageViewer)); imgviewer->obj = obj; - imgviewer->onbuttonpress = args.onbuttonpress; - imgviewer->onbuttonpressdata = args.onbuttonpressdata; - imgviewer->onbuttonrelease = args.onbuttonrelease; - imgviewer->onbuttonreleasedata = args.onbuttonreleasedata; - if(args.image_padding > 0) { - imgviewer->padding_left = args.image_padding; - imgviewer->padding_right = args.image_padding; - imgviewer->padding_top = args.image_padding; - imgviewer->padding_bottom = args.image_padding; + imgviewer->onbuttonpress = args->onbuttonpress; + imgviewer->onbuttonpressdata = args->onbuttonpressdata; + imgviewer->onbuttonrelease = args->onbuttonrelease; + imgviewer->onbuttonreleasedata = args->onbuttonreleasedata; + if(args->image_padding > 0) { + imgviewer->padding_left = args->image_padding; + imgviewer->padding_right = args->image_padding; + imgviewer->padding_top = args->image_padding; + imgviewer->padding_bottom = args->image_padding; } else { - imgviewer->padding_left = args.image_padding_left; - imgviewer->padding_right = args.image_padding_right; - imgviewer->padding_top = args.image_padding_top; - imgviewer->padding_bottom = args.image_padding_bottom; + imgviewer->padding_left = args->image_padding_left; + imgviewer->padding_right = args->image_padding_right; + imgviewer->padding_top = args->image_padding_top; + imgviewer->padding_bottom = args->image_padding_bottom; } - imgviewer->adjustwidgetsize = args.adjustwidgetsize; - imgviewer->autoscale = args.autoscale; - imgviewer->useradjustable = args.useradjustable; + imgviewer->adjustwidgetsize = args->adjustwidgetsize; + imgviewer->autoscale = args->autoscale; + imgviewer->useradjustable = args->useradjustable; imgviewer->zoom_scale = 20; g_object_set_data_full(G_OBJECT(drawingarea), "uiimageviewer", imgviewer, (GDestroyNotify)imageviewer_destroy); - UiVar *var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_GENERIC); + UiVar *var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_GENERIC); imgviewer->var = var; imgviewer->widget = drawingarea; @@ -136,7 +136,7 @@ imgviewer, NULL); - if(args.useradjustable) { + if(args->useradjustable) { gtk_widget_set_focusable(drawingarea, TRUE); } @@ -182,13 +182,13 @@ #endif - if(args.contextmenu) { - UIMENU menu = ui_contextmenu_create(args.contextmenu, obj, widget); + if(args->contextmenu) { + UIMENU menu = ui_contextmenu_create(args->contextmenu, obj, widget); ui_widget_set_contextmenu(widget, menu); } - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, toplevel, TRUE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, toplevel); return toplevel; } @@ -336,6 +336,28 @@ g_object_unref(pixbuf); } else { obj->value = pixbuf; + obj->type = UI_IMAGE_OBJECT_TYPE; + } + + return 0; +} + +UIEXPORT int ui_image_load_data(UiGeneric *obj, const void *imgdata, size_t size) { + GBytes *bytes = g_bytes_new_static(imgdata, size); + GInputStream *in = g_memory_input_stream_new_from_bytes(bytes); + GError *error = NULL; + GdkPixbuf *pixbuf = gdk_pixbuf_new_from_stream(in, NULL, &error); + g_object_unref(in); + if(!pixbuf) { + return 1; + } + + if(obj->set) { + obj->set(obj, pixbuf, UI_IMAGE_OBJECT_TYPE); + g_object_unref(pixbuf); + } else { + obj->value = pixbuf; + obj->type = UI_IMAGE_OBJECT_TYPE; } return 0; @@ -416,6 +438,7 @@ event.window = event.obj->window; event.document = event.obj->ctx->document; event.eventdata = NULL; + event.eventdatatype = 0; event.intval = gtk_gesture_single_get_current_button(GTK_GESTURE_SINGLE(gesture)); event.set = 0; callback(&event, userdata);
--- a/ui/gtk/list.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/list.c Sun Jul 20 22:04:39 2025 +0200 @@ -48,6 +48,15 @@ return column == 0 ? elm : NULL; } +static void* model_getvalue(UiModel *model, UiList *list, void *elm, int row, int col, UiBool *freeResult) { + if(model->getvalue2) { + return model->getvalue2(list, elm, row, col, model->getvalue2data, freeResult); + } else if(model->getvalue) { + return model->getvalue(elm, col); + } + return NULL; +} + /* static GtkTargetEntry targetentries[] = { @@ -73,6 +82,7 @@ typedef struct _ObjWrapper { GObject parent_instance; void *data; + int i; } ObjWrapper; typedef struct _ObjWrapperClass { @@ -89,9 +99,10 @@ self->data = NULL; } -ObjWrapper* obj_wrapper_new(void* data) { +ObjWrapper* obj_wrapper_new(void* data, int i) { ObjWrapper *obj = g_object_new(obj_wrapper_get_type(), NULL); obj->data = data; + obj->i = i; return obj; } @@ -122,20 +133,21 @@ static void column_factory_bind( GtkListItemFactory *factory, GtkListItem *item, gpointer userdata) { UiColData *col = userdata; + UiList *list = col->listview->var ? col->listview->var->value : NULL; ObjWrapper *obj = gtk_list_item_get_item(item); UiModel *model = col->listview->model; UiModelType type = model->types[col->model_column]; - void *data = model->getvalue(obj->data, col->data_column); + UiBool freevalue = FALSE; + void *data = model_getvalue(model, list, obj->data, obj->i, col->data_column, &freevalue); GtkWidget *child = gtk_list_item_get_child(item); - bool freevalue = TRUE; switch(type) { + case UI_STRING_FREE: { + freevalue = TRUE; + } case UI_STRING: { - freevalue = FALSE; - } - case UI_STRING_FREE: { gtk_label_set_label(GTK_LABEL(child), data); if(freevalue) { free(data); @@ -157,10 +169,13 @@ break; } case UI_ICON_TEXT: { - freevalue = FALSE; + } case UI_ICON_TEXT_FREE: { - void *data2 = model->getvalue(obj->data, col->data_column+1); + void *data2 = model_getvalue(model, list, obj->data, obj->i, col->data_column+1, &freevalue); + if(type == UI_ICON_TEXT_FREE) { + freevalue = TRUE; + } GtkWidget *image = g_object_get_data(G_OBJECT(child), "image"); GtkWidget *label = g_object_get_data(G_OBJECT(child), "label"); if(data && image) { @@ -189,34 +204,41 @@ return selection_model; } -static UiListView* create_listview(UiObject *obj, UiListArgs args) { +static UiListView* create_listview(UiObject *obj, UiListArgs *args) { UiListView *tableview = malloc(sizeof(UiListView)); memset(tableview, 0, sizeof(UiListView)); tableview->obj = obj; - tableview->model = args.model; - tableview->onactivate = args.onactivate; - tableview->onactivatedata = args.onactivatedata; - tableview->onselection = args.onselection; - tableview->onselectiondata = args.onselectiondata; - tableview->ondragstart = args.ondragstart; - tableview->ondragstartdata = args.ondragstartdata; - tableview->ondragcomplete = args.ondragcomplete; - tableview->ondragcompletedata = args.ondragcompletedata; - tableview->ondrop = args.ondrop; - tableview->ondropdata = args.ondropsdata; + tableview->model = args->model; + tableview->onactivate = args->onactivate; + tableview->onactivatedata = args->onactivatedata; + tableview->onselection = args->onselection; + tableview->onselectiondata = args->onselectiondata; + tableview->ondragstart = args->ondragstart; + tableview->ondragstartdata = args->ondragstartdata; + tableview->ondragcomplete = args->ondragcomplete; + tableview->ondragcompletedata = args->ondragcompletedata; + tableview->ondrop = args->ondrop; + tableview->ondropdata = args->ondropdata; tableview->selection.count = 0; tableview->selection.rows = NULL; return tableview; } -UIWIDGET ui_listview_create(UiObject *obj, UiListArgs args) { +UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args) { UiObject* current = uic_current_obj(obj); // to simplify things and share code with ui_table_create, we also // use a UiModel for the listview UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1); - model->getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue; - args.model = model; + if(args->getvalue2) { + model->getvalue2 = args->getvalue2; + model->getvalue2data = args->getvalue2data; + } else if(args->getvalue) { + model->getvalue = args->getvalue; + } else { + model->getvalue = ui_strmodel_getvalue; + } + args->model = model; GListStore *ls = g_list_store_new(G_TYPE_OBJECT); UiListView *listview = create_listview(obj, args); @@ -230,10 +252,10 @@ g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), listview->columns); g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), listview->columns); - GtkSelectionModel *selection_model = create_selection_model(listview, ls, args.multiselection); + GtkSelectionModel *selection_model = create_selection_model(listview, ls, args->multiselection); GtkWidget *view = gtk_list_view_new(GTK_SELECTION_MODEL(selection_model), factory); - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->list, args->varname, UI_VAR_LIST); // init listview listview->widget = view; @@ -256,19 +278,23 @@ list->setselection = ui_listview_setselection2; ui_update_liststore(ls, list); - } else if (args.static_elements && args.static_nelm > 0) { - listview_copy_static_elements(listview, args.static_elements, args.static_nelm); + } else if (args->static_elements && args->static_nelm > 0) { + listview_copy_static_elements(listview, args->static_elements, args->static_nelm); listview->model->getvalue = ui_strmodel_getvalue; // force strmodel ui_update_liststore_static(ls, listview->elements, listview->nelm); } // event handling - if(args.onactivate) { + if(args->onactivate) { // columnview and listview can use the same callback function, because // the first parameter (which is technically a different pointer type) // is ignored g_signal_connect(view, "activate", G_CALLBACK(ui_columnview_activate), listview); } + if(args->contextmenu) { + UIMENU menu = ui_contextmenu_create(args->contextmenu, obj, view); + ui_widget_set_contextmenu(view, menu); + } // add widget to parent GtkWidget *scroll_area = SCROLLEDWINDOW_NEW(); @@ -278,8 +304,8 @@ GTK_POLICY_AUTOMATIC); // GTK_POLICY_ALWAYS SCROLLEDWINDOW_SET_CHILD(scroll_area, view); - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, scroll_area, FALSE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, scroll_area); // ct->current should point to view, not scroll_area, to make it possible // to add a context menu @@ -288,14 +314,21 @@ return scroll_area; } -UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs args) { +UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs *args) { UiObject* current = uic_current_obj(obj); // to simplify things and share code with ui_tableview_create, we also // use a UiModel for the listview UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1); - model->getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue; - args.model = model; + if(args->getvalue2) { + model->getvalue2 = args->getvalue2; + model->getvalue2data = args->getvalue2data; + } else if(args->getvalue) { + model->getvalue = args->getvalue; + } else { + model->getvalue = ui_strmodel_getvalue; + } + args->model = model; GListStore *ls = g_list_store_new(G_TYPE_OBJECT); UiListView *listview = create_listview(obj, args); @@ -312,7 +345,7 @@ GtkWidget *view = gtk_drop_down_new(G_LIST_MODEL(ls), NULL); gtk_drop_down_set_factory(GTK_DROP_DOWN(view), factory); - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->list, args->varname, UI_VAR_LIST); // init listview listview->widget = view; @@ -335,20 +368,20 @@ list->setselection = ui_combobox_setselection; ui_update_liststore(ls, list); - } else if (args.static_elements && args.static_nelm > 0) { - listview_copy_static_elements(listview, args.static_elements, args.static_nelm); + } else if (args->static_elements && args->static_nelm > 0) { + listview_copy_static_elements(listview, args->static_elements, args->static_nelm); listview->model->getvalue = ui_strmodel_getvalue; // force strmodel ui_update_liststore_static(ls, listview->elements, listview->nelm); } // event handling - if(args.onactivate) { + if(args->onactivate) { g_signal_connect(view, "notify::selected", G_CALLBACK(ui_dropdown_notify), listview); } // add widget to parent - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, view, FALSE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, view); return view; } @@ -361,7 +394,7 @@ gtk_drop_down_set_selected(GTK_DROP_DOWN(dropdown), index); } -UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) { +UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) { UiObject* current = uic_current_obj(obj); GListStore *ls = g_list_store_new(G_TYPE_OBJECT); @@ -371,10 +404,10 @@ // and list updates UiListView *tableview = create_listview(obj, args); - GtkSelectionModel *selection_model = create_selection_model(tableview, ls, args.multiselection); + GtkSelectionModel *selection_model = create_selection_model(tableview, ls, args->multiselection); GtkWidget *view = gtk_column_view_new(GTK_SELECTION_MODEL(selection_model)); - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->list, args->varname, UI_VAR_LIST); // init tableview tableview->widget = view; @@ -389,7 +422,7 @@ // create columns from UiModel - UiModel *model = args.model; + UiModel *model = args->model; int columns = model ? model->columns : 0; tableview->columns = calloc(columns, sizeof(UiColData)); @@ -435,9 +468,13 @@ } // event handling - if(args.onactivate) { + if(args->onactivate) { g_signal_connect(view, "activate", G_CALLBACK(ui_columnview_activate), tableview); } + if(args->contextmenu) { + UIMENU menu = ui_contextmenu_create(args->contextmenu, obj, view); + ui_widget_set_contextmenu(view, menu); + } // add widget to parent GtkWidget *scroll_area = SCROLLEDWINDOW_NEW(); @@ -447,8 +484,8 @@ GTK_POLICY_AUTOMATIC); // GTK_POLICY_ALWAYS SCROLLEDWINDOW_SET_CHILD(scroll_area, view); - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, scroll_area, FALSE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, scroll_area); // ct->current should point to view, not scroll_area, to make it possible // to add a context menu @@ -474,6 +511,7 @@ event.window = event.obj->window; event.intval = view->selection.count; event.eventdata = &view->selection; + event.eventdatatype = UI_EVENT_DATA_LIST_SELECTION; event.set = ui_get_setop(); if(cb) { cb(&event, cbdata); @@ -517,6 +555,7 @@ event.window = event.obj->window; event.intval = index; event.eventdata = eventdata->data; + event.eventdatatype = UI_EVENT_DATA_LIST_ELM; event.set = ui_get_setop(); view->onactivate(&event, view->onactivatedata); } @@ -554,6 +593,7 @@ event.window = event.obj->window; event.intval = view->selection.count; event.eventdata = &view->selection; + event.eventdatatype = UI_EVENT_DATA_LIST_SELECTION; event.set = ui_get_setop(); view->onactivate(&event, view->onactivatedata); } @@ -561,9 +601,10 @@ void ui_update_liststore(GListStore *liststore, UiList *list) { g_list_store_remove_all(liststore); + int i = 0; void *elm = list->first(list); while(elm) { - ObjWrapper *obj = obj_wrapper_new(elm); + ObjWrapper *obj = obj_wrapper_new(elm, i++); g_list_store_append(liststore, obj); elm = list->next(list); } @@ -572,7 +613,7 @@ void ui_update_liststore_static(GListStore *liststore, char **elm, size_t nelm) { g_list_store_remove_all(liststore); for(int i=0;i<nelm;i++) { - ObjWrapper *obj = obj_wrapper_new(elm[i]); + ObjWrapper *obj = obj_wrapper_new(elm[i], i); g_list_store_append(liststore, obj); } } @@ -584,10 +625,15 @@ } else { void *value = list->get(list, i); if(value) { - ObjWrapper *obj = obj_wrapper_new(value); + ObjWrapper *obj = obj_wrapper_new(value, i); // TODO: if index i is selected, the selection is lost // is it possible to update the item without removing it? - g_list_store_splice(view->liststore, i, 1, (void **)&obj, 1); + int count = g_list_model_get_n_items(G_LIST_MODEL(view->liststore)); + if(count <= i) { + g_list_store_splice(view->liststore, i, 0, (void **)&obj, 1); + } else { + g_list_store_splice(view->liststore, i, 1, (void **)&obj, 1); + } } } } @@ -649,19 +695,22 @@ #else -static void update_list_row(GtkListStore *store, GtkTreeIter *iter, UiModel *model, void *elm) { +static void update_list_row(GtkListStore *store, GtkTreeIter *iter, UiModel *model, UiList *list, void *elm, int row) { // set column values int c = 0; for(int i=0;i<model->columns;i++,c++) { - void *data = model->getvalue(elm, c); + UiBool freevalue = FALSE; + void *data = model_getvalue(model, list, elm, row, c, &freevalue); GValue value = G_VALUE_INIT; switch(model->types[i]) { - case UI_STRING: case UI_STRING_FREE: { + freevalue = TRUE; + } + case UI_STRING: { g_value_init(&value, G_TYPE_STRING); g_value_set_string(&value, data); - if(model->types[i] == UI_STRING_FREE) { + if(freevalue) { free(data); } break; @@ -714,11 +763,12 @@ } #endif c++; - - char *str = model->getvalue(elm, c); + + freevalue = FALSE; + char *str = model_getvalue(model, list, elm, row, c, &freevalue); g_value_init(&value, G_TYPE_STRING); g_value_set_string(&value, str); - if(model->types[i] == UI_ICON_TEXT_FREE) { + if(model->types[i] == UI_ICON_TEXT_FREE || freevalue) { free(str); } break; @@ -751,12 +801,13 @@ if(list) { void *elm = list->first(list); + int i = 0; while(elm) { // insert new row GtkTreeIter iter; gtk_list_store_insert (store, &iter, -1); - update_list_row(store, &iter, model, elm); + update_list_row(store, &iter, model, list, elm, i++); // next row elm = list->next(list); @@ -767,13 +818,13 @@ } -UIWIDGET ui_listview_create(UiObject *obj, UiListArgs args) { +UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args) { UiObject* current = uic_current_obj(obj); // create treeview GtkWidget *view = gtk_tree_view_new(); - ui_set_name_and_style(view, args.name, args.style_class); - ui_set_widget_groups(obj->ctx, view, args.groups); + ui_set_name_and_style(view, args->name, args->style_class); + ui_set_widget_groups(obj->ctx, view, args->groups); GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(NULL, renderer, "text", 0, NULL); gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); @@ -790,9 +841,16 @@ #endif UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1); - model->getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue; + if(args->getvalue2) { + model->getvalue2 = args->getvalue2; + model->getvalue2data = args->getvalue2data; + } else if(args->getvalue) { + model->getvalue = args->getvalue; + } else { + model->getvalue = ui_strmodel_getvalue; + } - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->list, args->varname, UI_VAR_LIST); UiList *list = var ? var->value : NULL; GtkListStore *listmodel = create_list_store(list, model); @@ -822,24 +880,24 @@ // add callback UiTreeEventData *event = malloc(sizeof(UiTreeEventData)); event->obj = obj; - event->activate = args.onactivate; - event->activatedata = args.onactivatedata; - event->selection = args.onselection; - event->selectiondata = args.onselectiondata; + event->activate = args->onactivate; + event->activatedata = args->onactivatedata; + event->selection = args->onselection; + event->selectiondata = args->onselectiondata; g_signal_connect( view, "destroy", G_CALLBACK(ui_destroy_userdata), event); - if(args.onactivate) { + if(args->onactivate) { g_signal_connect( view, "row-activated", G_CALLBACK(ui_listview_activate_event), event); } - if(args.onselection) { + if(args->onselection) { GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(view)); g_signal_connect( @@ -848,8 +906,8 @@ G_CALLBACK(ui_listview_selection_event), event); } - if(args.contextmenu) { - UIMENU menu = ui_contextmenu_create(args.contextmenu, obj, view); + if(args->contextmenu) { + UIMENU menu = ui_contextmenu_create(args->contextmenu, obj, view); ui_widget_set_contextmenu(view, menu); } @@ -862,7 +920,7 @@ GTK_POLICY_AUTOMATIC); // GTK_POLICY_ALWAYS SCROLLEDWINDOW_SET_CHILD(scroll_area, view); - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); current->container->add(current->container, scroll_area, FALSE); // ct->current should point to view, not scroll_area, to make it possible @@ -883,13 +941,13 @@ gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown), index); } -UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) { +UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) { UiObject* current = uic_current_obj(obj); // create treeview GtkWidget *view = gtk_tree_view_new(); - UiModel *model = args.model; + UiModel *model = args->model; int columns = model ? model->columns : 0; int addi = 0; @@ -946,7 +1004,7 @@ #endif - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->list, args->varname, UI_VAR_LIST); UiList *list = var ? var->value : NULL; GtkListStore *listmodel = create_list_store(list, model); @@ -964,12 +1022,12 @@ tableview->widget = view; tableview->var = var; tableview->model = model; - tableview->ondragstart = args.ondragstart; - tableview->ondragstartdata = args.ondragstartdata; - tableview->ondragcomplete = args.ondragcomplete; - tableview->ondragcompletedata = args.ondragcompletedata; - tableview->ondrop = args.ondrop; - tableview->ondropdata = args.ondropsdata; + tableview->ondragstart = args->ondragstart; + tableview->ondragstartdata = args->ondragstartdata; + tableview->ondragcomplete = args->ondragcomplete; + tableview->ondragcompletedata = args->ondragcompletedata; + tableview->ondrop = args->ondrop; + tableview->ondropdata = args->ondropdata; tableview->selection.count = 0; tableview->selection.rows = NULL; g_signal_connect( @@ -987,18 +1045,18 @@ // add callback UiTreeEventData *event = ui_malloc(obj->ctx, sizeof(UiTreeEventData)); event->obj = obj; - event->activate = args.onactivate; - event->selection = args.onselection; - event->activatedata = args.onactivatedata; - event->selectiondata = args.onselectiondata; - if(args.onactivate) { + event->activate = args->onactivate; + event->selection = args->onselection; + event->activatedata = args->onactivatedata; + event->selectiondata = args->onselectiondata; + if(args->onactivate) { g_signal_connect( view, "row-activated", G_CALLBACK(ui_listview_activate_event), event); } - if(args.onselection) { + if(args->onselection) { GtkTreeSelection *selection = gtk_tree_view_get_selection( GTK_TREE_VIEW(view)); g_signal_connect( @@ -1010,15 +1068,15 @@ // TODO: destroy callback - if(args.ondragstart) { - ui_listview_add_dnd(tableview, &args); + if(args->ondragstart) { + ui_listview_add_dnd(tableview, args); } - if(args.ondrop) { - ui_listview_enable_drop(tableview, &args); + if(args->ondrop) { + ui_listview_enable_drop(tableview, args); } GtkTreeSelection *selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(view)); - if(args.multiselection) { + if(args->multiselection) { gtk_tree_selection_set_mode(selection, GTK_SELECTION_MULTIPLE); } @@ -1030,8 +1088,8 @@ GTK_POLICY_AUTOMATIC); // GTK_POLICY_ALWAYS SCROLLEDWINDOW_SET_CHILD(scroll_area, view); - if(args.contextmenu) { - UIMENU menu = ui_contextmenu_create(args.contextmenu, obj, scroll_area); + if(args->contextmenu) { + UIMENU menu = ui_contextmenu_create(args->contextmenu, obj, scroll_area); #if GTK_MAJOR_VERSION >= 4 ui_widget_set_contextmenu(scroll_area, menu); #else @@ -1039,7 +1097,7 @@ #endif } - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); current->container->add(current->container, scroll_area, FALSE); // ct->current should point to view, not scroll_area, to make it possible @@ -1062,7 +1120,7 @@ GtkTreeModel *store = gtk_tree_view_get_model(GTK_TREE_VIEW(view->widget)); GtkTreeIter iter; if(gtk_tree_model_iter_nth_child(store, &iter, NULL, i)) { - update_list_row(GTK_LIST_STORE(store), &iter, view->model, elm); + update_list_row(GTK_LIST_STORE(store), &iter, view->model, list, elm, i); } } } @@ -1089,18 +1147,25 @@ /* --------------------------- ComboBox --------------------------- */ -UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs args) { +UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs *args) { UiObject* current = uic_current_obj(obj); UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1); - model->getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue; - - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST); + if(args->getvalue2) { + model->getvalue2 = args->getvalue2; + model->getvalue2data = args->getvalue2data; + } else if(args->getvalue) { + model->getvalue = args->getvalue; + } else { + model->getvalue = ui_strmodel_getvalue; + } - GtkWidget *combobox = ui_create_combobox(obj, model, var, args.static_elements, args.static_nelm, args.onactivate, args.onactivatedata); - ui_set_name_and_style(combobox, args.name, args.style_class); - ui_set_widget_groups(obj->ctx, combobox, args.groups); - UI_APPLY_LAYOUT1(current, args); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->list, args->varname, UI_VAR_LIST); + + GtkWidget *combobox = ui_create_combobox(obj, model, var, args->static_elements, args->static_nelm, args->onactivate, args->onactivatedata); + ui_set_name_and_style(combobox, args->name, args->style_class); + ui_set_widget_groups(obj->ctx, combobox, args->groups); + UI_APPLY_LAYOUT2(current, args); current->container->add(current->container, combobox, FALSE); current->container->current = combobox; return combobox; @@ -1323,6 +1388,7 @@ event.window = event.obj->window; event.document = event.obj->ctx->document; event.eventdata = dnd; + event.eventdatatype = UI_EVENT_DATA_DND; event.intval = 0; event.set = ui_get_setop(); listview->ondragstart(&event, listview->ondragstartdata); @@ -1359,6 +1425,7 @@ event.window = event.obj->window; event.document = event.obj->ctx->document; event.eventdata = &dnd; + event.eventdatatype = UI_EVENT_DATA_DND; event.intval = 0; event.set = ui_get_setop(); listview->ondragcomplete(&event, listview->ondragcompletedata); @@ -1388,6 +1455,7 @@ event.window = event.obj->window; event.document = event.obj->ctx->document; event.eventdata = &dnd; + event.eventdatatype = UI_EVENT_DATA_DND; event.intval = 0; event.set = ui_get_setop(); listview->ondrop(&event, listview->ondropdata); @@ -1745,7 +1813,7 @@ cxListAdd(sublists, &uisublist); } -UIEXPORT UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs args) { +UIEXPORT UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs *args) { UiObject* current = uic_current_obj(obj); #ifdef UI_GTK3 @@ -1753,7 +1821,7 @@ #else GtkWidget *listbox = gtk_list_box_new(); #endif - if(!args.style_class) { + if(!args->style_class) { #if GTK_MAJOR_VERSION >= 4 WIDGET_ADD_CSS_CLASS(listbox, "navigation-sidebar"); #else @@ -1764,31 +1832,32 @@ GtkWidget *scroll_area = SCROLLEDWINDOW_NEW(); SCROLLEDWINDOW_SET_CHILD(scroll_area, listbox); - ui_set_name_and_style(listbox, args.name, args.style_class); - ui_set_widget_groups(obj->ctx, listbox, args.groups); - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, scroll_area, TRUE); + ui_set_name_and_style(listbox, args->name, args->style_class); + ui_set_widget_groups(obj->ctx, listbox, args->groups); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, scroll_area); UiListBox *uilistbox = malloc(sizeof(UiListBox)); uilistbox->obj = obj; uilistbox->listbox = GTK_LIST_BOX(listbox); - uilistbox->getvalue = args.getvalue; - uilistbox->onactivate = args.onactivate; - uilistbox->onactivatedata = args.onactivatedata; - uilistbox->onbuttonclick = args.onbuttonclick; - uilistbox->onbuttonclickdata = args.onbuttonclickdata; + uilistbox->getvalue = args->getvalue; + uilistbox->getvaluedata = args->getvaluedata; + uilistbox->onactivate = args->onactivate; + uilistbox->onactivatedata = args->onactivatedata; + uilistbox->onbuttonclick = args->onbuttonclick; + uilistbox->onbuttonclickdata = args->onbuttonclickdata; uilistbox->sublists = cxArrayListCreateSimple(sizeof(UiListBoxSubList), 4); uilistbox->sublists->collection.advanced_destructor = (cx_destructor_func2)sublist_destroy; uilistbox->sublists->collection.destructor_data = obj; uilistbox->first_row = NULL; - if(args.sublists) { + if(args->sublists) { // static sublist initalization - if(args.numsublists == 0 && args.sublists) { - args.numsublists = INT_MAX; + if(args->numsublists == 0 && args->sublists) { + args->numsublists = INT_MAX; } - for(int i=0;i<args.numsublists;i++) { - UiSubList sublist = args.sublists[i]; + for(int i=0;i<args->numsublists;i++) { + UiSubList sublist = args->sublists[i]; if(!sublist.varname && !sublist.value) { break; } @@ -1799,13 +1868,13 @@ // fill items ui_listbox_update(uilistbox, 0, cxListSize(uilistbox->sublists)); } else { - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.dynamic_sublist, args.varname, UI_VAR_LIST); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->dynamic_sublist, args->varname, UI_VAR_LIST); if(var) { UiList *list = var->value; list->obj = uilistbox; list->update = ui_listbox_dynamic_update; - ui_listbox_dynamic_update(list, 0); + ui_listbox_dynamic_update(list, -1); } } @@ -1821,7 +1890,7 @@ G_CALLBACK(ui_destroy_sourcelist), uilistbox); - if(args.onactivate) { + if(args->onactivate) { g_signal_connect( listbox, "row-activated", @@ -1838,6 +1907,15 @@ // unbind/free previous list vars CxIterator i = cxListIterator(uilistbox->sublists); cx_foreach(UiListBoxSubList *, s, i) { + // TODO: "unbind/free previous list vars" will also remove + // the widget list. This makes the widget optimization + // in ui_listbox_update_sublist pointless + // Is it actually possible to not recreate the whole list? + CxIterator r = cxListIterator(s->widgets); + cx_foreach(GtkWidget*, widget, r) { + LISTBOX_REMOVE(uilistbox->listbox, widget); + } + if(s->var) { UiList *sl = s->var->value; sl->obj = NULL; @@ -1936,7 +2014,11 @@ void *elm = list->first(list); while(elm) { UiSubListItem item = { NULL, NULL, NULL, NULL, NULL, NULL }; - listbox->getvalue(sublist->userdata, elm, index, &item); + if(listbox->getvalue) { + listbox->getvalue(list, sublist->userdata, elm, index, &item, listbox->getvaluedata); + } else { + item.label = strdup(elm); + } // create listbox item GtkWidget *row = create_listbox_row(listbox, sublist, &item, (int)index); @@ -1987,7 +2069,7 @@ eventdata.sublist_index = sublist->index; eventdata.row_index = data->value0; eventdata.sublist_userdata = sublist->userdata; - eventdata.row_data = ui_list_get(eventdata.list, eventdata.row_index); + eventdata.row_data = eventdata.list->get(eventdata.list, eventdata.row_index); eventdata.event_data = data->customdata2; UiEvent event; @@ -1995,6 +2077,7 @@ event.window = event.obj->window; event.document = event.obj->ctx->document; event.eventdata = &eventdata; + event.eventdatatype = UI_EVENT_DATA_SUBLIST; event.intval = data->value0; event.set = ui_get_setop();
--- a/ui/gtk/list.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/list.h Sun Jul 20 22:04:39 2025 +0200 @@ -98,6 +98,7 @@ GtkListBox *listbox; CxList *sublists; // contains UiListBoxSubList elements ui_sublist_getvalue_func getvalue; + void *getvaluedata; ui_callback onactivate; void *onactivatedata; ui_callback onbuttonclick;
--- a/ui/gtk/menu.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/menu.c Sun Jul 20 22:04:39 2025 +0200 @@ -233,6 +233,20 @@ } */ +static void menuitem_list_remove_binding(void *obj) { + UiActiveMenuItemList *ls = obj; + UiList *list = ls->var->value; + CxList *bindings = list->obj; + if(bindings) { + (void)cxListFindRemove(bindings, obj); + if(cxListSize(bindings) == 0) { + cxListFree(bindings); + list->obj = NULL; + list->update = NULL; + } + } +} + void add_menuitem_list_widget(GtkWidget *p, int index, UiMenuItemI *item, UiObject *obj) { UiMenuItemList *il = (UiMenuItemList*)item; const CxAllocator *a = obj->ctx->allocator; @@ -247,21 +261,45 @@ ls->oldcount = 0; ls->getvalue = il->getvalue; - UiVar* var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST); - ls->list = var->value; + //UiVar* var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST); + UiVar* var = uic_create_var(obj->ctx, il->varname, UI_VAR_LIST); + ls->var = var; + if(var) { + UiList *list = var->value; + list->update = ui_menulist_update; + list->getselection = NULL; + list->setselection = NULL; + + // It is possible, that the UiVar is from a global shared context, + // used by multiple windows. To support this usecase, the list->obj + // binding object is a list of all connected UiActiveMenuItemList. + CxList *bindings = list->obj; + if(!bindings) { + bindings = cxLinkedListCreate(var->from_ctx->mp->allocator, NULL, CX_STORE_POINTERS); + list->obj = bindings; + } + cxListAdd(bindings, ls); + + // The destruction of the toplevel obj must remove the menulist binding + uic_context_add_destructor(obj->ctx, menuitem_list_remove_binding, ls); + + ui_update_menuitem_list(ls); + } ls->callback = il->callback; ls->userdata = il->userdata; - - UiObserver *observer = ui_observer_new((ui_callback)ui_update_menuitem_list, ls); - ls->list->observers = ui_obsvlist_add(ls->list->observers, observer); - uic_list_register_observer_destructor(obj->ctx, ls->list, observer); - - ui_update_menuitem_list(NULL, ls); +} + +void ui_menulist_update(UiList *list, int ignored) { + CxList *bindings = list->obj; + CxIterator i = cxListIterator(bindings); + cx_foreach(UiActiveMenuItemList *, ls, i) { + ui_update_menuitem_list(ls); + } } -void ui_update_menuitem_list(UiEvent *event, UiActiveMenuItemList *list) { +void ui_update_menuitem_list(UiActiveMenuItemList *list) { // remove old items if(list->oldcount > 0) { int i = 0; @@ -276,7 +314,9 @@ } } - void* elm = ui_list_first(list->list); + UiList *ls = list->var->value; + + void* elm = ui_list_first(ls); if(elm) { GtkWidget *widget = gtk_separator_menu_item_new(); gtk_menu_shell_insert(list->menu, widget, list->index); @@ -312,7 +352,7 @@ event); } - elm = ui_list_next(list->list); + elm = ui_list_next(ls); i++; } @@ -474,6 +514,7 @@ event->callback = i->callback; event->value = 0; event->customdata = NULL; + event->customint = 0; g_signal_connect( action, @@ -506,6 +547,20 @@ } +static void menuitem_list_remove_binding(void *obj) { + UiActiveGMenuItemList *ls = obj; + UiList *list = ls->var->value; + CxList *bindings = list->obj; + if(bindings) { + (void)cxListFindRemove(bindings, obj); + if(cxListSize(bindings) == 0) { + cxListFree(bindings); + list->obj = NULL; + list->update = NULL; + } + } +} + void ui_gmenu_add_menuitem_list(GMenu *p, int index, UiMenuItemI *item, UiObject *obj) { UiMenuItemList *il = (UiMenuItemList*)item; @@ -521,17 +576,34 @@ ls->oldcount = 0; ls->getvalue = il->getvalue; - UiVar* var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST); + //UiVar* var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST); + UiVar* var = uic_create_var(obj->ctx, il->varname, UI_VAR_LIST); ls->var = var; - UiList *list = var->value; + if(var) { + UiList *list = var->value; + list->update = ui_menulist_update; + list->getselection = NULL; + list->setselection = NULL; + + // It is possible, that the UiVar is from a global shared context, + // used by multiple windows. To support this usecase, the list->obj + // binding object is a list of all connected UiActiveMenuItemList. + CxList *bindings = list->obj; + if(!bindings) { + bindings = cxLinkedListCreate(var->from_ctx->mp->allocator, NULL, CX_STORE_POINTERS); + list->obj = bindings; + } + cxListAdd(bindings, ls); + + // The destruction of the toplevel obj must remove the menulist binding + uic_context_add_destructor(obj->ctx, menuitem_list_remove_binding, ls); + + ui_update_gmenu_item_list(ls); + } ls->callback = il->callback; ls->userdata = il->userdata; - UiObserver *observer = ui_observer_new((ui_callback)ui_update_gmenu_item_list, ls); - list->observers = ui_obsvlist_add(list->observers, observer); - uic_list_register_observer_destructor(obj->ctx, list, observer); - GSimpleAction *action = g_simple_action_new(item->id, g_variant_type_new("i")); g_action_map_add_action(obj->ctx->action_map, G_ACTION(action)); snprintf(ls->action, 32, "win.%s", item->id); @@ -542,6 +614,7 @@ event->userdata = il->userdata; event->callback = il->callback; event->customdata = var; + event->customint = 0; event->value = 0; g_signal_connect( @@ -554,8 +627,6 @@ "destroy", G_CALLBACK(ui_destroy_userdata), event); - - ui_update_gmenu_item_list(NULL, ls); } void ui_activate_event_wrapper(GSimpleAction* self, GVariant* parameter, UiEventData *event) { @@ -569,6 +640,7 @@ evt.window = event->obj->window; evt.document = event->obj->ctx->document; evt.eventdata = event->customdata; + evt.eventdatatype = event->customint; evt.intval = intval; event->callback(&evt, event->userdata); } @@ -583,12 +655,21 @@ evt.window = event->obj->window; evt.document = event->obj->ctx->document; evt.eventdata = ui_list_get(list, index); + evt.eventdatatype = UI_EVENT_DATA_LIST_ELM; evt.intval = index; event->callback(&evt, event->userdata); } -void ui_update_gmenu_item_list(UiEvent *event, UiActiveGMenuItemList *list) { +void ui_menulist_update(UiList *list, int ignored) { + CxList *bindings = list->obj; + CxIterator i = cxListIterator(bindings); + cx_foreach(UiActiveGMenuItemList *, ls, i) { + ui_update_gmenu_item_list(ls); + } +} + +void ui_update_gmenu_item_list(UiActiveGMenuItemList *list) { // remove old items for(int i=0;i<list->oldcount;i++) { g_menu_remove(list->menu, list->index);
--- a/ui/gtk/menu.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/menu.h Sun Jul 20 22:04:39 2025 +0200 @@ -55,10 +55,10 @@ GtkMenuShell *menu; int index; int oldcount; - UiList *list; - ui_getvaluefunc getvalue; - ui_callback callback; - void *userdata; + UiVar *var; + ui_getvaluefunc getvalue; + ui_callback callback; + void *userdata; }; void ui_add_menu_items(GtkWidget *parent, int i, UiMenu *menu, UiObject *obj); @@ -72,7 +72,8 @@ void add_checkitemnv_widget(GtkWidget *p, int i, UiMenuItemI *item, UiObject *obj); void add_menuitem_list_widget(GtkWidget *p, int i, UiMenuItemI *item, UiObject *obj); -void ui_update_menuitem_list(UiEvent *event, UiActiveMenuItemList *list); +void ui_menulist_update(UiList *list, int ignored); +void ui_update_menuitem_list(UiActiveMenuItemList *list); void ui_menu_event_wrapper(GtkMenuItem *item, UiEventData *event); void ui_menu_event_toggled(GtkCheckMenuItem *ci, UiEventData *event); int64_t ui_checkitem_get(UiInteger *i); @@ -108,7 +109,8 @@ void ui_activate_event_wrapper(GSimpleAction* self, GVariant* parameter, UiEventData *event); void ui_menu_list_item_activate_event_wrapper(GSimpleAction* self, GVariant* parameter, UiEventData *event); -void ui_update_gmenu_item_list(UiEvent *event, UiActiveGMenuItemList *list); +void ui_menulist_update(UiList *list, int ignored); +void ui_update_gmenu_item_list(UiActiveGMenuItemList *list); #endif
--- a/ui/gtk/range.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/range.c Sun Jul 20 22:04:39 2025 +0200 @@ -62,6 +62,7 @@ event->callback = f; event->value = 0; event->customdata = NULL; + event->customint = 0; g_signal_connect( G_OBJECT(scrollbar), @@ -76,7 +77,7 @@ } UiContainer *ct = uic_get_current_container(obj); - ct->add(ct, scrollbar, FALSE); + ct->add(ct, scrollbar); return scrollbar; } @@ -95,6 +96,7 @@ e.window = event->obj->window; e.document = event->obj->ctx->document; e.eventdata = NULL; + e.eventdatatype = 0; e.intval = event->value; event->callback(&e, event->userdata); return TRUE;
--- a/ui/gtk/text.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/text.c Sun Jul 20 22:04:39 2025 +0200 @@ -107,13 +107,13 @@ return buf; } -UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs args) { +UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) { UiObject* current = uic_current_obj(obj); - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_TEXT); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_TEXT); GtkWidget *text_area = gtk_text_view_new(); - ui_set_name_and_style(text_area, args.name, args.style_class); - ui_set_widget_groups(obj->ctx, text_area, args.groups); + ui_set_name_and_style(text_area, args->name, args->style_class); + ui_set_widget_groups(obj->ctx, text_area, args->groups); gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text_area), GTK_WRAP_WORD_CHAR); g_signal_connect( @@ -127,8 +127,8 @@ uitext->ctx = obj->ctx; uitext->var = var; uitext->last_selection_state = 0; - uitext->onchange = args.onchange; - uitext->onchangedata = args.onchangedata; + uitext->onchange = args->onchange; + uitext->onchangedata = args->onchangedata; g_object_set_data(G_OBJECT(text_area), "ui_textarea", uitext); @@ -155,8 +155,8 @@ gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text_area), 2); // add - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, scroll_area, TRUE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, scroll_area); // bind value if(var) { @@ -330,6 +330,7 @@ e.window = e.obj->window; e.document = textarea->ctx->document; e.eventdata = value; + e.eventdatatype = UI_EVENT_DATA_TEXT_VALUE; e.intval = 0; e.set = ui_get_setop(); @@ -592,21 +593,21 @@ -static UIWIDGET create_textfield(UiObject *obj, UiBool frameless, UiBool password, UiTextFieldArgs args) { +static UIWIDGET create_textfield(UiObject *obj, UiBool frameless, UiBool password, UiTextFieldArgs *args) { GtkWidget *textfield = gtk_entry_new(); - ui_set_name_and_style(textfield, args.name, args.style_class); - ui_set_widget_groups(obj->ctx, textfield, args.groups); + ui_set_name_and_style(textfield, args->name, args->style_class); + ui_set_widget_groups(obj->ctx, textfield, args->groups); UiObject* current = uic_current_obj(obj); - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_STRING); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_STRING); UiTextField *uitext = malloc(sizeof(UiTextField)); uitext->obj = obj; uitext->var = var; - uitext->onchange = args.onchange; - uitext->onchangedata = args.onchangedata; - uitext->onactivate = args.onactivate; - uitext->onactivatedata = args.onactivatedata; + uitext->onchange = args->onchange; + uitext->onchangedata = args->onchangedata; + uitext->onactivate = args->onactivate; + uitext->onactivatedata = args->onactivatedata; g_signal_connect( textfield, @@ -614,10 +615,10 @@ G_CALLBACK(ui_textfield_destroy), uitext); - if(args.width > 0) { + if(args->width > 0) { // TODO: gtk4 #if GTK_MAJOR_VERSION <= 3 - gtk_entry_set_width_chars(GTK_ENTRY(textfield), args.width); + gtk_entry_set_width_chars(GTK_ENTRY(textfield), args->width); #endif } if(frameless) { @@ -628,8 +629,8 @@ gtk_entry_set_visibility(GTK_ENTRY(textfield), FALSE); } - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, textfield, FALSE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, textfield); if(var) { UiString *value = var->value; @@ -647,7 +648,7 @@ value->obj = GTK_ENTRY(textfield); } - if(args.onchange || var) { + if(args->onchange || var) { g_signal_connect( textfield, "changed", @@ -655,7 +656,7 @@ uitext); } - if(args.onactivate) { + if(args->onactivate) { g_signal_connect( textfield, "activate", @@ -666,15 +667,15 @@ return textfield; } -UIWIDGET ui_textfield_create(UiObject *obj, UiTextFieldArgs args) { +UIWIDGET ui_textfield_create(UiObject *obj, UiTextFieldArgs *args) { return create_textfield(obj, FALSE, FALSE, args); } -UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs args) { +UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs *args) { return create_textfield(obj, TRUE, FALSE, args); } -UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs args) { +UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs *args) { return create_textfield(obj, FALSE, TRUE, args); } @@ -691,6 +692,7 @@ e.window = e.obj->window; e.document = textfield->obj->ctx->document; e.eventdata = value; + e.eventdatatype = UI_EVENT_DATA_TEXT_VALUE; e.intval = 0; e.set = ui_get_setop(); @@ -710,6 +712,7 @@ e.window = e.obj->window; e.document = textfield->obj->ctx->document; e.eventdata = NULL; + e.eventdatatype = 0; e.intval = 0; e.set = ui_get_setop(); textfield->onactivate(&e, textfield->onactivatedata); @@ -807,6 +810,7 @@ evt.window = evt.obj->window; evt.document = evt.obj->ctx->document; evt.eventdata = elm->path; + evt.eventdatatype = UI_EVENT_DATA_STRING; evt.intval = event->value0; evt.set = ui_get_setop(); event->callback(&evt, event->userdata); @@ -888,6 +892,7 @@ evt.window = obj->window; evt.document = obj->ctx->document; evt.eventdata = (char*)text; + evt.eventdatatype = UI_EVENT_DATA_STRING; evt.intval = -1; pathtf->onactivate(&evt, pathtf->onactivatedata); } @@ -915,22 +920,22 @@ return FALSE; } -UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs args) { +UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs *args) { UiObject* current = uic_current_obj(obj); UiPathTextField *pathtf = malloc(sizeof(UiPathTextField)); memset(pathtf, 0, sizeof(UiPathTextField)); pathtf->obj = obj; - pathtf->getpathelm = args.getpathelm; - pathtf->getpathelmdata = args.getpathelmdata; - pathtf->onactivate = args.onactivate; - pathtf->onactivatedata = args.onactivatedata; - pathtf->ondragcomplete = args.ondragcomplete; - pathtf->ondragcompletedata = args.ondragcompletedata; - pathtf->ondragstart = args.ondragstart; - pathtf->ondragstartdata = args.ondragstartdata; - pathtf->ondrop = args.ondrop; - pathtf->ondropdata = args.ondropsdata; + pathtf->getpathelm = args->getpathelm; + pathtf->getpathelmdata = args->getpathelmdata; + pathtf->onactivate = args->onactivate; + pathtf->onactivatedata = args->onactivatedata; + pathtf->ondragcomplete = args->ondragcomplete; + pathtf->ondragcompletedata = args->ondragcompletedata; + pathtf->ondragstart = args->ondragstart; + pathtf->ondragstartdata = args->ondragstartdata; + pathtf->ondrop = args->ondrop; + pathtf->ondropdata = args->ondropsdata; if(!pathtf->getpathelm) { pathtf->getpathelm = default_pathelm_func; @@ -940,8 +945,8 @@ pathtf->stack = gtk_stack_new(); gtk_widget_set_name(pathtf->stack, "path-textfield-box"); - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, pathtf->stack, FALSE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, pathtf->stack); pathtf->entry_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0); pathtf->entry = gtk_entry_new(); @@ -973,7 +978,7 @@ gtk_stack_set_visible_child(GTK_STACK(pathtf->stack), pathtf->entry_box); - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_STRING); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_STRING); if (var) { UiString* value = (UiString*)var->value; value->obj = pathtf; @@ -1076,22 +1081,22 @@ return bb; } -UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs args) { +UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs *args) { UiObject* current = uic_current_obj(obj); UiPathTextField *pathtf = malloc(sizeof(UiPathTextField)); memset(pathtf, 0, sizeof(UiPathTextField)); pathtf->obj = obj; - pathtf->getpathelm = args.getpathelm; - pathtf->getpathelmdata = args.getpathelmdata; - pathtf->onactivate = args.onactivate; - pathtf->onactivatedata = args.onactivatedata; - pathtf->ondragcomplete = args.ondragcomplete; - pathtf->ondragcompletedata = args.ondragcompletedata; - pathtf->ondragstart = args.ondragstart; - pathtf->ondragstartdata = args.ondragstartdata; - pathtf->ondrop = args.ondrop; - pathtf->ondropdata = args.ondropsdata; + pathtf->getpathelm = args->getpathelm; + pathtf->getpathelmdata = args->getpathelmdata; + pathtf->onactivate = args->onactivate; + pathtf->onactivatedata = args->onactivatedata; + pathtf->ondragcomplete = args->ondragcomplete; + pathtf->ondragcompletedata = args->ondragcompletedata; + pathtf->ondragstart = args->ondragstart; + pathtf->ondragstartdata = args->ondragstartdata; + pathtf->ondrop = args->ondrop; + pathtf->ondropdata = args->ondropsdata; if(!pathtf->getpathelm) { pathtf->getpathelm = default_pathelm_func; @@ -1112,7 +1117,7 @@ G_CALLBACK(ui_path_textfield_destroy), pathtf); - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); current->container->add(current->container, eventbox, FALSE); // hbox as parent for the GtkEntry and GtkButtonBox @@ -1137,7 +1142,7 @@ G_CALLBACK(ui_path_textfield_key_press), pathtf); - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_STRING); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_STRING); if (var) { UiString* value = (UiString*)var->value; value->obj = pathtf;
--- a/ui/gtk/toolbar.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/toolbar.c Sun Jul 20 22:04:39 2025 +0200 @@ -155,6 +155,7 @@ event->callback = item->args.onclick; event->userdata = item->args.onclickdata; event->customdata = NULL; + event->customint = 0; event->value = 0; g_signal_connect( @@ -237,6 +238,7 @@ e.window = event->obj->window; e.document = event->obj->ctx->document; e.eventdata = NULL; + e.eventdatatype = 0; e.intval = gtk_toggle_tool_button_get_active(widget); if(event->callback) {
--- a/ui/gtk/toolkit.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/toolkit.c Sun Jul 20 22:04:39 2025 +0200 @@ -66,6 +66,8 @@ static int scale_factor = 1; +static UiBool exit_on_shutdown; + UIEXPORT void ui_init(const char *appname, int argc, char **argv) { application_name = appname; uic_init_global_context(); @@ -110,8 +112,11 @@ exit_data = userdata; } +void ui_app_exit_on_shutdown(UiBool exitapp) { + exit_on_shutdown = exitapp; +} -#ifndef UI_GTK2 +#ifdef UI_APPLICATION static void app_startup(GtkApplication* app, gpointer userdata) { if(startup_func) { startup_func(NULL, startup_data); @@ -119,8 +124,16 @@ } static void app_activate(GtkApplication* app, gpointer userdata) { - printf("activate\n"); + //printf("activate\n"); } + +static void app_shutdown(GtkApplication *app, gpointer userdata) { + if(exit_func) { + exit_func(NULL, exit_data); + } + ui_app_save_settings(); +} + #endif void ui_main() { @@ -130,6 +143,7 @@ application_name ? application_name : "application1"); app = UI_APPLICATION_NEW(appid.ptr); g_signal_connect (app, "startup", G_CALLBACK (app_startup), NULL); + g_signal_connect (app, "shutdown", G_CALLBACK (app_shutdown), NULL); g_signal_connect (app, "activate", G_CALLBACK (app_activate), NULL); g_application_run(G_APPLICATION (app), 0, NULL); g_object_unref (app); @@ -140,11 +154,14 @@ startup_func(NULL, startup_data); } gtk_main(); -#endif if(exit_func) { exit_func(NULL, exit_data); } - uic_store_app_properties(); + ui_app_save_settings(); +#endif + if(exit_on_shutdown) { + exit(0); + } } #ifndef UI_GTK2 @@ -191,6 +208,7 @@ event.document = job->obj->ctx->document; event.intval = 0; event.eventdata = NULL; + event.eventdatatype = 0; job->finish_callback(&event, job->finish_data); free(job);
--- a/ui/gtk/toolkit.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/toolkit.h Sun Jul 20 22:04:39 2025 +0200 @@ -131,6 +131,7 @@ ui_callback callback; void *userdata; int value; + int customint; void *customdata; } UiEventData;
--- a/ui/gtk/webview.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/webview.c Sun Jul 20 22:04:39 2025 +0200 @@ -33,14 +33,14 @@ #ifdef UI_WEBVIEW -UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs args) { +UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs *args) { UiObject* current = uic_current_obj(obj); GtkWidget *webview = webkit_web_view_new(); - ui_set_name_and_style(webview, args.name, args.style_class); + ui_set_name_and_style(webview, args->name, args->style_class); - UiVar *var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_GENERIC); + UiVar *var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_GENERIC); if(var) { WebViewData *data = malloc(sizeof(WebViewData)); memset(data, 0, sizeof(WebViewData)); @@ -59,9 +59,9 @@ } } - ui_set_widget_groups(obj->ctx, webview, args.groups); - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, webview, FALSE); + ui_set_widget_groups(obj->ctx, webview, args->groups); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, webview); return webview; } @@ -115,7 +115,14 @@ const char *mimetype, const char *encoding) { + WebViewData *data0 = g->obj; + if(!data0) { + return; + } + WebViewData data; + memset(&data, 0, sizeof(WebViewData)); + data.webview = data0->webview; data.uri = (char*)uri; data.content = (char*)content; data.contentlength = contentlength;
--- a/ui/gtk/widget.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/widget.c Sun Jul 20 22:04:39 2025 +0200 @@ -31,13 +31,13 @@ #include "../common/object.h" -UIEXPORT UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs args) { +UIEXPORT UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs *args) { UiObject* current = uic_current_obj(obj); UIWIDGET widget = create_widget(obj, args, userdata); - UI_APPLY_LAYOUT1(current, args); - current->container->add(current->container, widget, FALSE); + UI_APPLY_LAYOUT2(current, args); + current->container->add(current->container, widget); return widget; } @@ -47,7 +47,7 @@ GtkWidget *widget = gtk_separator_new(GTK_ORIENTATION_HORIZONTAL); ui_set_name_and_style(widget, args->name, args->style_class); UI_APPLY_LAYOUT1(current, (*args)); - current->container->add(current->container, widget, FALSE); + current->container->add(current->container, widget); return widget; }
--- a/ui/gtk/window.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/gtk/window.c Sun Jul 20 22:04:39 2025 +0200 @@ -102,9 +102,7 @@ #endif static UiObject* create_window(const char *title, void *window_data, UiBool sidebar, UiBool simple) { - CxMempool *mp = cxMempoolCreateSimple(256); - UiObject *obj = cxCalloc(mp->allocator, 1, sizeof(UiObject)); - obj->ref = 0; + UiObject *obj = uic_object_new_toplevel(); #ifdef UI_LIBADWAITA obj->widget = adw_application_window_new(ui_get_application()); @@ -114,8 +112,6 @@ obj->widget = gtk_window_new(GTK_WINDOW_TOPLEVEL); #endif - - obj->ctx = uic_context(obj, mp); obj->window = window_data; #if GTK_CHECK_VERSION(4, 0, 0) @@ -316,6 +312,8 @@ evt.document = evt.obj->ctx->document; evt.window = evt.obj->window; evt.eventdata = NULL; + evt.eventdatatype = 0; + evt.eventdatatype = 0; evt.intval = 0; if(!strcmp(response, "btn1")) { @@ -327,6 +325,7 @@ if(data->customdata) { GtkWidget *entry = data->customdata; evt.eventdata = (void*)ENTRY_GET_TEXT(GTK_ENTRY(entry)); + evt.eventdatatype = UI_EVENT_DATA_STRING; } if(data->callback) { @@ -334,37 +333,39 @@ } } -void ui_dialog_create(UiObject *parent, UiDialogArgs args) { - AdwDialog *dialog = adw_alert_dialog_new(args.title, args.content); +void ui_dialog_create(UiObject *parent, UiDialogArgs *args) { + AdwDialog *dialog = adw_alert_dialog_new(args->title, args->content); UiEventData *event = malloc(sizeof(UiEventData)); - event->callback = args.result; - event->userdata = args.resultdata; + event->callback = args->result; + event->userdata = args->resultdata; event->customdata = NULL; + event->customint = 0; event->value = 0; event->obj = parent; - if(args.button1_label) { - adw_alert_dialog_add_response(ADW_ALERT_DIALOG(dialog), "btn1", args.button1_label); + if(args->button1_label) { + adw_alert_dialog_add_response(ADW_ALERT_DIALOG(dialog), "btn1", args->button1_label); } - if(args.button2_label) { - adw_alert_dialog_add_response(ADW_ALERT_DIALOG(dialog), "btn2", args.button2_label); + if(args->button2_label) { + adw_alert_dialog_add_response(ADW_ALERT_DIALOG(dialog), "btn2", args->button2_label); } - if(args.closebutton_label) { - adw_alert_dialog_add_response(ADW_ALERT_DIALOG(dialog), "close", args.closebutton_label); + if(args->closebutton_label) { + adw_alert_dialog_add_response(ADW_ALERT_DIALOG(dialog), "close", args->closebutton_label); adw_alert_dialog_set_close_response(ADW_ALERT_DIALOG(dialog), "close"); } GtkWidget *entry = NULL; - if(args.input || args.password) { + if(args->input || args->password) { entry = gtk_entry_new(); - if(args.password) { + if(args->password) { gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); } - if(args.input_value) { - ENTRY_SET_TEXT(entry, args.input_value); + if(args->input_value) { + ENTRY_SET_TEXT(entry, args->input_value); } adw_alert_dialog_set_extra_child(ADW_ALERT_DIALOG(dialog), entry); event->customdata = entry; + event->customint = 0; } g_signal_connect( @@ -415,41 +416,41 @@ gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); GtkWidget *dialog_w = GTK_WIDGET(dialog); - if(args.title) { - gtk_window_set_title(GTK_WINDOW(dialog), args.title); + if(args->title) { + gtk_window_set_title(GTK_WINDOW(dialog), args->title); } - if(args.button1_label) { - gtk_dialog_add_button(dialog, args.button1_label, 1); + if(args->button1_label) { + gtk_dialog_add_button(dialog, args->button1_label, 1); } - if(args.button2_label) { - gtk_dialog_add_button(dialog, args.button2_label, 2); + if(args->button2_label) { + gtk_dialog_add_button(dialog, args->button2_label, 2); } - if(args.closebutton_label) { - gtk_dialog_add_button(dialog, args.closebutton_label, 0); + if(args->closebutton_label) { + gtk_dialog_add_button(dialog, args->closebutton_label, 0); } GtkWidget *content_area = gtk_dialog_get_content_area(dialog); - if(args.content) { - GtkWidget *label = gtk_label_new(args.content); + if(args->content) { + GtkWidget *label = gtk_label_new(args->content); BOX_ADD(content_area, label); } GtkWidget *textfield = NULL; - if(args.input || args.password) { + if(args->input || args->password) { textfield = gtk_entry_new(); - if(args.password) { + if(args->password) { gtk_entry_set_visibility(GTK_ENTRY(textfield), FALSE); } - if(args.input_value) { - ENTRY_SET_TEXT(textfield, args.input_value); + if(args->input_value) { + ENTRY_SET_TEXT(textfield, args->input_value); } BOX_ADD(content_area, textfield); } UiEventData *event = malloc(sizeof(UiEventData)); event->obj = parent; - event->callback = args.result; - event->userdata = args.resultdata; + event->callback = args->result; + event->userdata = args->resultdata; event->value = 0; event->customdata = textfield; @@ -521,6 +522,7 @@ flist.files = NULL; flist.nfiles = 0; evt.eventdata = &flist; + evt.eventdatatype = UI_EVENT_DATA_FILE_LIST; if(selection) { flist = listmodel2filelist(selection); @@ -555,6 +557,7 @@ event->callback = file_selected_callback; event->userdata = cbdata; event->customdata = NULL; + event->customint = 0; event->value = mode; event->obj = obj; @@ -746,38 +749,36 @@ -UiObject* ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs args) { +UiObject* ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) { GtkWidget *dialog = DIALOG_NEW(); - if(args.width > 0 || args.height > 0) { + if(args->width > 0 || args->height > 0) { gtk_window_set_default_size( GTK_WINDOW(dialog), - args.width, - args.height); + args->width, + args->height); } gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(parent->widget)); - if(args.modal != UI_OFF) { + if(args->modal != UI_OFF) { gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); } - CxMempool *mp = cxMempoolCreateSimple(256); - UiObject *obj = cxCalloc(mp->allocator, 1, sizeof(UiObject)); - obj->ctx = uic_context(obj, mp); + UiObject *obj = uic_object_new_toplevel(); obj->widget = dialog; obj->ref = 0; obj->destroy = ui_window_widget_destroy; nwindows++; - if(args.title != NULL) { - gtk_window_set_title(GTK_WINDOW(dialog), args.title); + if(args->title != NULL) { + gtk_window_set_title(GTK_WINDOW(dialog), args->title); } #if ! GTK_CHECK_VERSION(4, 10, 0) UiEventData *event = malloc(sizeof(UiEventData)); event->obj = obj; - event->userdata = args.onclickdata; - event->callback = args.onclick; + event->userdata = args->onclickdata; + event->callback = args->onclick; event->value = 0; event->customdata = NULL; @@ -815,44 +816,44 @@ GtkWidget *content_vbox = ui_gtk_vbox_new(0); obj->container = ui_box_container(obj, content_vbox, UI_CONTAINER_VBOX); - if(args.lbutton1 || args.lbutton2 || args.rbutton3 || args.rbutton4) { + if(args->lbutton1 || args->lbutton2 || args->rbutton3 || args->rbutton4) { #if GTK_CHECK_VERSION(3, 10, 0) - if(args.titlebar_buttons != UI_OFF) { + if(args->titlebar_buttons != UI_OFF) { GtkWidget *headerbar = gtk_header_bar_new(); gtk_window_set_titlebar(GTK_WINDOW(dialog), headerbar); - if(args.show_closebutton == UI_OFF) { + if(args->show_closebutton == UI_OFF) { HEADERBAR_SHOW_CLOSEBUTTON(headerbar, FALSE); } - if(args.lbutton1) { - GtkWidget *button = ui_create_button(obj, args.lbutton1, NULL, args.onclick, args.onclickdata, 1, args.default_button == 1); + if(args->lbutton1) { + GtkWidget *button = ui_create_button(obj, args->lbutton1, NULL, args->onclick, args->onclickdata, 1, args->default_button == 1); gtk_header_bar_pack_start(GTK_HEADER_BAR(headerbar), button); - if(args.default_button == 1) { + if(args->default_button == 1) { WIDGET_ADD_CSS_CLASS(button, "suggested-action"); DEFAULT_BUTTON(dialog, button); } } - if(args.lbutton2) { - GtkWidget *button = ui_create_button(obj, args.lbutton2, NULL, args.onclick, args.onclickdata, 2, args.default_button == 2); + if(args->lbutton2) { + GtkWidget *button = ui_create_button(obj, args->lbutton2, NULL, args->onclick, args->onclickdata, 2, args->default_button == 2); gtk_header_bar_pack_start(GTK_HEADER_BAR(headerbar), button); - if(args.default_button == 2) { + if(args->default_button == 2) { WIDGET_ADD_CSS_CLASS(button, "suggested-action"); DEFAULT_BUTTON(dialog, button); } } - if(args.rbutton4) { - GtkWidget *button = ui_create_button(obj, args.rbutton4, NULL, args.onclick, args.onclickdata, 4, args.default_button == 4); + if(args->rbutton4) { + GtkWidget *button = ui_create_button(obj, args->rbutton4, NULL, args->onclick, args->onclickdata, 4, args->default_button == 4); gtk_header_bar_pack_end(GTK_HEADER_BAR(headerbar), button); - if(args.default_button == 4) { + if(args->default_button == 4) { WIDGET_ADD_CSS_CLASS(button, "suggested-action"); DEFAULT_BUTTON(dialog, button); } } - if(args.rbutton3) { - GtkWidget *button = ui_create_button(obj, args.rbutton3, NULL, args.onclick, args.onclickdata, 3, args.default_button == 3); + if(args->rbutton3) { + GtkWidget *button = ui_create_button(obj, args->rbutton3, NULL, args->onclick, args->onclickdata, 3, args->default_button == 3); gtk_header_bar_pack_end(GTK_HEADER_BAR(headerbar), button); - if(args.default_button == 3) { + if(args->default_button == 3) { WIDGET_ADD_CSS_CLASS(button, "suggested-action"); DEFAULT_BUTTON(dialog, button); } @@ -870,18 +871,18 @@ GtkWidget *widget = ui_box_set_margin(grid, 16); gtk_grid_set_column_homogeneous(GTK_GRID(grid), TRUE); - if(args.lbutton1) { - GtkWidget *button = ui_create_button(obj, args.lbutton1, NULL, args.onclick, args.onclickdata, 1, args.default_button == 1); + if(args->lbutton1) { + GtkWidget *button = ui_create_button(obj, args->lbutton1, NULL, args->onclick, args->onclickdata, 1, args->default_button == 1); gtk_grid_attach(GTK_GRID(grid), button, 0, 0, 1, 1); - if(args.default_button == 1) { + if(args->default_button == 1) { WIDGET_ADD_CSS_CLASS(button, "suggested-action"); DEFAULT_BUTTON(dialog, button); } } - if(args.lbutton2) { - GtkWidget *button = ui_create_button(obj, args.lbutton2, NULL, args.onclick, args.onclickdata, 2, args.default_button == 2); + if(args->lbutton2) { + GtkWidget *button = ui_create_button(obj, args->lbutton2, NULL, args->onclick, args->onclickdata, 2, args->default_button == 2); gtk_grid_attach(GTK_GRID(grid), button, 1, 0, 1, 1); - if(args.default_button == 2) { + if(args->default_button == 2) { WIDGET_ADD_CSS_CLASS(button, "suggested-action"); DEFAULT_BUTTON(dialog, button); } @@ -889,18 +890,18 @@ GtkWidget *space = gtk_label_new(NULL); gtk_widget_set_hexpand(space, TRUE); gtk_grid_attach(GTK_GRID(grid), space, 2, 0, 1, 1); - if(args.rbutton3) { - GtkWidget *button = ui_create_button(obj, args.rbutton3, NULL, args.onclick, args.onclickdata, 3, args.default_button == 3); + if(args->rbutton3) { + GtkWidget *button = ui_create_button(obj, args->rbutton3, NULL, args->onclick, args->onclickdata, 3, args->default_button == 3); gtk_grid_attach(GTK_GRID(grid), button, 3, 0, 1, 1); - if(args.default_button == 3) { + if(args->default_button == 3) { WIDGET_ADD_CSS_CLASS(button, "suggested-action"); DEFAULT_BUTTON(dialog, button); } } - if(args.rbutton4) { - GtkWidget *button = ui_create_button(obj, args.rbutton4, NULL, args.onclick, args.onclickdata, 4, args.default_button == 4); + if(args->rbutton4) { + GtkWidget *button = ui_create_button(obj, args->rbutton4, NULL, args->onclick, args->onclickdata, 4, args->default_button == 4); gtk_grid_attach(GTK_GRID(grid), button, 4, 0, 1, 1); - if(args.default_button == 4) { + if(args->default_button == 4) { WIDGET_ADD_CSS_CLASS(button, "suggested-action"); DEFAULT_BUTTON(dialog, button); }
--- a/ui/motif/Makefile Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/motif/Makefile Sun Jul 20 22:04:39 2025 +0200 @@ -27,7 +27,10 @@ # $(MOTIF_OBJPRE)%.o: motif/%.c - $(CC) -o $@ -c -I../ucx $(CFLAGS) $(TK_CFLAGS) $< + $(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
--- a/ui/motif/button.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/motif/button.c Sun Jul 20 22:04:39 2025 +0200 @@ -41,7 +41,7 @@ #include <Xm/XmAll.h> -UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs args) { +UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs *args) { Arg xargs[16]; int n = 0; @@ -51,22 +51,22 @@ Widget parent = ctn->prepare(ctn, xargs, &n); XmString label = NULL; - if(args.label) { - label = XmStringCreateLocalized((char*)args.label); + if(args->label) { + label = XmStringCreateLocalized((char*)args->label); XtSetArg(xargs[n], XmNlabelString, label); n++; } - char *name = args.name ? (char*)args.name : "button"; + char *name = args->name ? (char*)args->name : "button"; Widget button = XmCreatePushButton(parent, name, xargs, n); XtManageChild(button); ctn->add(ctn, button); - ui_set_widget_groups(obj->ctx, button, args.groups); + ui_set_widget_groups(obj->ctx, button, args->groups); - if(args.onclick) { + if(args->onclick) { UiEventData *eventdata = malloc(sizeof(UiEventData)); - eventdata->callback = args.onclick; - eventdata->userdata = args.onclickdata; + eventdata->callback = args->onclick; + eventdata->userdata = args->onclickdata; eventdata->obj = obj; eventdata->value = 0; XtAddCallback( @@ -96,7 +96,7 @@ event->callback(&e, event->userdata); } -UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs args) { +UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs *args) { Arg xargs[16]; int n = 0; @@ -108,25 +108,25 @@ XtSetArg(xargs[n], XmNindicatorOn, False); n++; XmString label = NULL; - if(args.label) { - label = XmStringCreateLocalized((char*)args.label); + if(args->label) { + label = XmStringCreateLocalized((char*)args->label); XtSetArg(xargs[n], XmNlabelString, label); n++; } - char *name = args.name ? (char*)args.name : "togglebutton"; + char *name = args->name ? (char*)args->name : "togglebutton"; Widget button = XmCreateToggleButton(parent, name, xargs, n); XtManageChild(button); ctn->add(ctn, button); - ui_set_widget_groups(obj->ctx, button, args.groups); + ui_set_widget_groups(obj->ctx, button, args->groups); - ui_bind_togglebutton(obj, button, args.varname, args.value, args.onchange, args.onchangedata, args.enable_group); + ui_bind_togglebutton(obj, button, args->varname, args->value, args->onchange, args->onchangedata, args->enable_group); XmStringFree(label); return button; } -UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs args) { +UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs *args) { Arg xargs[16]; int n = 0; @@ -136,25 +136,25 @@ Widget parent = ctn->prepare(ctn, xargs, &n); XmString label = NULL; - if(args.label) { - label = XmStringCreateLocalized((char*)args.label); + if(args->label) { + label = XmStringCreateLocalized((char*)args->label); XtSetArg(xargs[n], XmNlabelString, label); n++; } - char *name = args.name ? (char*)args.name : "button"; + char *name = args->name ? (char*)args->name : "button"; Widget button = XmCreateToggleButton(parent, name, xargs, n); XtManageChild(button); ctn->add(ctn, button); - ui_set_widget_groups(obj->ctx, button, args.groups); + ui_set_widget_groups(obj->ctx, button, args->groups); - ui_bind_togglebutton(obj, button, args.varname, args.value, args.onchange, args.onchangedata, args.enable_group); + ui_bind_togglebutton(obj, button, args->varname, args->value, args->onchange, args->onchangedata, args->enable_group); XmStringFree(label); return button; } -UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs args) { +UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs *args) { return ui_checkbox_create(obj, args); } @@ -173,6 +173,7 @@ e.window = e.obj->window; e.document = e.obj->ctx->document; e.eventdata = NULL; + e.eventdatatype = 0; e.intval = XmToggleButtonGetState(w); e.set = ui_get_setop(); @@ -282,6 +283,7 @@ e.window = e.obj->window; e.document = e.obj->ctx->document; e.eventdata = value; + e.eventdatatype = UI_EVENT_DATA_INTEGER_VALUE; e.intval = v; e.set = ui_get_setop(); @@ -343,7 +345,7 @@ event); } -UIWIDGET ui_radiobutton_create(UiObject* obj, UiToggleArgs args) { +UIWIDGET ui_radiobutton_create(UiObject* obj, UiToggleArgs *args) { Arg xargs[16]; int n = 0; @@ -353,19 +355,19 @@ Widget parent = ctn->prepare(ctn, xargs, &n); XtSetArg(xargs[n], XmNindicatorType, XmONE_OF_MANY_ROUND); n++; XmString label = NULL; - if(args.label) { - label = XmStringCreateLocalized((char*)args.label); + if(args->label) { + label = XmStringCreateLocalized((char*)args->label); XtSetArg(xargs[n], XmNlabelString, label); n++; } - char *name = args.name ? (char*)args.name : "button"; + char *name = args->name ? (char*)args->name : "button"; Widget button = XmCreateToggleButton(parent, name, xargs, n); XtManageChild(button); ctn->add(ctn, button); - ui_set_widget_groups(obj->ctx, button, args.groups); + ui_set_widget_groups(obj->ctx, button, args->groups); - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_INTEGER); + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_INTEGER); if(var) { UiInteger *value = var->value; CxList *rb = value->obj; @@ -396,11 +398,11 @@ // other buttons in the radio button group UiVarEventData *event = malloc(sizeof(UiVarEventData)); event->obj = obj; - event->callback = args.onchange; - event->userdata = args.onchangedata; + event->callback = args->onchange; + event->userdata = args->onchangedata; event->observers = NULL; event->var = var; - event->value = args.enable_group; + event->value = args->enable_group; XtAddCallback( button, XmNvalueChangedCallback,
--- a/ui/motif/container.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/motif/container.c Sun Jul 20 22:04:39 2025 +0200 @@ -43,7 +43,7 @@ /* ---------------------------- Box Container ---------------------------- */ -static UIWIDGET box_create(UiObject *obj, UiContainerArgs args, UiBoxOrientation orientation) { +static UIWIDGET box_create(UiObject *obj, UiContainerArgs *args, UiBoxOrientation orientation) { UiContainerPrivate *ctn = ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args); @@ -51,13 +51,13 @@ int n = 0; if(orientation == UI_BOX_VERTICAL) { - //XtSetArg(xargs[n], gridRowSpacing, args.spacing); n++; + //XtSetArg(xargs[n], gridRowSpacing, args->spacing); n++; } else { - //XtSetArg(xargs[n], gridColumnSpacing, args.spacing); n++; + //XtSetArg(xargs[n], gridColumnSpacing, args->spacing); n++; } Widget parent = ctn->prepare(ctn, xargs, &n); - Widget grid = XtCreateManagedWidget(args.name ? args.name : "boxcontainer", gridClass, parent, xargs, n); + Widget grid = XtCreateManagedWidget(args->name ? args->name : "boxcontainer", gridClass, parent, xargs, n); ctn->add(ctn, grid); UiContainerX *container = ui_box_container(obj, grid, orientation); @@ -67,12 +67,12 @@ } // public -UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs args) { +UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs *args) { return box_create(obj, args, UI_BOX_VERTICAL); } // public -UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs args) { +UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs *args) { return box_create(obj, args, UI_BOX_HORIZONTAL); } @@ -129,7 +129,7 @@ /* ---------------------------- Grid Container ---------------------------- */ // public -UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs args) { +UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) { Arg xargs[16]; int n = 0; @@ -137,13 +137,13 @@ UI_APPLY_LAYOUT(ctn->layout, args); Widget parent = ctn->prepare(ctn, xargs, &n); - XtSetArg(xargs[n], gridMargin, args.margin); n++; - XtSetArg(xargs[n], gridColumnSpacing, args.columnspacing); n++; - XtSetArg(xargs[n], gridRowSpacing, args.rowspacing); n++; - Widget grid = XtCreateManagedWidget(args.name ? args.name : "gridcontainer", gridClass, parent, xargs, n); + XtSetArg(xargs[n], gridMargin, args->margin); n++; + XtSetArg(xargs[n], gridColumnSpacing, args->columnspacing); n++; + XtSetArg(xargs[n], gridRowSpacing, args->rowspacing); n++; + Widget grid = XtCreateManagedWidget(args->name ? args->name : "gridcontainer", gridClass, parent, xargs, n); ctn->add(ctn, grid); - UiContainerX *container = ui_grid_container(obj, grid, args.def_hexpand, args.def_vexpand, args.def_hfill, args.def_vfill); + UiContainerX *container = ui_grid_container(obj, grid, args->def_hexpand, args->def_vexpand, args->def_hfill, args->def_vfill); uic_object_push_container(obj, container); return grid; @@ -308,7 +308,7 @@ } } -UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs args) { +UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs *args) { Arg xargs[16]; int n = 0; @@ -321,7 +321,7 @@ // - content (Frame) UiMotifTabView *tabview = malloc(sizeof(UiMotifTabView)); memset(tabview, 0, sizeof(UiMotifTabView)); - char *name = args.name ? (char*)args.name : "tabview"; + char *name = args->name ? (char*)args->name : "tabview"; XtSetArg(xargs[n], XmNuserData, tabview); n++; Widget parent = ctn->prepare(ctn, xargs, &n); Widget form = XmCreateForm(parent, name, xargs, n); @@ -354,8 +354,8 @@ tabview->form = form; tabview->tabbar = tabbar; tabview->content = content; - tabview->tabview = args.tabview; - tabview->subcontainer = args.subcontainer; + tabview->tabview = args->tabview; + tabview->subcontainer = args->subcontainer; tabview->select = ui_motif_tabview_select; tabview->add = ui_motif_tabview_add_tab; tabview->remove = ui_motif_tabview_remove; @@ -369,7 +369,7 @@ ct->container.add = ui_tabview_container_add; ct->tabview = tabview; - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_INTEGER); + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_INTEGER); if(var) { UiInteger *i = var->value; i->obj = tabview; @@ -411,7 +411,7 @@ } - Widget child = ui_vbox_create(obj, (UiContainerArgs) { 0 }); + Widget child = ui_vbox_create(obj, &(UiContainerArgs) { 0 }); if(tabview->current) { XtUnmanageChild(child); } else { @@ -605,7 +605,7 @@ return (UiContainerX*)ctn; } -UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs args) { +UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs *args) { UiContainerPrivate *ctn = ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args);
--- a/ui/motif/container.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/motif/container.h Sun Jul 20 22:04:39 2025 +0200 @@ -39,14 +39,14 @@ #endif #define UI_APPLY_LAYOUT(layout, args) \ - layout.fill = args.fill; \ - layout.hexpand = args.hexpand; \ - layout.vexpand = args.vexpand; \ - layout.hfill = args.hfill; \ - layout.vfill = args.vfill; \ - layout.override_defaults = args.override_defaults; \ - layout.colspan = args.colspan; \ - layout.rowspan = args.rowspan + layout.fill = args->fill; \ + layout.hexpand = args->hexpand; \ + layout.vexpand = args->vexpand; \ + layout.hfill = args->hfill; \ + layout.vfill = args->vfill; \ + layout.override_defaults = args->override_defaults; \ + layout.colspan = args->colspan; \ + layout.rowspan = args->rowspan typedef enum UiBoxOrientation UiBoxOrientation; @@ -65,7 +65,7 @@ typedef struct UiLayout UiLayout; struct UiLayout { - UiTri fill; + UiBool fill; UiBool newline; char *label; UiBool hexpand;
--- a/ui/motif/image.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/motif/image.c Sun Jul 20 22:04:39 2025 +0200 @@ -6,3 +6,12 @@ #include "image.h" + + +void ui_image_ref(UIIMAGE img) { + // TODO +} + +void ui_image_unref(UIIMAGE img) { + // TODO +}
--- a/ui/motif/label.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/motif/label.c Sun Jul 20 22:04:39 2025 +0200 @@ -36,7 +36,7 @@ #include "Grid.h" -static UIWIDGET label_create(UiObject *obj, UiLabelArgs args, int align) { +static UIWIDGET label_create(UiObject *obj, UiLabelArgs *args, int align) { Arg xargs[16]; int n = 0; @@ -47,12 +47,12 @@ XtSetArg(xargs[n], XmNalignment, align); n++; XmString label = NULL; - if(args.label) { - label = XmStringCreateLocalized((char*)args.label); + if(args->label) { + label = XmStringCreateLocalized((char*)args->label); XtSetArg(xargs[n], XmNlabelString, label); n++; } - char *name = args.name ? (char*)args.name : "label"; + char *name = args->name ? (char*)args->name : "label"; Widget w = XmCreateLabel(parent, name, xargs, n); XtManageChild(w); ctn->add(ctn, w); @@ -61,15 +61,15 @@ return w; } -UIWIDGET ui_label_create(UiObject* obj, UiLabelArgs args) { +UIWIDGET ui_label_create(UiObject* obj, UiLabelArgs *args) { return label_create(obj, args, XmALIGNMENT_CENTER); } -UIWIDGET ui_llabel_create(UiObject* obj, UiLabelArgs args) { +UIWIDGET ui_llabel_create(UiObject* obj, UiLabelArgs *args) { return label_create(obj, args, XmALIGNMENT_BEGINNING); } -UIWIDGET ui_rlabel_create(UiObject* obj, UiLabelArgs args) { +UIWIDGET ui_rlabel_create(UiObject* obj, UiLabelArgs *args) { return label_create(obj, args, XmALIGNMENT_END); } @@ -103,7 +103,7 @@ XFillRectangle(dp, w, pb->gc, 0, 0, valueW, widget->core.height); } -UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs args) { +UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs *args) { Arg xargs[16]; int n = 0; @@ -112,7 +112,7 @@ Widget parent = ctn->prepare(ctn, xargs, &n); - char *name = args.name ? (char*)args.name : "progressbar"; + char *name = args->name ? (char*)args->name : "progressbar"; Widget frame = XmCreateFrame(parent, name, xargs, n); // create a button and get some informations about the height, shadow, highlight, .... @@ -137,12 +137,12 @@ Widget drawingArea = XmCreateDrawingArea(frame, "progressbar_drawingarea", xargs, n); XtManageChild(drawingArea); - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_DOUBLE); + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_DOUBLE); UiProgressBar *progressbarData = malloc(sizeof(UiProgressBar)); progressbarData->widget = drawingArea; - progressbarData->min = args.min; - progressbarData->max = args.max == 0 ? 100 : args.max; + progressbarData->min = args->min; + progressbarData->max = args->max == 0 ? 100 : args->max; progressbarData->value = 50; progressbarData->var = var; progressbarData->color = highlightColor; @@ -186,7 +186,7 @@ } -UIWIDGET ui_progressspinner_create(UiObject* obj, UiProgressbarSpinnerArgs args) { +UIWIDGET ui_progressspinner_create(UiObject* obj, UiProgressbarSpinnerArgs *args) { Arg xargs[16]; int n = 0; @@ -200,12 +200,12 @@ XtSetArg(xargs[n], XmNalignment, XmALIGNMENT_END); n++; XtSetArg(xargs[n], gridMinWidth, 40); n++; - char *name = args.name ? (char*)args.name : "progresss_spinner"; + char *name = args->name ? (char*)args->name : "progresss_spinner"; Widget w = XmCreateLabel(parent, name, xargs, n); XtManageChild(w); ctn->add(ctn, w); - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_INTEGER); + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_INTEGER); if(var) { UiInteger *value = var->value; value->obj = w;
--- a/ui/motif/list.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/motif/list.c Sun Jul 20 22:04:39 2025 +0200 @@ -34,36 +34,61 @@ #include "list.h" #include "../common/object.h" -UIWIDGET ui_listview_create(UiObject* obj, UiListArgs args) { +static void* getvalue_wrapper(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) { + ui_getvaluefunc getvalue = (ui_getvaluefunc)userdata; + return getvalue(elm, col); +} + +/* +static void* model_getvalue(UiModel *model, UiList *list, void *elm, int row, int col, UiBool *freeResult) { + if(model->getvalue2) { + return model->getvalue2(list, elm, row, col, model->getvalue2data, freeResult); + } else if(model->getvalue) { + return model->getvalue(elm, col); + } + return NULL; +} +*/ + +UIWIDGET ui_listview_create(UiObject* obj, UiListArgs *args) { Arg xargs[16]; int n = 0; UiContainerPrivate *ctn = ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args); - if(args.multiselection) { + if(args->multiselection) { XtSetArg(xargs[n], XmNselectionPolicy, XmEXTENDED_SELECT); n++; } else { XtSetArg(xargs[n], XmNselectionPolicy, XmSINGLE_SELECT); n++; } - char *name = args.name ? (char*)args.name : "listview"; + char *name = args->name ? (char*)args->name : "listview"; Widget parent = ctn->prepare(ctn, xargs, &n); Widget widget = XmCreateScrolledList(parent, name, xargs, n); XtManageChild(widget); - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.list, args.varname, UI_VAR_LIST); + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST); UiListView *listview = malloc(sizeof(UiListView)); memset(listview, 0, sizeof(UiListView)); listview->obj = obj; listview->widget = widget; - listview->getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue; + if(args->getvalue2) { + listview->getvalue = args->getvalue2; + listview->getvaluedata = args->getvalue2data; + } else if(args->getvalue) { + listview->getvalue = getvalue_wrapper; + listview->getvaluedata = args->getvalue; + } else { + listview->getvalue = getvalue_wrapper; + listview->getvaluedata = ui_strmodel_getvalue; + } listview->var = var; - listview->onactivate = args.onactivate; - listview->onactivatedata = args.onactivatedata; - listview->onselection = args.onselection; - listview->onselectiondata = args.onselectiondata; + listview->onactivate = args->onactivate; + listview->onactivatedata = args->onactivatedata; + listview->onselection = args->onselection; + listview->onselectiondata = args->onselectiondata; if(var) { UiList *list = var->value; @@ -109,6 +134,7 @@ event.window = obj->window; event.document = obj->ctx->document; event.eventdata = &sel; + event.eventdatatype = UI_EVENT_DATA_LIST_SELECTION; event.intval = sel.count > 0 ? sel.rows[0] : -1; callback(&event, userdata); } @@ -139,13 +165,17 @@ } } -static XmStringTable create_stringlist(UiList *list, ui_getvaluefunc getvalue, int *count) { +static XmStringTable create_stringlist(UiList *list, ui_getvaluefunc2 getvalue, void *getvaluedata, int *count) { int num = list->count(list); XmStringTable items = (XmStringTable)XtMalloc(num * sizeof(XmString)); void *data = list->first(list); for(int i=0;i<num;i++) { - char *s = getvalue(data, 0); + UiBool freevalue = FALSE; + char *s = getvalue(list, data, i, 0, getvaluedata, &freevalue); items[i] = XmStringCreateLocalized(s ? s : ""); + if(freevalue) { + free(s); + } data = list->next(list); } @@ -160,6 +190,7 @@ XmStringTable items = create_stringlist( list, listview->getvalue, + listview->getvaluedata, &count); XtVaSetValues( @@ -206,18 +237,20 @@ UiListView *listview, XmComboBoxCallbackStruct *cb) { - UiListSelection sel = { 0, NULL }; - if(cb->item_position > 0) { - sel.count = 1; - sel.rows = malloc(sizeof(int)); - sel.rows[0] = cb->item_position-1; + int index = cb->item_position; + void *elm = NULL; + if(listview->var) { + UiList *list = listview->var->value; + elm = ui_list_get(list, index); } + UiEvent event; event.obj = listview->obj; event.window = event.obj->window; event.document = event.obj->ctx->document; - event.eventdata = &sel; - event.intval = 0; + event.eventdata = elm; + event.eventdatatype = UI_EVENT_DATA_LIST_ELM; + event.intval = index; if(listview->onactivate) { listview->onactivate(&event, listview->onactivatedata); } @@ -226,30 +259,39 @@ } } -UIWIDGET ui_combobox_create(UiObject* obj, UiListArgs args) { +UIWIDGET ui_combobox_create(UiObject* obj, UiListArgs *args) { Arg xargs[16]; int n = 0; UiContainerPrivate *ctn = ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args); - char *name = args.name ? (char*)args.name : "dropdown"; + char *name = args->name ? (char*)args->name : "dropdown"; Widget parent = ctn->prepare(ctn, xargs, &n); Widget widget = XmCreateDropDownList(parent, name, xargs, n); XtManageChild(widget); - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.list, args.varname, UI_VAR_LIST); + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST); UiListView *listview = malloc(sizeof(UiListView)); memset(listview, 0, sizeof(UiListView)); listview->obj = obj; listview->widget = widget; - listview->getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue; + if(args->getvalue2) { + listview->getvalue = args->getvalue2; + listview->getvaluedata = args->getvalue2data; + } else if(args->getvalue) { + listview->getvalue = getvalue_wrapper; + listview->getvaluedata = args->getvalue; + } else { + listview->getvalue = getvalue_wrapper; + listview->getvaluedata = ui_strmodel_getvalue; + } listview->var = var; - listview->onactivate = args.onactivate; - listview->onactivatedata = args.onactivatedata; - listview->onselection = args.onselection; - listview->onselectiondata = args.onselectiondata; + listview->onactivate = args->onactivate; + listview->onactivatedata = args->onactivatedata; + listview->onselection = args->onselection; + listview->onselectiondata = args->onselectiondata; if(var) { UiList *list = var->value;
--- a/ui/motif/list.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/motif/list.h Sun Jul 20 22:04:39 2025 +0200 @@ -42,7 +42,8 @@ Widget widget; UiVar *var; UiModel* model; - ui_getvaluefunc getvalue; + ui_getvaluefunc2 getvalue; + void *getvaluedata; UiListSelection current_selection;
--- a/ui/motif/menu.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/motif/menu.c Sun Jul 20 22:04:39 2025 +0200 @@ -202,6 +202,20 @@ ui_bind_radiobutton(obj, button, NULL, it->varname, it->callback, it->userdata, 0); } +static void menuitem_list_remove_binding(void *obj) { + UiActiveMenuItemList *ls = obj; + UiList *list = ls->var->value; + CxList *bindings = list->obj; + if(bindings) { + (void)cxListFindRemove(bindings, obj); + if(cxListSize(bindings) == 0) { + cxListFree(bindings); + list->obj = NULL; + list->update = NULL; + } + } +} + void add_menuitem_list_widget(Widget p, int i, UiMenuItemI *item, UiObject *obj) { UiMenuItemList *il = (UiMenuItemList*)item; const CxAllocator *a = obj->ctx->allocator; @@ -218,17 +232,40 @@ ls->userdata = il->userdata; ls->addseparator = il->addseparator; - ls->var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST); //uic_widget_var(obj->ctx, obj->ctx, NULL, il->varname, UI_VAR_LIST); - UiList *list = ls->var->value; - - UiObserver *observer = ui_observer_new((ui_callback)ui_update_menuitem_list, ls); - list->observers = ui_obsvlist_add(list->observers, observer); - uic_list_register_observer_destructor(obj->ctx, list, observer); - - ui_update_menuitem_list(NULL, ls); + //ls->var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST); + ls->var = uic_create_var(obj->ctx, il->varname, UI_VAR_LIST); + if(ls->var) { + UiList *list = ls->var->value; + list->update = ui_menulist_update; + list->getselection = NULL; + list->setselection = NULL; + + // It is possible, that the UiVar is from a global shared context, + // used by multiple windows. To support this usecase, the list->obj + // binding object is a list of all connected UiActiveMenuItemList. + CxList *bindings = list->obj; + if(!bindings) { + bindings = cxLinkedListCreate(ls->var->from_ctx->mp->allocator, NULL, CX_STORE_POINTERS); + list->obj = bindings; + } + cxListAdd(bindings, ls); + + // The destruction of the toplevel obj must remove the menulist binding + uic_context_add_destructor(obj->ctx, menuitem_list_remove_binding, ls); + + ui_update_menuitem_list(ls); + } } -void ui_update_menuitem_list(UiEvent *event, UiActiveMenuItemList *list) { +void ui_menulist_update(UiList *list, int ignored) { + CxList *bindings = list->obj; + CxIterator i = cxListIterator(bindings); + cx_foreach(UiActiveMenuItemList *, ls, i) { + ui_update_menuitem_list(ls); + } +} + +void ui_update_menuitem_list(UiActiveMenuItemList *list) { XmString s = NULL; Arg args[4]; int n;
--- a/ui/motif/menu.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/motif/menu.h Sun Jul 20 22:04:39 2025 +0200 @@ -64,7 +64,8 @@ void add_checkitemnv_widget(Widget p, int i, UiMenuItemI *item, UiObject *obj); void add_menuitem_list_widget(Widget p, int i, UiMenuItemI *item, UiObject *obj); -void ui_update_menuitem_list(UiEvent *event, UiActiveMenuItemList *list); +void ui_menulist_update(UiList *list, int ignored); +void ui_update_menuitem_list(UiActiveMenuItemList *list); #ifdef __cplusplus }
--- a/ui/motif/text.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/motif/text.c Sun Jul 20 22:04:39 2025 +0200 @@ -38,7 +38,7 @@ /* ------------------------------ Text Area ------------------------------ */ -UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs args) { +UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) { Arg xargs[16]; int n = 0; @@ -48,12 +48,12 @@ UI_APPLY_LAYOUT(ctn->layout, args); Widget parent = ctn->prepare(ctn, xargs, &n); - char *name = args.name ? (char*)args.name : "textarea"; + char *name = args->name ? (char*)args->name : "textarea"; XtSetArg(xargs[n], XmNwidth, 100); n++; Widget widget = XmCreateScrolledText(parent, name, xargs, n); XtManageChild(widget); - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_TEXT); + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_TEXT); UiTextArea *textarea = malloc(sizeof(UiTextArea)); memset(textarea, 0, sizeof(UiTextArea)); @@ -68,6 +68,9 @@ value->value.ptr = NULL; } + value->save = ui_textarea_save; + value->restore = ui_textarea_restore; + value->destroy = ui_textarea_text_destroy; value->set = ui_textarea_set; value->get = ui_textarea_get; value->getsubstr = ui_textarea_getsubstr; @@ -79,8 +82,8 @@ value->value.ptr = NULL; value->obj = widget; - if(!value->undomgr) { - value->undomgr = ui_create_undomgr(); + if(!value->data2) { + value->data2 = ui_create_undomgr(); } XtAddCallback( @@ -103,6 +106,25 @@ return str; } +void ui_textarea_save(UiText *text) { + (void)ui_textarea_get(text); +} + +void ui_textarea_restore(UiText *text) { + if(text->value.ptr) { + ui_textarea_set(text, text->value.ptr); + } +} + +void ui_textarea_text_destroy(UiText *text) { + if(text->value.free) { + text->value.free(text->value.ptr); + } + if(text->data2) { + ui_destroy_undomgr(text->data2); + } +} + void ui_textarea_set(UiText *text, const char *str) { XmTextSetString(text->obj, (char*)str); if(text->value.ptr) { @@ -201,13 +223,13 @@ // TODO: bug, fix return; } - if(!value->undomgr) { - value->undomgr = ui_create_undomgr(); + if(!value->data2) { + value->data2 = ui_create_undomgr(); } XmTextVerifyCallbackStruct *txv = (XmTextVerifyCallbackStruct*)data; int type = txv->text->length > 0 ? UI_TEXTBUF_INSERT : UI_TEXTBUF_DELETE; - UiUndoMgr *mgr = value->undomgr; + UiUndoMgr *mgr = value->data2; if(!mgr->event) { return; } @@ -307,7 +329,7 @@ void ui_text_undo(UiText *value) { - UiUndoMgr *mgr = value->undomgr; + UiUndoMgr *mgr = value->data2; if(mgr->cur) { UiTextBufOp *op = mgr->cur; @@ -328,7 +350,7 @@ } void ui_text_redo(UiText *value) { - UiUndoMgr *mgr = value->undomgr; + UiUndoMgr *mgr = value->data2; UiTextBufOp *elm = NULL; if(mgr->cur) { @@ -361,7 +383,7 @@ /* ------------------------------ Text Field ------------------------------ */ -static UIWIDGET create_textfield(UiObject *obj, UiTextFieldArgs args, int frameless, int password) { +static UIWIDGET create_textfield(UiObject *obj, UiTextFieldArgs *args, int frameless, int password) { Arg xargs[16]; int n = 0; @@ -377,13 +399,13 @@ UI_APPLY_LAYOUT(ctn->layout, args); Widget parent = ctn->prepare(ctn, xargs, &n); - char *name = args.name ? (char*)args.name : "textfield"; + char *name = args->name ? (char*)args->name : "textfield"; Widget textfield = XmCreateTextField(parent, name, xargs, n); XtManageChild(textfield); - ui_set_widget_groups(obj->ctx, textfield, args.groups); + ui_set_widget_groups(obj->ctx, textfield, args->groups); - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_STRING); + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_STRING); if(var) { UiString *value = (UiString*)var->value; value->obj = textfield; @@ -398,20 +420,22 @@ return textfield; } -UIWIDGET ui_textfield_create(UiObject *obj, UiTextFieldArgs args) { +UIWIDGET ui_textfield_create(UiObject *obj, UiTextFieldArgs *args) { return create_textfield(obj, args, FALSE, FALSE); } -UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs args) { +UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs *args) { return create_textfield(obj, args, TRUE, FALSE); } -UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs args) { +UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs *args) { return create_textfield(obj, args, FALSE, FALSE); } char* ui_textfield_get(UiString *str) { - str->value.free(str->value.ptr); + if(str->value.free) { + str->value.free(str->value.ptr); + } char *value = XmTextFieldGetString(str->obj); str->value.ptr = value; str->value.free = (ui_freefunc)XtFree; @@ -420,8 +444,10 @@ void ui_textfield_set(UiString *str, const char *value) { XmTextFieldSetString(str->obj, (void*)value); + if(str->value.free) { + str->value.free(str->value.ptr); + } str->value.ptr = NULL; - str->value.free(str->value.ptr); } @@ -935,11 +961,12 @@ evt.window = evt.obj->window; evt.document = evt.obj->ctx->document; evt.eventdata = path; + evt.eventdatatype = UI_EVENT_DATA_STRING; evt.intval = index; event->callback(&evt, event->userdata); } -UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs args) { +UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs *args) { Arg xargs[16]; int n = 0; @@ -951,18 +978,18 @@ PathBar *pathbar = CreatePathBar(parent, xargs, n); - if(!args.getpathelm) { + if(!args->getpathelm) { pathbar->getpathelm= default_pathelm_func; } else { - pathbar->getpathelm = args.getpathelm; - pathbar->getpathelmdata = args.getpathelmdata; + pathbar->getpathelm = args->getpathelm; + pathbar->getpathelmdata = args->getpathelmdata; } XtManageChild(pathbar->widget); ctn->add(ctn, pathbar->widget); - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_STRING); + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_STRING); if (var) { UiString* value = (UiString*)var->value; value->obj = pathbar; @@ -976,10 +1003,10 @@ } } - if(args.onactivate) { + if(args->onactivate) { UiEventData *eventdata = malloc(sizeof(UiEventData)); - eventdata->callback = args.onactivate; - eventdata->userdata = args.onactivatedata; + eventdata->callback = args->onactivate; + eventdata->userdata = args->onactivatedata; eventdata->obj = obj; eventdata->value = 0;
--- a/ui/motif/text.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/motif/text.h Sun Jul 20 22:04:39 2025 +0200 @@ -64,6 +64,9 @@ int last_selection_state; } UiTextArea; +void ui_textarea_save(UiText *text); +void ui_textarea_restore(UiText *text); +void ui_textarea_text_destroy(UiText *text); char* ui_textarea_get(UiText *text); void ui_textarea_set(UiText *text, const char *str); char* ui_textarea_getsubstr(UiText *text, int begin, int end);
--- a/ui/motif/toolkit.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/motif/toolkit.c Sun Jul 20 22:04:39 2025 +0200 @@ -52,17 +52,18 @@ static ui_callback startup_func; static void *startup_data; static ui_callback open_func; -void *open_data; +static void *open_data; static ui_callback exit_func; -void *exit_data; +static void *exit_data; static ui_callback appclose_fnc; static void *appclose_udata; static int is_toplevel_realized = 0; -int event_pipe[2]; +static int event_pipe[2]; +static UiBool exit_on_shutdown; static String fallback[] = { //"*fontList: -dt-interface system-medium-r-normal-s*utf*:", @@ -139,6 +140,10 @@ exit_data = userdata; } +void ui_app_exit_on_shutdown(UiBool exitapp) { + exit_on_shutdown = exitapp; +} + void ui_main() { if(startup_func) { startup_func(NULL, startup_data); @@ -148,6 +153,9 @@ exit_func(NULL, exit_data); } uic_store_app_properties(); + if(exit_on_shutdown) { + exit(0); + } } void ui_exit_mainloop() { @@ -202,6 +210,7 @@ event.document = job->obj->ctx->document; event.intval = 0; event.eventdata = NULL; + event.eventdatatype = 0; job->finish_callback(&event, job->finish_data); } free(job);
--- a/ui/motif/tree.c Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,328 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2014 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 <string.h> -#include <inttypes.h> - -#include "tree.h" - -#include "container.h" -#include "../common/object.h" -#include "../common/context.h" -#include <cx/utils.h> -#include <cx/compare.h> -#include <cx/printf.h> - -UIWIDGET ui_table_var(UiObject *obj, UiVar *var, UiModel *model, UiListCallbacks cb) { - // TODO: check if modelinfo is complete - - Arg args[32]; - int n = 0; - - // create scrolled window - UiContainer *ct = uic_get_current_container(obj); - Widget parent = ct->prepare(ct, args, &n, TRUE); - - XtSetArg(args[n], XmNscrollingPolicy, XmAUTOMATIC); - n++; - XtSetArg(args[n], XmNshadowThickness, 0); - n++; - Widget scrollw = XmCreateScrolledWindow(parent, "scroll_win", args, n); - ct->add(ct, scrollw); - XtManageChild(scrollw); - - // create table headers - XmStringTable header = (XmStringTable)XtMalloc( - model->columns * sizeof(XmString)); - for(int i=0;i<model->columns;i++) { - header[i] = XmStringCreateLocalized(model->titles[i]); - } - n = 0; - XtSetArg(args[n], XmNdetailColumnHeading, header); - n++; - XtSetArg(args[n], XmNdetailColumnHeadingCount, model->columns); - n++; - - // set res - XtSetArg(args[n], XmNlayoutType, XmDETAIL); - n++; - XtSetArg(args[n], XmNentryViewType, XmSMALL_ICON); - n++; - XtSetArg(args[n], XmNselectionPolicy, XmSINGLE_SELECT); - n++; - XtSetArg(args[n], XmNwidth, 600); - n++; - - // create widget - //UiContainer *ct = uic_get_current_container(obj); - //Widget parent = ct->add(ct, args, &n); - - Widget container = XmCreateContainer(scrollw, "table", args, n); - XtManageChild(container); - - // add callbacks - UiTreeEventData *event = ui_malloc(obj->ctx, sizeof(UiTreeEventData)); - event->obj = obj; - event->activate = cb.activate; - event->selection = cb.selection; - event->userdata = cb.userdata; - event->last_selection = NULL; - if(cb.selection) { - XtAddCallback( - container, - XmNselectionCallback, - (XtCallbackProc)ui_table_select_callback, - event); - } - if(cb.activate) { - XtAddCallback( - container, - XmNdefaultActionCallback, - (XtCallbackProc)ui_table_action_callback, - event); - } - - // add initial data - UiList *list = var->value; - void *data = list->first(list); - int width = 0; - while(data) { - int w = ui_add_icon_gadget(container, model, data); - if(w > width) { - width = w; - } - data = list->next(list); - } - - UiTableView *tableview = cxMalloc(obj->ctx->allocator, sizeof(UiTableView)); - tableview->widget = container; - tableview->var = var; - tableview->model = model; - - // set new XmContainer width - XtVaSetValues(container, XmNwidth, width, NULL); - - // cleanup - for(int i=0;i<model->columns;i++) { - XmStringFree(header[i]); - } - XtFree((char*)header); - - return scrollw; -} - -UIWIDGET ui_table(UiObject *obj, UiList *data, UiModel *model, UiListCallbacks cb) { - UiVar *var = malloc(sizeof(UiVar)); - var->value = data; - var->type = UI_VAR_SPECIAL; - return ui_table_var(obj, var, model, cb); -} - -void ui_table_update(UiEvent *event, UiTableView *view) { - // clear container - Widget *children; - int nc; - - XtVaGetValues( - view->widget, - XmNchildren, - &children, - XmNnumChildren, - &nc, - NULL); - - for(int i=0;i<nc;i++) { - XtDestroyWidget(children[i]); - } - - UiList *list = view->var->value; - - void *data = list->first(list); - int width = 0; - while(data) { - int w = ui_add_icon_gadget(view->widget, view->model, data); - if(w > width) { - width = w; - } - data = list->next(list); - } - -} - -#define UI_COL_CHAR_WIDTH 12 - -int ui_add_icon_gadget(Widget container, UiModel *model, void *data) { - int width = 50; - - if(model->columns == 0) { - return width; - } - - XmString label = NULL; - Arg args[8]; - Boolean f; - // first column - if(model->types[0] != 12345678) { // TODO: icon/label type - char *str = ui_type_to_string( - model->types[0], - model->getvalue(data, 0), - &f); - - // column width - width += strlen(str) * UI_COL_CHAR_WIDTH; - - - XmString label = XmStringCreateLocalized(str); - XtSetArg(args[0], XmNlabelString, label); - if(f) { - free(str); - } - } else { - // TODO - } - - // remaining columns are the icon gadget details - XmStringTable details = (XmStringTable)XtMalloc( - (model->columns - 1) * sizeof(XmString)); - for(int i=1;i<model->columns;i++) { - char *str = ui_type_to_string( - model->types[i], - model->getvalue(data, i), - &f); - - // column width - width += strlen(str) * UI_COL_CHAR_WIDTH; - - details[i - 1] = XmStringCreateLocalized(str); - if(f) { - free(str); - } - } - XtSetArg(args[1], XmNdetail, details); - XtSetArg(args[2], XmNdetailCount, model->columns - 1); - XtSetArg(args[3], XmNshadowThickness, 0); - // create widget - Widget item = XmCreateIconGadget(container, "table_item", args, 4); - XtManageChild(item); - - // cleanup - XmStringFree(label); - for(int i=0;i<model->columns-1;i++) { - XmStringFree(details[i]); - } - XtFree((char*)details); - - return width; -} - -char* ui_type_to_string(UiModelType type, void *data, Boolean *free) { - switch(type) { - case UI_STRING: *free = FALSE; return data; - case UI_INTEGER: { - *free = TRUE; - int *val = data; - cxmutstr str = cx_asprintf("%d", *val); - return str.ptr; - } - case UI_ICON: break; // TODO - case UI_ICON_TEXT: break; // TODO - } - *free = FALSE; - return NULL; -} - -void ui_table_action_callback( - Widget widget, - UiTreeEventData *event, - XmContainerSelectCallbackStruct *sel) -{ - UiListSelection *selection = ui_list_selection(sel); - - UiEvent e; - e.obj = event->obj; - e.window = event->obj->window; - e.document = event->obj->ctx->document; - e.eventdata = selection; - e.intval = selection->count > 0 ? selection->rows[0] : -1; - event->activate(&e, event->userdata); - - free(event->last_selection->rows); - free(event->last_selection); - event->last_selection = selection; -} - -void ui_table_select_callback( - Widget widget, - UiTreeEventData *event, - XmContainerSelectCallbackStruct *sel) -{ - UiListSelection *selection = ui_list_selection(sel); - if(!ui_compare_list_selection(selection, event->last_selection)) { - UiEvent e; - e.obj = event->obj; - e.window = event->obj->window; - e.document = event->obj->ctx->document; - e.eventdata = selection; - e.intval = selection->count > 0 ? selection->rows[0] : -1; - event->selection(&e, event->userdata); - } - if(event->last_selection) { - free(event->last_selection->rows); - free(event->last_selection); - } - event->last_selection = selection; -} - -UiListSelection* ui_list_selection(XmContainerSelectCallbackStruct *xs) { - UiListSelection *selection = malloc(sizeof(UiListSelection)); - selection->count = xs->selected_item_count; - selection->rows = calloc(selection->count, sizeof(int)); - for(int i=0;i<selection->count;i++) { - int index; - XtVaGetValues(xs->selected_items[i], XmNpositionIndex, &index, NULL); - selection->rows[i] = index; - } - return selection; -} - -Boolean ui_compare_list_selection(UiListSelection *s1, UiListSelection *s2) { - if(!s1 || !s2) { - return FALSE; - } - if(s1->count != s2->count) { - return FALSE; - } - for(int i=0;i<s1->count;i++) { - if(s1->rows[i] != s2->rows[i]) { - return FALSE; - } - } - return TRUE; -}
--- a/ui/motif/tree.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,76 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2014 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 TREE_H -#define TREE_H - -#include "../ui/tree.h" -#include "../common/context.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct UiTreeEventData { - UiObject *obj; - ui_callback activate; - ui_callback selection; - void *userdata; - UiListSelection *last_selection; -} UiTreeEventData; - -typedef struct UiTableView { - Widget widget; - UiVar *var; - UiModel *model; -} UiTableView; - -void ui_table_update(UiEvent *event, UiTableView *view); -int ui_add_icon_gadget(Widget container, UiModel *model, void *data); -char* ui_type_to_string(UiModelType type, void *data, Boolean *free); - -void ui_table_action_callback( - Widget widget, - UiTreeEventData *event, - XmContainerSelectCallbackStruct *sel); -void ui_table_select_callback( - Widget widget, - UiTreeEventData *event, - XmContainerSelectCallbackStruct *sel); - -UiListSelection* ui_list_selection(XmContainerSelectCallbackStruct *xs); - -Boolean ui_compare_list_selection(UiListSelection *s1, UiListSelection *s2); - - -#ifdef __cplusplus -} -#endif - -#endif /* TREE_H */ -
--- a/ui/motif/widget.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/motif/widget.c Sun Jul 20 22:04:39 2025 +0200 @@ -37,7 +37,7 @@ #include "../common/object.h" -UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs args) { +UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs *args) { Arg xargs[64]; int n = 0; @@ -56,12 +56,11 @@ UIEXPORT UIWIDGET ui_separator_create(UiObject *obj, UiWidgetArgs *args) { Arg xargs[64]; int n = 0; - UiWidgetArgs a = *args; UiContainerPrivate *ctn = ui_obj_container(obj); - UI_APPLY_LAYOUT(ctn->layout, a); + UI_APPLY_LAYOUT(ctn->layout, args); - char *name = a.name ? (char*)a.name : "separator"; + char *name = args->name ? (char*)args->name : "separator"; Widget parent = ctn->prepare(ctn, xargs, &n); Widget widget = XmCreateSeparator(parent, name, xargs, n); XtManageChild(widget); @@ -69,3 +68,11 @@ return widget; } + +void ui_widget_set_size(UIWIDGET w, int width, int height) { + +} + +void ui_widget_redraw(UIWIDGET w) { + +}
--- a/ui/motif/window.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/motif/window.c Sun Jul 20 22:04:39 2025 +0200 @@ -70,8 +70,7 @@ static UiObject* create_window(const char *title, void *window_data, Boolean simple) { CxMempool *mp = cxMempoolCreateSimple(256); const CxAllocator *a = mp->allocator; - UiObject *obj = cxCalloc(a, 1, sizeof(UiObject)); - obj->ctx = uic_context(obj, mp); + UiObject *obj = uic_object_new_toplevel(); obj->window = window_data; obj->destroy = ui_window_widget_destroy;
--- a/ui/qt/Makefile Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/qt/Makefile Sun Jul 20 22:04:39 2025 +0200 @@ -37,5 +37,9 @@ $(MAKE) -f $(QT_MAKEFILE) $(AR) $(ARFLAGS) $(UI_LIB) $(OBJ) +$(UI_SHLIB): $(OBJ) + $(MAKE) -f $(QT_MAKEFILE) + $(CXX) -o $(UI_SHLIB) $(LDFLAGS) $(SHLIB_LDFLAGS) $(TK_LDFLAGS) $(OBJ) -L../build/lib -lucx + FORCE:
--- a/ui/qt/button.cpp Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/qt/button.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2015 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: @@ -30,20 +30,20 @@ #include "container.h" #include "toolkit.h" -UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs args) { +UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs *args) { UiContainerPrivate *ctn = ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args); - QString str = QString::fromUtf8(args.label); + QString str = QString::fromUtf8(args->label); QPushButton *button = new QPushButton(str); - if(args.onclick) { - UiEventWrapper *event = new UiEventWrapper(obj, args.onclick, args.onclickdata); + if(args->onclick) { + UiEventWrapper *event = new UiEventWrapper(obj, args->onclick, args->onclickdata); button->connect(button, SIGNAL(clicked()), event, SLOT(slot())); button->connect(button, SIGNAL(destroyed()), event, SLOT(destroy())); } - ctn->add(button, false); + ctn->add(button); return button; } @@ -53,21 +53,22 @@ event->intval = button->isChecked(); if(wrapper->var) { event->eventdata = wrapper->var->value; + event->eventdatatype = UI_EVENT_DATA_INTEGER_VALUE; } } -UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs args) { +UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs *args) { UiContainerPrivate *ctn = ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args); - QString str = QString::fromUtf8(args.label); + QString str = QString::fromUtf8(args->label); QPushButton *button = new QPushButton(str); button->setCheckable(true); - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_INTEGER); + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_INTEGER); - if(args.onchange) { - UiEventWrapper *event = new UiEventWrapper(obj, args.onchange, args.onchangedata); + if(args->onchange) { + UiEventWrapper *event = new UiEventWrapper(obj, args->onchange, args->onchangedata); event->var = var; event->customdata1 = button; event->prepare_event = togglebutton_event; @@ -87,7 +88,7 @@ i->set = ui_togglebutton_set; } - ctn->add(button, false); + ctn->add(button); return button; } @@ -111,21 +112,22 @@ event->intval = button->isChecked(); if(wrapper->var) { event->eventdata = wrapper->var->value; + event->eventdatatype = UI_EVENT_DATA_INTEGER_VALUE; } } -UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs args) { +UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs *args) { UiContainerPrivate *ctn = ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args); - QString str = QString::fromUtf8(args.label); + QString str = QString::fromUtf8(args->label); QCheckBox *checkbox = new QCheckBox(str); - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_INTEGER); + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_INTEGER); - if(args.onchange) { - UiEventWrapper *event = new UiEventWrapper(obj, args.onchange, args.onchangedata); + if(args->onchange) { + UiEventWrapper *event = new UiEventWrapper(obj, args->onchange, args->onchangedata); event->var = var; event->customdata1 = checkbox; event->prepare_event = checkbox_event; @@ -145,7 +147,7 @@ i->set = ui_checkbox_set; } - ctn->add(checkbox, false); + ctn->add(checkbox); return checkbox; } @@ -167,21 +169,22 @@ static void radiobutton_event(UiEvent *event, UiEventWrapper *wrapper) { if(wrapper->var) { - UiInteger *value = wrapper->var->value; + UiInteger *value = (UiInteger*)wrapper->var->value; event->eventdata = value; - event->intval = ui_get(value); + event->eventdatatype = UI_EVENT_DATA_INTEGER_VALUE; + event->intval = value->get(value); } } -UIWIDGET ui_radiobutton_create(UiObject *obj, UiToggleArgs args) { +UIWIDGET ui_radiobutton_create(UiObject *obj, UiToggleArgs *args) { UiContainerPrivate *ctn = ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args); - QString str = QString::fromUtf8(args.label); + QString str = QString::fromUtf8(args->label); QRadioButton *button = new QRadioButton(str); button->setAutoExclusive(false); - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_INTEGER); + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_INTEGER); if(var) { UiInteger *value = (UiInteger*)var->value; QButtonGroup *buttonGroup = (QButtonGroup*)value->obj; @@ -198,14 +201,14 @@ value->set = ui_radiobutton_set; } - UiEventWrapper *event = new UiEventWrapper(obj, args.onchange, args.onchangedata); + UiEventWrapper *event = new UiEventWrapper(obj, args->onchange, args->onchangedata); event->var = var; event->customdata1 = button; event->prepare_event = togglebutton_event; button->connect(button, SIGNAL(clicked()), event, SLOT(slot())); button->connect(button, SIGNAL(destroyed()), event, SLOT(destroy())); - ctn->add(button, false); + ctn->add(button); return button; }
--- a/ui/qt/button.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/qt/button.h Sun Jul 20 22:04:39 2025 +0200 @@ -1,7 +1,7 @@ /* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * - * Copyright 2015 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:
--- a/ui/qt/container.cpp Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/qt/container.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -60,17 +60,14 @@ ui_reset_layout(layout); } -void UiBoxContainer::add(QWidget* widget, bool fill) { - if(layout.fill != UI_LAYOUT_UNDEFINED) { - fill = ui_lb2bool(layout.fill); - } - +void UiBoxContainer::add(QWidget* widget) { + bool fill = layout.fill; if(hasStretchedWidget && fill) { fill = false; fprintf(stderr, "UiError: container has 2 filled widgets"); } - box->addWidget(widget, fill); + box->addWidget(widget); if(!hasStretchedWidget) { QSpacerItem *newspace = new QSpacerItem(0, 0, QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); @@ -86,25 +83,25 @@ current = widget; } -UIWIDGET ui_box(UiObject *obj, UiContainerArgs args, QBoxLayout::Direction dir) { +UIWIDGET ui_box(UiObject *obj, UiContainerArgs *args, QBoxLayout::Direction dir) { UiContainerPrivate *ctn = (UiContainerPrivate*)ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args); QWidget *widget = new QWidget(); QBoxLayout *box = new QBoxLayout(dir); widget->setLayout(box); - ctn->add(widget, true); + ctn->add(widget); ui_container_add(obj, new UiBoxContainer(box)); return widget; } -UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs args) { +UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs *args) { return ui_box(obj, args, QBoxLayout::TopToBottom); } -UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs args) { +UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs *args) { return ui_box(obj, args, QBoxLayout::LeftToRight); } @@ -133,16 +130,17 @@ ui_reset_layout(layout); } -void UiGridContainer::add(QWidget* widget, bool fill) { +void UiGridContainer::add(QWidget* widget) { if(layout.newline) { x = 0; y++; } - int hexpand = false; - int vexpand = false; - int hfill = false; - int vfill = false; + bool fill = layout.fill; + bool hexpand = false; + bool vexpand = false; + bool hfill = false; + bool vfill = false; if(!layout.override_defaults) { if(def_hexpand) { hexpand = true; @@ -158,9 +156,6 @@ } } - if(layout.fill != UI_LAYOUT_UNDEFINED) { - fill = ui_lb2bool(layout.fill); - } if(layout.hexpand) { hexpand = true; //hfill = true; @@ -233,24 +228,24 @@ } } -UIEXPORT UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs args) { +UIEXPORT UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) { UiContainerPrivate *ctn = (UiContainerPrivate*)ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args); QWidget *widget = new QWidget(); QGridLayout *grid = new QGridLayout(); widget->setLayout(grid); - ctn->add(widget, true); + ctn->add(widget); ui_container_add(obj, new UiGridContainer( grid, - args.margin, - args.columnspacing, - args.rowspacing, - args.def_hexpand, - args.def_vexpand, - args.def_hfill, - args.def_vfill)); + args->margin, + args->columnspacing, + args->rowspacing, + args->def_hexpand, + args->def_vexpand, + args->def_hfill, + args->def_vfill)); return widget; }
--- a/ui/qt/container.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/qt/container.h Sun Jul 20 22:04:39 2025 +0200 @@ -41,14 +41,14 @@ #include <QSplitter> #define UI_APPLY_LAYOUT(layout, args) \ - layout.fill = args.fill; \ - layout.hexpand = args.hexpand; \ - layout.vexpand = args.vexpand; \ - layout.hfill = args.hfill; \ - layout.vfill = args.vfill; \ - layout.override_defaults = args.override_defaults; \ - layout.colspan = args.colspan; \ - layout.rowspan = args.rowspan + layout.fill = args->fill; \ + layout.hexpand = args->hexpand; \ + layout.vexpand = args->vexpand; \ + layout.hfill = args->hfill; \ + layout.vfill = args->vfill; \ + layout.override_defaults = args->override_defaults; \ + layout.colspan = args->colspan; \ + layout.rowspan = args->rowspan #define ui_reset_layout(layout) memset(&(layout), 0, sizeof(UiLayout)) #define ui_lb2bool(b) ((b) == UI_LAYOUT_TRUE ? TRUE : FALSE) @@ -64,7 +64,7 @@ typedef struct UiLayout UiLayout; struct UiLayout { - UiTri fill; + UiBool fill; UiBool newline; char *label; UiBool hexpand; @@ -81,7 +81,7 @@ UiLayout layout; UIWIDGET current; - virtual void add(QWidget *widget, bool fill) = 0; + virtual void add(QWidget *widget) = 0; virtual void end() {} }; @@ -93,7 +93,7 @@ UiBoxContainer(QBoxLayout *box); - virtual void add(QWidget *widget, bool fill); + virtual void add(QWidget *widget); }; class UiGridContainer : public UiContainerPrivate { @@ -120,7 +120,7 @@ bool def_hfill, bool def_vfill); - virtual void add(QWidget *widget, bool fill); + virtual void add(QWidget *widget); virtual void end(); };
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/qt/entry.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,180 @@ +/* + * 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 "entry.h" + +#include "container.h" +#include "../common/context.h" + +#include <QDoubleSpinBox> +#include <QSpinBox> + + + +UIWIDGET ui_spinner_create(UiObject *obj, UiSpinnerArgs *args) { + UiContainerPrivate *ctn = ui_obj_container(obj); + UI_APPLY_LAYOUT(ctn->layout, args); + + bool use_double = false; + UiVar *var = NULL; + if(args->varname) { + var = uic_get_var(obj->ctx, args->varname); + if(var->type == UI_VAR_DOUBLE) { + use_double = true; + } else if(var->type == UI_VAR_RANGE) { + use_double = true; + } else if(var->type != UI_VAR_INTEGER) { + var = NULL; + fprintf(stderr, "UI Error: var '%s' has wrong type (must be int/double/range)\n", args->varname); + } + } + + if(!var) { + if(args->intvalue) { + var = uic_widget_var(obj->ctx, obj->ctx, args->intvalue, NULL, UI_VAR_INTEGER); + } else if(args->doublevalue) { + var = uic_widget_var(obj->ctx, obj->ctx, args->doublevalue, NULL, UI_VAR_DOUBLE); + use_double = true; + } else if(args->rangevalue) { + var = uic_widget_var(obj->ctx, obj->ctx, args->rangevalue, NULL, UI_VAR_RANGE); + use_double = true; + } else { + if(args->digits > 0) { + use_double = true; + } + } + } + + QAbstractSpinBox *widget = nullptr; + if(use_double) { + QDoubleSpinBox *spinbox = new QDoubleSpinBox(); + spinbox->setDecimals(args->digits); + if(args->step != 0) { + spinbox->setSingleStep(args->step); + } + widget = spinbox; + } else { + QSpinBox *spinbox = new QSpinBox(); + if(args->step != 0) { + spinbox->setSingleStep(args->step); + } + widget = spinbox; + } + + if(var) { + if(var->type == UI_VAR_INTEGER) { + UiInteger *value = (UiInteger*)var->value; + value->obj = widget; + if(value->value != 0) { + QSpinBox *spinbox = (QSpinBox*)widget; + spinbox->setValue(value->value); + } + value->get = ui_spinbox_int_get; + value->set = ui_spinbox_int_set; + } else if(var->type == UI_VAR_DOUBLE) { + UiDouble *value = (UiDouble*)var->value; + value->obj = widget; + if(value->value != 0) { + QDoubleSpinBox *spinbox = (QDoubleSpinBox*)widget; + spinbox->setValue(value->value); + } + value->get = ui_spinbox_double_get; + value->set = ui_spinbox_double_set; + } else if(var->type == UI_VAR_RANGE) { + UiRange *value = (UiRange*)var->value; + value->obj = widget; + QDoubleSpinBox *spinbox = (QDoubleSpinBox*)widget; + if(value->value != 0) { + spinbox->setValue(value->value); + } + if(value->min != value->max) { + spinbox->setRange(value->min, value->max); + } + if(value->extent != 0) { + spinbox->setSingleStep(value->extent); + } + value->get = ui_spinbox_range_get; + value->set = ui_spinbox_range_set; + value->setrange = ui_spinbox_range_setrange; + value->setextent = ui_spinbox_range_setextent; + } + } + + + ctn->add(widget); + return widget; +} + +int64_t ui_spinbox_int_get(UiInteger *i) { + QSpinBox *spinbox = (QSpinBox*)i->obj; + i->value = spinbox->value(); + return i->value; +} + +void ui_spinbox_int_set(UiInteger *i, int64_t value) { + QSpinBox *spinbox = (QSpinBox*)i->obj; + spinbox->setValue(value); + i->value = spinbox->value(); +} + +double ui_spinbox_double_get(UiDouble *d) { + QDoubleSpinBox *spinbox = (QDoubleSpinBox*)d->obj; + d->value = spinbox->value(); + return d->value; +} + +void ui_spinbox_double_set(UiDouble *d, double value) { + QDoubleSpinBox *spinbox = (QDoubleSpinBox*)d->obj; + spinbox->setValue(value); + d->value = spinbox->value(); +} + +double ui_spinbox_range_get(UiRange *range) { + QDoubleSpinBox *spinbox = (QDoubleSpinBox*)range->obj; + range->value = spinbox->value(); + return range->value; +} + +void ui_spinbox_range_set(UiRange *range, double value) { + QDoubleSpinBox *spinbox = (QDoubleSpinBox*)range->obj; + spinbox->setValue(value); + range->value = spinbox->value(); +} + +void ui_spinbox_range_setrange(UiRange *range, double min, double max) { + QDoubleSpinBox *spinbox = (QDoubleSpinBox*)range->obj; + spinbox->setRange(min, max); + range->min = min; + range->max = max; +} + +void ui_spinbox_range_setextent(UiRange *range, double extent) { + QDoubleSpinBox *spinbox = (QDoubleSpinBox*)range->obj; + spinbox->setSingleStep(extent); + range->extent = extent; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/qt/entry.h Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,55 @@ +/* + * 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 ENTRY_H +#define ENTRY_H + +#include "../ui/entry.h" +#include "toolkit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +int64_t ui_spinbox_int_get(UiInteger *i); +void ui_spinbox_int_set(UiInteger *i, int64_t value); + +double ui_spinbox_double_get(UiDouble *d); +void ui_spinbox_double_set(UiDouble *d, double value); + +double ui_spinbox_range_get(UiRange *range); +void ui_spinbox_range_set(UiRange *range, double value); +void ui_spinbox_range_setrange(UiRange *range, double min, double max); +void ui_spinbox_range_setextent(UiRange *range, double extent); + +#ifdef __cplusplus +} +#endif + +#endif /* ENTRY_H */ +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/qt/image.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,39 @@ +/* + * 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 "image.h" + + + +void ui_image_ref(UIIMAGE img) { + // TODO +} + +void ui_image_unref(UIIMAGE img) { + // TODO +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/qt/image.h Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,36 @@ +/* + * 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 IMAGE_H +#define IMAGE_H + +#include "toolkit.h" +#include "../ui/image.h" + +#endif /* IMAGE_H */ +
--- a/ui/qt/label.cpp Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/qt/label.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -32,32 +32,32 @@ #include "ui/display.h" -UIWIDGET ui_label_create(UiObject* obj, UiLabelArgs args) { +UIWIDGET ui_label_create(UiObject* obj, UiLabelArgs *args) { UiContainerPrivate *ctn = ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args); - QString str = QString::fromUtf8(args.label); + QString str = QString::fromUtf8(args->label); QLabel *widget = new QLabel(str); Qt::AlignmentFlag align = Qt::AlignCenter; - if(args.align == UI_ALIGN_LEFT) { + if(args->align == UI_ALIGN_LEFT) { align = Qt::AlignLeft; - } else if(args.align == UI_ALIGN_RIGHT) { + } else if(args->align == UI_ALIGN_RIGHT) { align = Qt::AlignRight; } widget->setAlignment(align); - ctn->add(widget, false); + ctn->add(widget); return widget; } -UIWIDGET ui_llabel_create(UiObject* obj, UiLabelArgs args) { - args.align = UI_ALIGN_LEFT; +UIWIDGET ui_llabel_create(UiObject* obj, UiLabelArgs *args) { + args->align = UI_ALIGN_LEFT; return ui_label_create(obj, args); } -UIWIDGET ui_rlabel_create(UiObject* obj, UiLabelArgs args) { - args.align = UI_ALIGN_RIGHT; +UIWIDGET ui_rlabel_create(UiObject* obj, UiLabelArgs *args) { + args->align = UI_ALIGN_RIGHT; return ui_label_create(obj, args); }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/qt/list.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,130 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2014 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 "list.h" +#include "container.h" + +#include <QTreeView> +#include <QTreeWidgetItem> +#include <QListView> + +extern "C" void* ui_strmodel_getvalue(void *elm, int column) { + return column == 0 ? elm : NULL; +} + +static void* getvalue_wrapper(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) { + ui_getvaluefunc getvalue = (ui_getvaluefunc)userdata; + return getvalue(elm, col); +} + +UIWIDGET ui_listview_create(UiObject* obj, UiListArgs *args) { + UiContainerPrivate *ctn = ui_obj_container(obj); + UI_APPLY_LAYOUT(ctn->layout, args); + + QListView *view = new QListView(); + ui_getvaluefunc2 getvalue = nullptr; + void *getvaluedata = nullptr; + if(args->getvalue2) { + getvalue = args->getvalue2; + getvaluedata = args->getvalue2data; + } else if(args->getvalue) { + getvalue = getvalue_wrapper; + getvaluedata = (void*)args->getvalue; + } else { + getvalue = getvalue_wrapper; + getvaluedata = (void*)ui_strmodel_getvalue; + } + + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST); + + ListModel *model = new ListModel(obj, view, var, getvalue, getvaluedata); + view->setModel(model); + + if(var) { + UiList *list = (UiList*)var->value; + list->update = ui_listmodel_update; + list->getselection = ui_listmodel_getselection; + list->setselection = ui_listmodel_setselection; + list->obj = model; + } + + model->setActivationCallback(args->onactivate, args->onactivatedata); + model->setSelectionCallback(args->onselection, args->onselectiondata); + + QItemSelectionModel *s = view->selectionModel(); + QObject::connect( + s, + SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), + model, + SLOT(selectionChanged(const QItemSelection &, const QItemSelection &))); + + + ctn->add(view); + + return view; +} + +UIWIDGET ui_table_create(UiObject* obj, UiListArgs *args) { + UiContainerPrivate *ctn = ui_obj_container(obj); + UI_APPLY_LAYOUT(ctn->layout, args); + + QTreeView *view = new QTreeView(); + view->setItemsExpandable(false); + view->setRootIsDecorated(false); + if(args->multiselection) { + view->setSelectionMode(QAbstractItemView::ExtendedSelection); + } + + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST); + + TableModel *model = new TableModel(obj, view, var, args->model); + view->setModel(model); + + if(var) { + UiList *list = (UiList*)var->value; + list->update = ui_listmodel_update; + list->getselection = ui_listmodel_getselection; + list->setselection = ui_listmodel_setselection; + list->obj = model; + } + + model->setActivationCallback(args->onactivate, args->onactivatedata); + model->setSelectionCallback(args->onselection, args->onselectiondata); + + QItemSelectionModel *s = view->selectionModel(); + QObject::connect( + s, + SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)), + model, + SLOT(selectionChanged(const QItemSelection &, const QItemSelection &))); + + + ctn->add(view); + + return view; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/qt/list.h Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,40 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2014 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 TREE_H +#define TREE_H + +#include "../ui/tree.h" +#include "model.h" + +#include <QTableView> + + + +#endif /* TREE_H */ +
--- a/ui/qt/menu.cpp Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/qt/menu.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -157,6 +157,7 @@ if(action->var) { UiInteger *value = (UiInteger*)action->var->value; event->eventdata = value; + event->eventdatatype = UI_EVENT_DATA_INTEGER_VALUE; event->intval = value->get(value); } } @@ -217,6 +218,7 @@ void ui_checkableaction_prepare_event(UiEvent *event, UiAction *action) { if(action->var) { event->eventdata = action->var->value; + event->eventdatatype = UI_EVENT_DATA_INTEGER_VALUE; } event->intval = action->isChecked(); }
--- a/ui/qt/model.cpp Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/qt/model.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -28,3 +28,245 @@ #include "model.h" +static void* model_getvalue(UiModel *model, UiList *list, void *elm, int row, int col, UiBool *freeResult) { + if(model->getvalue2) { + return model->getvalue2(list, elm, row, col, model->getvalue2data, freeResult); + } else if(model->getvalue) { + return model->getvalue(elm, col); + } + return NULL; +} + +ListModel::ListModel(UiObject *obj, QListView *view, UiVar *var, ui_getvaluefunc2 getvalue, void *getvaluedata){ + this->obj = obj; + this->view = view; + this->var = var; + this->getvalue = getvalue; + this->getvaluedata = getvaluedata; + this->onactivate = nullptr; + this->onactivatedata = nullptr; + this->onselection = nullptr; + this->onselectiondata = nullptr; +} + +void ListModel::setActivationCallback(ui_callback f, void *userdata) { + onactivate = f; + onactivatedata = userdata; +} + +void ListModel::setSelectionCallback(ui_callback f, void *userdata) { + onselection = f; + onselectiondata = userdata; +} + +void ListModel::update(int row) { + if(row >= 0) { + this->update(row); + } else { + this->beginResetModel(); + this->endResetModel(); + } +} + +int ListModel::rowCount(const QModelIndex& parent) const { + UiList *list = (UiList*)var->value; + return ui_list_count(list); +} + +QVariant ListModel::data(const QModelIndex &index, int role) const { + if(role == Qt::DisplayRole) { + UiList *ls = (UiList*)var->value; + void *rowData = ls->get(ls, index.row()); + if(rowData && getvalue) { + UiBool freeResult = false; + void *value = getvalue(ls, rowData, index.row(), 0, getvaluedata, &freeResult); + if(value) { + auto qs = QString::fromUtf8((char*)value); + if(freeResult) { + free(value); + } + return qs; + } + } + } + return QVariant(); +} + +void ListModel::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) { + UiListSelection sel = ui_selection_model_to_selection(view->selectionModel()); + + UiEvent event; + event.obj = obj; + event.window = obj->window; + event.document = obj->ctx->document; + event.eventdata = &sel; + event.eventdatatype = UI_EVENT_DATA_LIST_SELECTION; + event.intval = sel.count; + event.set = ui_get_setop(); + + if(onactivate) { + onactivate(&event, onactivatedata); + } + if(onselection) { + onselection(&event, onselectiondata); + } + + free(sel.rows); +} + + + +TableModel::TableModel(UiObject *obj, QTreeView *view, UiVar *var, UiModel *model){ + this->obj = obj; + this->view = view; + this->var = var; + this->model = model; + this->onactivate = nullptr; + this->onactivatedata = nullptr; + this->onselection = nullptr; + this->onselectiondata = nullptr; +} + +void TableModel::setActivationCallback(ui_callback f, void *userdata) { + onactivate = f; + onactivatedata = userdata; +} + +void TableModel::setSelectionCallback(ui_callback f, void *userdata) { + onselection = f; + onselectiondata = userdata; +} + +void TableModel::update(int row) { + if(row >= 0) { + this->update(row); + } else { + this->beginResetModel(); + this->endResetModel(); + } +} + +int TableModel::rowCount(const QModelIndex& parent) const { + UiList *list = (UiList*)var->value; + return ui_list_count(list); +} + +int TableModel::columnCount(const QModelIndex &parent) const { + return model->columns; +} + +QVariant TableModel::data(const QModelIndex &index, int role) const { + if(role == Qt::DisplayRole) { + UiList *ls = (UiList*)var->value; + void *rowData = ls->get(ls, index.row()); + if(rowData) { + int col = index.column(); + UiBool freeResult = false; + void *value = model_getvalue(model, ls, rowData, index.row(), col, &freeResult); + if(value) { + UiModelType type = model->types[col]; + switch(type) { + case UI_STRING: { + auto qs = QString::fromUtf8((char*)value); + if(freeResult) { + free(value); + } + return qs; + } + case UI_STRING_FREE: { + QString s = QString::fromUtf8((char*)value); + free(value); + return s; + } + case UI_INTEGER: { + intptr_t i = (intptr_t)value; + return QString::number(i); + } + case UI_ICON: { + break; // TODO + } + case UI_ICON_TEXT: { + break; // TODO + } + case UI_ICON_TEXT_FREE: { + break; // TODO + } + } + } + } + } + return QVariant(); +} + +QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const { + if(role == Qt::DisplayRole) { + char *label = model->titles[section]; + return QString::fromUtf8(label); + } + return QVariant(); +} + +void TableModel::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) { + UiListSelection sel = ui_selection_model_to_selection(view->selectionModel()); + + UiEvent event; + event.obj = obj; + event.window = obj->window; + event.document = obj->ctx->document; + event.eventdata = &sel; + event.eventdatatype = UI_EVENT_DATA_LIST_SELECTION; + event.intval = sel.count; + event.set = ui_get_setop(); + + if(onactivate) { + onactivate(&event, onactivatedata); + } + if(onselection) { + onselection(&event, onselectiondata); + } + + free(sel.rows); +} + + + +UiListSelection ui_selection_model_to_selection(QItemSelectionModel *model) { + UiListSelection sel; + sel.rows = NULL; + sel.count = 0; + + if(model->hasSelection()) { + QModelIndexList indices = model->selectedIndexes(); + sel.count = indices.count(); + sel.rows = (int*)calloc(sel.count, sizeof(int)); + + int i = 0; + for (const QModelIndex &index : indices) { + sel.rows[i++] = index.row(); + } + } + + return sel; +} + +/* ---------------------- UiList implementation -----------------------------*/ + +void ui_listmodel_update(UiList *list, int row) { + ListModel *model = (ListModel*)list->obj; + model->update(row); +} + +void ui_listmodel_setselection(UiList *list, UiListSelection sel) { + ListModel *model = (ListModel*)list->obj; + QItemSelection selection; + for (int i=0;i<sel.count;i++) { + QModelIndex index = model->index(sel.rows[i]); + selection.select(index, index); + } + model->view->selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect); +} + +UiListSelection ui_listmodel_getselection(UiList *list) { + ListModel *model = (ListModel*)list->obj; + return ui_selection_model_to_selection(model->view->selectionModel()); +}
--- a/ui/qt/model.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/qt/model.h Sun Jul 20 22:04:39 2025 +0200 @@ -40,5 +40,80 @@ #include <QItemSelectionModel> + +class ListModel : public QAbstractListModel { + Q_OBJECT + + ui_getvaluefunc2 getvalue; + void *getvaluedata; + ui_callback onactivate; + void *onactivatedata; + ui_callback onselection; + void *onselectiondata; + +public: + UiObject *obj; + UiVar *var; + QListView *view; + + ListModel(UiObject *obj, QListView *view, UiVar *var, ui_getvaluefunc2 getvalue, void *getvaluedata); + + void setActivationCallback(ui_callback f, void *userdata); + void setSelectionCallback(ui_callback f, void *userdata); + + void update(int row); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + +public slots: + void selectionChanged( + const QItemSelection & selected, + const QItemSelection & deselected); +}; + +class TableModel : public QAbstractListModel { + Q_OBJECT + + UiModel *model; + ui_callback onactivate; + void *onactivatedata; + ui_callback onselection; + void *onselectiondata; + +public: + UiObject *obj; + UiVar *var; + QTreeView *view; + + TableModel(UiObject *obj, QTreeView *view, UiVar *var, UiModel *model); + + void setActivationCallback(ui_callback f, void *userdata); + void setSelectionCallback(ui_callback f, void *userdata); + + void update(int row); + + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + QVariant headerData(int section, Qt::Orientation orientation, int role) const; + +public slots: + void selectionChanged( + const QItemSelection & selected, + const QItemSelection & deselected); +}; + + +UiListSelection ui_selection_model_to_selection(QItemSelectionModel *model); + +extern "C" { + + void ui_listmodel_update(UiList *list, int row); + void ui_listmodel_setselection(UiList *list, UiListSelection sel); + UiListSelection ui_listmodel_getselection(UiList *list); + +} + #endif /* MODEL_H */
--- a/ui/qt/qt4.pro Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -# -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. -# -# Copyright 2014 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. -# - -TARGET = uitk -TEMPLATE = lib -CONFIG += staticlib warn_off debug -DESTDIR = ../build/lib -MOC_DIR = ../build/ui/qt -OBJECTS_DIR = ../build/ui/qt - -DEFINES += UI_QT4 - -SOURCES += toolkit.cpp -SOURCES += window.cpp -SOURCES += menu.cpp -SOURCES += toolbar.cpp -SOURCES += stock.cpp -SOURCES += container.cpp -SOURCES += text.cpp -SOURCES += model.cpp -SOURCES += tree.cpp -SOURCES += button.cpp -SOURCES += label.cpp -SOURCES += graphics.cpp - -HEADERS += toolkit.h -HEADERS += window.h -HEADERS += menu.h -HEADERS += toolbar.h -HEADERS += stock.h -HEADERS += container.h -HEADERS += text.h -HEADERS += model.h -HEADERS += tree.h -HEADERS += button.h -HEADERS += label.h -HEADERS += graphics.h -
--- a/ui/qt/qt5.pro Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/qt/qt5.pro Sun Jul 20 22:04:39 2025 +0200 @@ -33,6 +33,8 @@ MOC_DIR = ../build/ui/qt OBJECTS_DIR = ../build/ui/qt +QMAKE_CXXFLAGS += -I../ucx + QT += core gui widgets DEFINES += UI_QT5 @@ -45,11 +47,13 @@ SOURCES += container.cpp SOURCES += text.cpp SOURCES += model.cpp -SOURCES += tree.cpp +SOURCES += list.cpp SOURCES += button.cpp SOURCES += label.cpp SOURCES += graphics.cpp SOURCES += widget.cpp +SOURCES += entry.cpp +SOURCES += image.cpp HEADERS += toolkit.h HEADERS += window.h @@ -59,9 +63,11 @@ HEADERS += container.h HEADERS += text.h HEADERS += model.h -HEADERS += tree.h +HEADERS += list.h HEADERS += button.h HEADERS += label.h HEADERS += graphics.h HEADERS += widget.h +HEADERS += entry.h +HEADERS += image.h
--- a/ui/qt/text.cpp Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/qt/text.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -57,16 +57,16 @@ return document; } -UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs args) { +UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) { UiContainerPrivate *ctn = ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args); QTextEdit *textarea = new QTextEdit(); - ctn->add(textarea, true); + ctn->add(textarea); QTextDocument *document = nullptr; - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_STRING); + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_STRING); if(var) { UiText *value = (UiText*)var->value; @@ -201,23 +201,27 @@ } void ui_textarea_remove(UiText *text, int begin, int end) { - // TODO + QTextDocument *doc = (QTextDocument*)text->data1; + QTextCursor cursor(doc); + cursor.setPosition(begin); + cursor.setPosition(end, QTextCursor::KeepAnchor); + cursor.removeSelectedText(); } /* ------------------------------ TextField ------------------------------ */ -static UIWIDGET create_textfield(UiObject *obj, UiTextFieldArgs args, bool password, bool frameless) { +static UIWIDGET create_textfield(UiObject *obj, UiTextFieldArgs *args, bool password, bool frameless) { UiContainerPrivate *ctn = ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args); QLineEdit *textfield = new QLineEdit(); - ctn->add(textfield, false); + ctn->add(textfield); if(password) { textfield->setEchoMode(QLineEdit::Password); } - UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_STRING); + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_STRING); if(var) { UiString *value = (UiString*)var->value; if(value->value.ptr) { @@ -237,15 +241,15 @@ return textfield; } -UIWIDGET ui_textfield_create(UiObject *obj, UiTextFieldArgs args) { +UIWIDGET ui_textfield_create(UiObject *obj, UiTextFieldArgs *args) { return create_textfield(obj, args, false, false); } -UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs args) { +UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs *args) { return create_textfield(obj, args, false, true); } -UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs args) { +UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs *args) { return create_textfield(obj, args, true, false); }
--- a/ui/qt/toolbar.cpp Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/qt/toolbar.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -32,3 +32,102 @@ #include "menu.h" #include "stock.h" +static void add_items(UiObject *obj, QToolBar *toolbar, CxList *defaults, CxMap *items); +static void create_item(UiObject *obj, QToolBar *toolbar, UiToolbarItemI *i); + +QToolBar* ui_create_toolbar(UiObject *obj) { + CxMap *items = uic_get_toolbar_items(); + CxList *left_defaults = uic_get_toolbar_defaults(UI_TOOLBAR_LEFT); + CxList *center_defaults = uic_get_toolbar_defaults(UI_TOOLBAR_CENTER); + CxList *right_defaults = uic_get_toolbar_defaults(UI_TOOLBAR_RIGHT); + + if(!items || cxMapSize(items) == 0) { + return nullptr; + } + + QToolBar *toolbar = new QToolBar(); + add_items(obj, toolbar, left_defaults, items); + add_items(obj, toolbar, center_defaults, items); + add_items(obj, toolbar, right_defaults, items); + + + return toolbar; +} + +static void add_items(UiObject *obj, QToolBar *toolbar, CxList *defaults, CxMap *items) { + CxIterator i = cxListIterator(defaults); + cx_foreach(char *, name, i) { + UiToolbarItemI *item = (UiToolbarItemI*)cxMapGet(items, name); + if(item) { + create_item(obj, toolbar, item); + } else { + fprintf(stderr, "UI Error: unknown toolbar item '%s'\n", name); + } + } +} + +static void create_item(UiObject *obj, QToolBar *toolbar, UiToolbarItemI *i) { + switch(i->type) { + case UI_TOOLBAR_ITEM: { + ui_toolbar_add_item(obj, toolbar, (UiToolbarItem*)i); + break; + } + case UI_TOOLBAR_TOGGLEITEM: { + ui_toolbar_add_toggleitem(obj, toolbar, (UiToolbarToggleItem*)i); + break; + } + case UI_TOOLBAR_MENU: { + ui_toolbar_add_menu(obj, toolbar, (UiToolbarMenuItem*)i); + break; + } + default: fprintf(stderr, "toolbar item type unimplemented: %d\n", (int)i->type); + } +} + +void ui_toolbar_add_item(UiObject *obj, QToolBar *toolbar, UiToolbarItem *item) { + QAction *action = new QAction(); + if(item->args.label) { + action->setText(item->args.label); + } + if(item->args.icon) { + action->setIcon(QIcon::fromTheme(item->args.icon)); + } + toolbar->addAction(action); + + UiEventWrapper *event = new UiEventWrapper(obj, item->args.onclick, item->args.onclickdata); + action->connect(action, SIGNAL(triggered()), event, SLOT(slot())); + action->connect(action, SIGNAL(destroyed()), event, SLOT(destroy())); +} + +static void toolbar_togglebutton_event(UiEvent *event, UiEventWrapper *wrapper) { + QAction *action = (QAction*)wrapper->customdata1; + event->intval = action->isChecked(); + if(wrapper->var) { + event->eventdata = wrapper->var->value; + event->eventdatatype = UI_EVENT_DATA_INTEGER_VALUE; + } +} + +void ui_toolbar_add_toggleitem(UiObject *obj, QToolBar *toolbar, UiToolbarToggleItem *item) { + QAction *action = new QAction(); + action->setCheckable(true); + if(item->args.label) { + action->setText(item->args.label); + } + if(item->args.icon) { + action->setIcon(QIcon::fromTheme(item->args.icon)); + } + toolbar->addAction(action); + + UiVar* var = uic_widget_var(obj->ctx, obj->ctx, nullptr, item->args.varname, UI_VAR_INTEGER); + UiEventWrapper *event = new UiEventWrapper(obj, item->args.onchange, item->args.onchangedata); + event->var = var; + event->customdata1 = action; + event->prepare_event = toolbar_togglebutton_event; + action->connect(action, SIGNAL(triggered()), event, SLOT(slot())); + action->connect(action, SIGNAL(destroyed()), event, SLOT(destroy())); +} + +void ui_toolbar_add_menu(UiObject *obj, QToolBar *toolbar, UiToolbarMenuItem *item) { + +}
--- a/ui/qt/toolbar.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/qt/toolbar.h Sun Jul 20 22:04:39 2025 +0200 @@ -31,10 +31,14 @@ #include "toolkit.h" #include "../ui/toolbar.h" +#include "../common/toolbar.h" #include <QToolBar> +QToolBar* ui_create_toolbar(UiObject *obj); - +void ui_toolbar_add_item(UiObject *obj, QToolBar *toolbar, UiToolbarItem *item); +void ui_toolbar_add_toggleitem(UiObject *obj, QToolBar *toolbar, UiToolbarToggleItem *item); +void ui_toolbar_add_menu(UiObject *obj, QToolBar *toolbar, UiToolbarMenuItem *item); #endif /* TOOLBAR_H */
--- a/ui/qt/toolkit.cpp Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/qt/toolkit.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -43,15 +43,17 @@ static ui_callback startup_func; static void *startup_data; static ui_callback open_func; -void *open_data; +static void *open_data; static ui_callback exit_func; -void *exit_data; +static void *exit_data; static int is_toplevel_realized = 0; -int app_argc; -char **app_argv; -QApplication *application = NULL; +static int app_argc; +static char **app_argv; +static QApplication *application = NULL; + +static UiBool exit_on_shutdown; void ui_init(const char *appname, int argc, char **argv) { application_name = appname; @@ -87,6 +89,10 @@ exit_data = userdata; } +void ui_app_exit_on_shutdown(UiBool exitapp) { + exit_on_shutdown = exitapp; +} + void ui_main() { if(startup_func) { startup_func(NULL, startup_data); @@ -98,6 +104,10 @@ uic_store_app_properties(); delete application; + + if(exit_on_shutdown) { + exit(0); + } } void ui_show(UiObject *obj) { @@ -137,6 +147,7 @@ e.window = obj->window; e.document = obj->ctx->document; e.eventdata = NULL; + e.eventdatatype = 0; e.intval = 0; e.set = ui_get_setop(); if(prepare_event) { @@ -174,6 +185,7 @@ e.window = obj->window; e.document = obj->ctx->document; e.eventdata = NULL; + e.eventdatatype = 0; e.intval = 0; e.set = ui_get_setop(); if(prepare_event) {
--- a/ui/qt/tree.cpp Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2014 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 "tree.h" -#include "container.h" - -#include <QTreeView> -#include <QTreeWidgetItem> -#include <QListView> - -
--- a/ui/qt/tree.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2014 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 TREE_H -#define TREE_H - -#include "../ui/tree.h" -#include "model.h" - -#include <QTableView> - - - -#endif /* TREE_H */ -
--- a/ui/qt/widget.cpp Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/qt/widget.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -31,11 +31,11 @@ #include "container.h" #include "../common/context.h" -UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs args) { +UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs *args) { UIWIDGET widget = create_widget(obj, args, userdata); UiContainerPrivate *ctn = ui_obj_container(obj); UI_APPLY_LAYOUT(ctn->layout, args); - ctn->add(widget, false); + ctn->add(widget); return widget; } @@ -45,9 +45,9 @@ separator->setFrameShadow(QFrame::Sunken); UiContainerPrivate *ctn = ui_obj_container(obj); - UI_APPLY_LAYOUT(ctn->layout, (*args)); + UI_APPLY_LAYOUT(ctn->layout, args); - ctn->add(separator, false); + ctn->add(separator); return separator; }
--- a/ui/qt/window.cpp Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/qt/window.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -28,6 +28,7 @@ #include <cx/mempool.h> #include "../common/context.h" +#include "../common/object.h" #include "window.h" #include "menu.h" @@ -39,9 +40,7 @@ #include <QPushButton> static UiObject* create_window(const char *title, void *window_data, bool simple) { - CxMempool *mp = cxMempoolCreateSimple(256); - UiObject *obj = (UiObject*)cxCalloc(mp->allocator, 1, sizeof(UiObject)); - obj->ctx = uic_context(obj, mp); + UiObject *obj = uic_object_new_toplevel(); obj->window = window_data; obj->next = NULL; @@ -51,8 +50,10 @@ if(!simple) { ui_add_menus(obj, window); - //QToolBar *toolbar = ui_create_toolbar(obj); - //window->addToolBar(Qt::TopToolBarArea, toolbar); + QToolBar *toolbar = ui_create_toolbar(obj); + if(toolbar) { + window->addToolBar(Qt::TopToolBarArea, toolbar); + } } QBoxLayout *box = new QVBoxLayout();
--- a/ui/ui/button.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/ui/button.h Sun Jul 20 22:04:39 2025 +0200 @@ -36,7 +36,7 @@ #endif typedef struct UiButtonArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -58,7 +58,7 @@ } UiButtonArgs; typedef struct UiToggleArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -82,17 +82,17 @@ const int* groups; } UiToggleArgs; -#define ui_button(obj, ...) ui_button_create(obj, (UiButtonArgs){ __VA_ARGS__ } ) -#define ui_togglebutton(obj, ...) ui_togglebutton_create(obj, (UiToggleArgs){ __VA_ARGS__ } ) -#define ui_checkbox(obj, ...) ui_checkbox_create(obj, (UiToggleArgs){ __VA_ARGS__ } ) -#define ui_switch(obj, ...) ui_switch_create(obj, (UiToggleArgs){ __VA_ARGS__ } ) -#define ui_radiobutton(obj, ...) ui_radiobutton_create(obj, (UiToggleArgs){ __VA_ARGS__ } ) +#define ui_button(obj, ...) ui_button_create(obj, &(UiButtonArgs){ __VA_ARGS__ } ) +#define ui_togglebutton(obj, ...) ui_togglebutton_create(obj, &(UiToggleArgs){ __VA_ARGS__ } ) +#define ui_checkbox(obj, ...) ui_checkbox_create(obj, &(UiToggleArgs){ __VA_ARGS__ } ) +#define ui_switch(obj, ...) ui_switch_create(obj, &(UiToggleArgs){ __VA_ARGS__ } ) +#define ui_radiobutton(obj, ...) ui_radiobutton_create(obj, &(UiToggleArgs){ __VA_ARGS__ } ) -UIEXPORT UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs args); -UIEXPORT UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs args); -UIEXPORT UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs args); -UIEXPORT UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs args); -UIEXPORT UIWIDGET ui_radiobutton_create(UiObject* obj, UiToggleArgs args); +UIEXPORT UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs *args); +UIEXPORT UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs *args); +UIEXPORT UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs *args); +UIEXPORT UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs *args); +UIEXPORT UIWIDGET ui_radiobutton_create(UiObject* obj, UiToggleArgs *args);
--- a/ui/ui/container.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/ui/container.h Sun Jul 20 22:04:39 2025 +0200 @@ -59,7 +59,7 @@ typedef struct UiContainerArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -81,7 +81,7 @@ } UiContainerArgs; typedef struct UiFrameArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -104,7 +104,7 @@ } UiFrameArgs; typedef struct UiTabViewArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -116,6 +116,8 @@ const char *style_class; UiTabViewType tabview; + ui_callback onchange; + void *onchangedata; UiSubContainerType subcontainer; @@ -132,7 +134,7 @@ } UiTabViewArgs; typedef struct UiHeaderbarArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -158,7 +160,7 @@ } UiSidebarArgs; typedef struct UiSplitPaneArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -181,7 +183,7 @@ } UiSplitPaneArgs; typedef struct UiItemListContainerArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -235,39 +237,39 @@ #define UI_CTN(obj, ctn) for(ctn;ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_vbox(obj, ...) for(ui_vbox_create(obj, (UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_hbox(obj, ...) for(ui_hbox_create(obj, (UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_grid(obj, ...) for(ui_grid_create(obj, (UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_frame(obj, ...) for(ui_frame_create(obj, (UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_expander(obj, ...) for(ui_expander_create(obj, (UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_scrolledwindow(obj, ...) for(ui_scrolledwindow_create(obj, (UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_tabview(obj, ...) for(ui_tabview_create(obj, (UiTabViewArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_headerbar(obj, ...) for(ui_headerbar_create(obj, (UiHeaderbarArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_sidebar(obj, ...) for(ui_sidebar_create(obj, (UiSidebarArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_vbox(obj, ...) for(ui_vbox_create(obj, &(UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_hbox(obj, ...) for(ui_hbox_create(obj, &(UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_grid(obj, ...) for(ui_grid_create(obj, &(UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_frame(obj, ...) for(ui_frame_create(obj, &(UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_expander(obj, ...) for(ui_expander_create(obj, &(UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_scrolledwindow(obj, ...) for(ui_scrolledwindow_create(obj, &(UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_tabview(obj, ...) for(ui_tabview_create(obj, &(UiTabViewArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_headerbar(obj, ...) for(ui_headerbar_create(obj, &(UiHeaderbarArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_sidebar(obj, ...) for(ui_sidebar_create(obj, &(UiSidebarArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_vbox0(obj) for(ui_vbox_create(obj, (UiContainerArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_hbox0(obj) for(ui_hbox_create(obj, (UiContainerArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_grid0(obj) for(ui_grid_create(obj, (UiContainerArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_frame0(obj) for(ui_frame_create(obj, (UiFrameArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_expander0(obj) for(ui_expande_create(obj, (UiFrameArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_scrolledwindow0(obj) for(ui_scrolledwindow_create(obj, (UiFrameArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_tabview0(obj) for(ui_tabview_create(obj, (UiTabViewArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_headerbar0(obj) for(ui_headerbar_create(obj, (UiHeaderbarArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_sidebar0(obj) for(ui_sidebar_create(obj, (UiSidebarArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_vbox0(obj) for(ui_vbox_create(obj, &(UiContainerArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_hbox0(obj) for(ui_hbox_create(obj, &(UiContainerArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_grid0(obj) for(ui_grid_create(obj, &(UiContainerArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_frame0(obj) for(ui_frame_create(obj, &(UiFrameArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_expander0(obj) for(ui_expande_create(obj, &(UiFrameArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_scrolledwindow0(obj) for(ui_scrolledwindow_create(obj, &(UiFrameArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_tabview0(obj) for(ui_tabview_create(obj, &(UiTabViewArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_headerbar0(obj) for(ui_headerbar_create(obj, &(UiHeaderbarArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_sidebar0(obj) for(ui_sidebar_create(obj, &(UiSidebarArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_vbox_w(obj, w, ...) for(w = ui_vbox_create(obj, (UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_hbox_w(obj, w, ...) for(w = ui_hbox_create(obj, (UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_grid_w(obj, w, ...) for(w = ui_grid_create(obj, (UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_tabview_w(obj, w, ...) for(w = ui_tabview_create(obj, (UiTabViewArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_scrolledwindow_w(obj, w, ...) for(w = ui_scrolledwindow_create(obj, (UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_vbox_w(obj, w, ...) for(w = ui_vbox_create(obj, &(UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_hbox_w(obj, w, ...) for(w = ui_hbox_create(obj, &(UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_grid_w(obj, w, ...) for(w = ui_grid_create(obj, &(UiContainerArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_tabview_w(obj, w, ...) for(w = ui_tabview_create(obj, &(UiTabViewArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_scrolledwindow_w(obj, w, ...) for(w = ui_scrolledwindow_create(obj, &(UiFrameArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_hsplitpane(obj, ...) for(ui_hsplitpane_create(obj, (UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_vsplitpane(obj, ...) for(ui_vsplitpane_create(obj, (UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_hsplitpane0(obj) for(ui_hsplitpane_create(obj, (UiSplitPaneArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_vsplitpane0(obj) for(ui_vsplitpane_create(obj, (UiSplitPaneArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_hsplitpane(obj, ...) for(ui_hsplitpane_create(obj, &(UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_vsplitpane(obj, ...) for(ui_vsplitpane_create(obj, &(UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_hsplitpane0(obj) for(ui_hsplitpane_create(obj, &(UiSplitPaneArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_vsplitpane0(obj) for(ui_vsplitpane_create(obj, &(UiSplitPaneArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_hsplitpane_w(obj, w, ...) for(w = ui_hsplitpane_create(obj, (UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_vsplitpane_w(obj, w, ...) for(w = ui_vsplitpane_create(obj, (UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_hsplitpane_w(obj, w, ...) for(w = ui_hsplitpane_create(obj, &(UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) +#define ui_vsplitpane_w(obj, w, ...) for(w = ui_vsplitpane_create(obj, &(UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj)) #define ui_tab(obj, label) for(ui_tab_create(obj, label);ui_container_finish(obj);ui_container_begin_close(obj)) @@ -275,35 +277,35 @@ #define ui_headerbar_center(obj) for(ui_headerbar_center_create(obj);ui_container_finish(obj);ui_container_begin_close(obj)) #define ui_headerbar_end(obj) for(ui_headerbar_end_create(obj);ui_container_finish(obj);ui_container_begin_close(obj)) -#define ui_itemlist(obj, ...) ui_itemlist_create(obj, (UiItemListContainerArgs) { __VA_ARGS__} ) +#define ui_itemlist(obj, ...) ui_itemlist_create(obj, &(UiItemListContainerArgs) { __VA_ARGS__} ) UIEXPORT void ui_end(UiObject *obj); // deprecated UIEXPORT void ui_end_new(UiObject *obj); // TODO: rename to ui_end -UIEXPORT UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs args); -UIEXPORT UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs args); -UIEXPORT UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs args); -UIEXPORT UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs args); -UIEXPORT UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs args); -UIEXPORT UIWIDGET ui_scrolledwindow_create(UiObject *obj, UiFrameArgs args); +UIEXPORT UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs *args); +UIEXPORT UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs *args); +UIEXPORT UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args); +UIEXPORT UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args); +UIEXPORT UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs *args); +UIEXPORT UIWIDGET ui_scrolledwindow_create(UiObject *obj, UiFrameArgs *args); -UIEXPORT UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs args); +UIEXPORT UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs *args); UIEXPORT void ui_tab_create(UiObject *obj, const char* title); UIEXPORT void ui_tabview_select(UIWIDGET tabview, int tab); UIEXPORT void ui_tabview_remove(UIWIDGET tabview, int tab); UIEXPORT UiObject* ui_tabview_add(UIWIDGET tabview, const char *name, int tab_index); -UIEXPORT UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args); +UIEXPORT UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs *args); UIEXPORT void ui_headerbar_start_create(UiObject *obj); UIEXPORT void ui_headerbar_center_create(UiObject *obj); UIEXPORT void ui_headerbar_end_create(UiObject *obj); -UIEXPORT UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs args); +UIEXPORT UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs *args); -UIEXPORT UIWIDGET ui_itemlist_create(UiObject *obj, UiItemListContainerArgs args); +UIEXPORT UIWIDGET ui_itemlist_create(UiObject *obj, UiItemListContainerArgs *args); -UIEXPORT UIWIDGET ui_hsplitpane_create(UiObject *obj, UiSplitPaneArgs args); -UIEXPORT UIWIDGET ui_vsplitpane_create(UiObject *obj, UiSplitPaneArgs args); +UIEXPORT UIWIDGET ui_hsplitpane_create(UiObject *obj, UiSplitPaneArgs *args); +UIEXPORT UIWIDGET ui_vsplitpane_create(UiObject *obj, UiSplitPaneArgs *args); UIEXPORT void ui_splitpane_set_visible(UIWIDGET splitpane, int child_index, UiBool visible); @@ -342,6 +344,17 @@ if(args.rowspan > 0) ui_layout_rowspan(obj, args.rowspan); \ /*force caller to add ';'*/(void)0 +#define UI_APPLY_LAYOUT2(obj, args) \ + if(args->fill != UI_DEFAULT) ui_layout_fill(obj, args->fill == UI_ON ? 1 : 0 ); \ + if(args->hexpand) ui_layout_hexpand(obj, 1); \ + if(args->vexpand) ui_layout_vexpand(obj, 1); \ + if(args->hfill) ui_layout_hfill(obj, 1); \ + if(args->vfill) ui_layout_vfill(obj, 1); \ + if(args->override_defaults) ui_layout_override_defaults(obj, 1); \ + if(args->colspan > 0) ui_layout_colspan(obj, args->colspan); \ + if(args->rowspan > 0) ui_layout_rowspan(obj, args->rowspan); \ + /*force caller to add ';'*/(void)0 + #ifdef __cplusplus }
--- a/ui/ui/display.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/ui/display.h Sun Jul 20 22:04:39 2025 +0200 @@ -58,7 +58,7 @@ typedef enum UiLabelStyle UiLabelStyle; typedef struct UiLabelArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -77,7 +77,7 @@ } UiLabelArgs; typedef struct UiProgressbarArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -96,7 +96,7 @@ } UiProgressbarArgs; typedef struct UiProgressbarSpinnerArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -113,24 +113,24 @@ /* label widgets */ -#define ui_label(obj, ...) ui_label_create(obj, (UiLabelArgs) { __VA_ARGS__ }) -#define ui_llabel(obj, ...) ui_llabel_create(obj, (UiLabelArgs) { __VA_ARGS__ }) -#define ui_rlabel(obj, ...) ui_rlabel_create(obj, (UiLabelArgs) { __VA_ARGS__ }) +#define ui_label(obj, ...) ui_label_create(obj, &(UiLabelArgs) { __VA_ARGS__ }) +#define ui_llabel(obj, ...) ui_llabel_create(obj, &(UiLabelArgs) { __VA_ARGS__ }) +#define ui_rlabel(obj, ...) ui_rlabel_create(obj, &(UiLabelArgs) { __VA_ARGS__ }) -UIEXPORT UIWIDGET ui_label_create(UiObject* obj, UiLabelArgs args); -UIEXPORT UIWIDGET ui_llabel_create(UiObject* obj, UiLabelArgs args); -UIEXPORT UIWIDGET ui_rlabel_create(UiObject* obj, UiLabelArgs args); +UIEXPORT UIWIDGET ui_label_create(UiObject* obj, UiLabelArgs *args); +UIEXPORT UIWIDGET ui_llabel_create(UiObject* obj, UiLabelArgs *args); +UIEXPORT UIWIDGET ui_rlabel_create(UiObject* obj, UiLabelArgs *args); UIWIDGET ui_space_deprecated(UiObject *obj); /* progress bar/spinner */ -#define ui_progressbar(obj, ...) ui_progressbar_create(obj, (UiProgressbarArgs) { __VA_ARGS__ } ) -#define ui_progressspinner(obj, ...) ui_progressspinner_create(obj, (UiProgressbarSpinnerArgs) { __VA_ARGS__ } ) +#define ui_progressbar(obj, ...) ui_progressbar_create(obj, &(UiProgressbarArgs) { __VA_ARGS__ } ) +#define ui_progressspinner(obj, ...) ui_progressspinner_create(obj, &(UiProgressbarSpinnerArgs) { __VA_ARGS__ } ) -UIEXPORT UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs args); -UIEXPORT UIWIDGET ui_progressspinner_create(UiObject* obj, UiProgressbarSpinnerArgs args); +UIEXPORT UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs *args); +UIEXPORT UIWIDGET ui_progressspinner_create(UiObject* obj, UiProgressbarSpinnerArgs *args); #ifdef __cplusplus
--- a/ui/ui/entry.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/ui/entry.h Sun Jul 20 22:04:39 2025 +0200 @@ -37,7 +37,7 @@ typedef struct UiSpinnerArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -62,9 +62,9 @@ -UIWIDGET ui_spinner_create(UiObject *obj, UiSpinnerArgs args); +UIWIDGET ui_spinner_create(UiObject *obj, UiSpinnerArgs *args); -#define ui_spinner(obj, ...) ui_spinner_create(obj, (UiSpinnerArgs){ __VA_ARGS__ } ) +#define ui_spinner(obj, ...) ui_spinner_create(obj, &(UiSpinnerArgs){ __VA_ARGS__ } ) void ui_spinner_setrange(UIWIDGET spinner, double min, double max); void ui_spinner_setdigits(UIWIDGET spinner, int digits);
--- a/ui/ui/icons.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/ui/icons.h Sun Jul 20 22:04:39 2025 +0200 @@ -49,6 +49,8 @@ #define UI_ICON_DOCK_RIGHT "" #define UI_ICON_GO_BACK "go-previous" #define UI_ICON_GO_FORWARD "go-next" +#define UI_ICON_GO_UP "go-up" +#define UI_ICON_GO_DOWN "go-down" #endif /* UI_GTK */ @@ -68,6 +70,8 @@ #define UI_ICON_DOCK_RIGHT "DockRight" #define UI_ICON_GO_BACK "Back" #define UI_ICON_GO_FORWARD "Forward" +#define UI_ICON_GO_UP "Up" +#define UI_ICON_GO_DOWN "" // TODO: implement workaround for missing down symbol #endif /* UI_WINUI */
--- a/ui/ui/image.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/ui/image.h Sun Jul 20 22:04:39 2025 +0200 @@ -45,7 +45,7 @@ typedef struct UiImageViewerArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -75,9 +75,9 @@ void *onbuttonreleasedata; } UiImageViewerArgs; -#define ui_imageviewer(obj, ...) ui_imageviewer_create(obj, (UiImageViewerArgs){ __VA_ARGS__ } ) +#define ui_imageviewer(obj, ...) ui_imageviewer_create(obj, &(UiImageViewerArgs){ __VA_ARGS__ } ) -UIEXPORT UIWIDGET ui_imageviewer_create(UiObject *obj, UiImageViewerArgs args); +UIEXPORT UIWIDGET ui_imageviewer_create(UiObject *obj, UiImageViewerArgs *args); UIEXPORT UIWIDGET ui_imageviewer_reset(UIWIDGET w); UIEXPORT UIWIDGET ui_imageviewer_set_autoscale(UIWIDGET w, UiBool set); @@ -85,6 +85,7 @@ UIEXPORT UIWIDGET ui_imageviewer_set_useradjustable(UIWIDGET w, UiBool set); UIEXPORT int ui_image_load_file(UiGeneric *obj, const char *path); +UIEXPORT int ui_image_load_data(UiGeneric *obj, const void *imgdata, size_t size); UIEXPORT void ui_image_ref(UIIMAGE img); UIEXPORT void ui_image_unref(UIIMAGE img);
--- a/ui/ui/menu.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/ui/menu.h Sun Jul 20 22:04:39 2025 +0200 @@ -69,23 +69,23 @@ #define ui_menu(label) for(ui_menu_create(label);ui_menu_is_open();ui_menu_close()) -#define ui_menuitem(...) ui_menuitem_create((UiMenuItemArgs){ __VA_ARGS__ }) -#define ui_menu_toggleitem(...) ui_menu_toggleitem_create((UiMenuToggleItemArgs){ __VA_ARGS__ }) -#define ui_menu_radioitem(...) ui_menu_radioitem_create((UiMenuToggleItemArgs){ __VA_ARGS__ }) -#define ui_menu_itemlist(...) ui_menu_itemlist_create((UiMenuItemListArgs) { __VA_ARGS__ } ) -#define ui_menu_togglelist(...) ui_menu_itemlist_create((UiMenuItemListArgs) { __VA_ARGS} ) -#define ui_menu_radiolist(...) ui_menu_itemlist_create((UiMenuItemListArgs) { __VA_ARGS} ) +#define ui_menuitem(...) ui_menuitem_create(&(UiMenuItemArgs){ __VA_ARGS__ }) +#define ui_menu_toggleitem(...) ui_menu_toggleitem_create(&(UiMenuToggleItemArgs){ __VA_ARGS__ }) +#define ui_menu_radioitem(...) ui_menu_radioitem_create(&(UiMenuToggleItemArgs){ __VA_ARGS__ }) +#define ui_menu_itemlist(...) ui_menu_itemlist_create(&(UiMenuItemListArgs) { __VA_ARGS__ } ) +#define ui_menu_togglelist(...) ui_menu_itemlist_create(&(UiMenuItemListArgs) { __VA_ARGS} ) +#define ui_menu_radiolist(...) ui_menu_itemlist_create(&(UiMenuItemListArgs) { __VA_ARGS} ) UIEXPORT void ui_menu_create(const char* label); -UIEXPORT void ui_menuitem_create(UiMenuItemArgs args); -UIEXPORT void ui_menu_toggleitem_create(UiMenuToggleItemArgs args); -UIEXPORT void ui_menu_radioitem_create(UiMenuToggleItemArgs args); +UIEXPORT void ui_menuitem_create(UiMenuItemArgs *args); +UIEXPORT void ui_menu_toggleitem_create(UiMenuToggleItemArgs *args); +UIEXPORT void ui_menu_radioitem_create(UiMenuToggleItemArgs *args); UIEXPORT void ui_menuseparator(); -UIEXPORT void ui_menu_itemlist_create(UiMenuItemListArgs args); -UIEXPORT void ui_menu_toggleitemlist_create(UiMenuItemListArgs args); -UIEXPORT void ui_menu_radioitemlist_create(UiMenuItemListArgs args); +UIEXPORT void ui_menu_itemlist_create(UiMenuItemListArgs *args); +UIEXPORT void ui_menu_toggleitemlist_create(UiMenuItemListArgs *args); +UIEXPORT void ui_menu_radioitemlist_create(UiMenuItemListArgs *args); UIEXPORT void ui_menu_end(void); // TODO: private
--- a/ui/ui/text.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/ui/text.h Sun Jul 20 22:04:39 2025 +0200 @@ -36,7 +36,7 @@ #endif typedef struct UiTextAreaArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -57,7 +57,7 @@ } UiTextAreaArgs; typedef struct UiTextFieldArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -91,7 +91,7 @@ typedef struct UiPathTextFieldArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -119,25 +119,25 @@ void *ondropsdata; } UiPathTextFieldArgs; -#define ui_textarea(obj, ...) ui_textarea_create(obj, (UiTextAreaArgs) { __VA_ARGS__ }) +#define ui_textarea(obj, ...) ui_textarea_create(obj, &(UiTextAreaArgs) { __VA_ARGS__ }) -UIEXPORT UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs args); +UIEXPORT UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args); UIEXPORT UIWIDGET ui_textarea_gettextwidget(UIWIDGET textarea); UIEXPORT void ui_text_undo(UiText *value); UIEXPORT void ui_text_redo(UiText *value); -#define ui_textfield(obj, ...) ui_textfield_create(obj, (UiTextFieldArgs) { __VA_ARGS__ }) -#define ui_frameless_textfield(obj, ...) ui_frameless_field_create(obj, (UiTextFieldArgs) { __VA_ARGS__ }) -#define ui_passwordfield(obj, ...) ui_passwordfield_create(obj, (UiTextFieldArgs) { __VA_ARGS__ }) -#define ui_path_textfield(obj, ...) ui_path_textfield_create(obj, (UiPathTextFieldArgs) { __VA_ARGS__ } ) +#define ui_textfield(obj, ...) ui_textfield_create(obj, &(UiTextFieldArgs) { __VA_ARGS__ }) +#define ui_frameless_textfield(obj, ...) ui_frameless_field_create(obj, &(UiTextFieldArgs) { __VA_ARGS__ }) +#define ui_passwordfield(obj, ...) ui_passwordfield_create(obj, &(UiTextFieldArgs) { __VA_ARGS__ }) +#define ui_path_textfield(obj, ...) ui_path_textfield_create(obj, &(UiPathTextFieldArgs) { __VA_ARGS__ } ) -UIEXPORT UIWIDGET ui_textfield_create(UiObject *obj, UiTextFieldArgs args); -UIEXPORT UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs args); -UIEXPORT UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs args); +UIEXPORT UIWIDGET ui_textfield_create(UiObject *obj, UiTextFieldArgs *args); +UIEXPORT UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs *args); +UIEXPORT UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs *args); -UIEXPORT UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs args); +UIEXPORT UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs *args); #ifdef __cplusplus }
--- a/ui/ui/toolbar.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/ui/toolbar.h Sun Jul 20 22:04:39 2025 +0200 @@ -71,16 +71,16 @@ UI_TOOLBAR_RIGHT }; -#define ui_toolbar_item(name, ...) ui_toolbar_item_create(name, (UiToolbarItemArgs){ __VA_ARGS__ } ) -#define ui_toolbar_toggleitem(name, ...) ui_toolbar_toggleitem_create(name, (UiToolbarToggleItemArgs){ __VA_ARGS__ } ) +#define ui_toolbar_item(name, ...) ui_toolbar_item_create(name, &(UiToolbarItemArgs){ __VA_ARGS__ } ) +#define ui_toolbar_toggleitem(name, ...) ui_toolbar_toggleitem_create(name, &(UiToolbarToggleItemArgs){ __VA_ARGS__ } ) -#define ui_toolbar_menu(name, ...) for(ui_toolbar_menu_create(name, (UiToolbarMenuArgs){ __VA_ARGS__ });ui_menu_is_open();ui_menu_close()) -#define ui_toolbar_appmenu() for(ui_toolbar_menu_create(NULL, (UiToolbarMenuArgs){ 0 });ui_menu_is_open();ui_menu_close()) +#define ui_toolbar_menu(name, ...) for(ui_toolbar_menu_create(name, &(UiToolbarMenuArgs){ __VA_ARGS__ });ui_menu_is_open();ui_menu_close()) +#define ui_toolbar_appmenu() for(ui_toolbar_menu_create(NULL, &(UiToolbarMenuArgs){ 0 });ui_menu_is_open();ui_menu_close()) -UIEXPORT void ui_toolbar_item_create(const char* name, UiToolbarItemArgs args); -UIEXPORT void ui_toolbar_toggleitem_create(const char* name, UiToolbarToggleItemArgs args); -UIEXPORT void ui_toolbar_menu_create(const char* name, UiToolbarMenuArgs args); +UIEXPORT void ui_toolbar_item_create(const char* name, UiToolbarItemArgs *args); +UIEXPORT void ui_toolbar_toggleitem_create(const char* name, UiToolbarToggleItemArgs *args); +UIEXPORT void ui_toolbar_menu_create(const char* name, UiToolbarMenuArgs *args); UIEXPORT void ui_toolbar_add_default(const char *name, enum UiToolbarPos pos);
--- a/ui/ui/toolkit.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/ui/toolkit.h Sun Jul 20 22:04:39 2025 +0200 @@ -92,7 +92,11 @@ #define UIEXPORT __declspec(dllexport) -#define UIWIDGET void* +typedef struct W32Widget { + HWND hwnd; +} W32Widget; + +#define UIWIDGET W32Widget* #define UIWINDOW void* #define UIMENU void* @@ -217,7 +221,6 @@ UI_OFF } UiTri; - enum UiMouseEventType { UI_PRESS = 0, UI_PRESS2 }; typedef enum UiLabelType { @@ -237,7 +240,8 @@ typedef void(*ui_callback)(UiEvent*, void*); /* event, user data */ -typedef void*(*ui_getvaluefunc)(void*, int); +typedef void*(*ui_getvaluefunc)(void *elm, int col); +typedef void*(*ui_getvaluefunc2)(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult); typedef int(*ui_threadfunc)(void*); @@ -318,6 +322,7 @@ void *document; void *window; void *eventdata; + int eventdatatype; int intval; int set; }; @@ -405,6 +410,8 @@ UiObserver *observers; }; +typedef void (*ui_list_init_func)(UiContext *ctx, UiList *list, void *userdata); + /* * abstract list */ @@ -470,6 +477,22 @@ int intdata; } UiCondVar; +enum UiEventType { + UI_EVENT_DATA_NULL = 0, + UI_EVENT_DATA_POINTER, + UI_EVENT_DATA_STRING, + UI_EVENT_DATA_INTEGER_VALUE, + UI_EVENT_DATA_STRING_VALUE, + UI_EVENT_DATA_TEXT_VALUE, + UI_EVENT_DATA_DOUBLE_VALUE, + UI_EVENT_DATA_RANGE_VALUE, + UI_EVENT_DATA_LIST_SELECTION, + UI_EVENT_DATA_LIST_ELM, + UI_EVENT_DATA_DND, + UI_EVENT_DATA_SUBLIST, + UI_EVENT_DATA_FILE_LIST +}; + UIEXPORT void ui_init(const char *appname, int argc, char **argv); UIEXPORT const char* ui_appname(); @@ -482,6 +505,8 @@ UIEXPORT void ui_context_destroy(UiContext *ctx); +UIEXPORT UiContext* ui_context_parent(UiContext *ctx); + UIEXPORT void ui_object_ref(UiObject *obj); UIEXPORT int ui_object_unref(UiObject *obj); @@ -489,6 +514,9 @@ UIEXPORT void ui_onopen(ui_callback f, void *userdata); UIEXPORT void ui_onexit(ui_callback f, void *userdata); +UIEXPORT int ui_app_save_settings(void); +UIEXPORT void ui_app_exit_on_shutdown(UiBool exitapp); + UIEXPORT void ui_main(void); UIEXPORT void ui_show(UiObject *obj); UIEXPORT void ui_close(UiObject *obj); @@ -502,17 +530,12 @@ UIEXPORT void* ui_document_new(size_t size); UIEXPORT void ui_document_destroy(void *doc); -UIEXPORT void ui_set_document(UiObject *obj, void *document); // deprecated -UIEXPORT void ui_detach_document(UiObject *obj); // deprecated -UIEXPORT void* ui_get_document(UiObject *obj); // deprecated -UIEXPORT void ui_set_subdocument(void *document, void *sub); // deprecated -UIEXPORT void ui_detach_subdocument(void *document, void *sub); // deprecated UIEXPORT void* ui_get_subdocument(void *document); // deprecated UIEXPORT UiContext* ui_document_context(void *doc); UIEXPORT void ui_attach_document(UiContext *ctx, void *document); -UIEXPORT void ui_detach_document2(UiContext *ctx, void *document); +UIEXPORT void ui_detach_document(UiContext *ctx, void *document); UIEXPORT void ui_widget_set_groups(UiContext *ctx, UIWIDGET widget, ui_enablefunc enable, ...); @@ -531,12 +554,12 @@ // types -UIEXPORT UiInteger* ui_int_new(UiContext *ctx, char *name); -UIEXPORT UiDouble* ui_double_new(UiContext *ctx, char *name); -UIEXPORT UiString* ui_string_new(UiContext *ctx, char *name); -UIEXPORT UiText* ui_text_new(UiContext *ctx, char *name); -UIEXPORT UiRange* ui_range_new(UiContext *ctx, char *name); -UIEXPORT UiGeneric* ui_generic_new(UiContext *ctx, char *name); +UIEXPORT UiInteger* ui_int_new(UiContext *ctx, const char *name); +UIEXPORT UiDouble* ui_double_new(UiContext *ctx, const char *name); +UIEXPORT UiString* ui_string_new(UiContext *ctx, const char *name); +UIEXPORT UiText* ui_text_new(UiContext *ctx, const char *name); +UIEXPORT UiRange* ui_range_new(UiContext *ctx, const char *name); +UIEXPORT UiGeneric* ui_generic_new(UiContext *ctx, const char *name); #define ui_get(v) _Generic(v, \ UiInteger*: ui_int_get, \ @@ -558,6 +581,8 @@ UIEXPORT char* ui_string_get(UiString *s); UIEXPORT void ui_text_set(UiText *s, const char* value); UIEXPORT char* ui_text_get(UiText *s); +UIEXPORT void ui_generic_set_image(UiGeneric *g, void *img); +UIEXPORT void* ui_generic_get_image(UiGeneric *g); UIEXPORT void ui_var_set_int(UiContext *ctx, const char *name, int64_t value); UIEXPORT int64_t ui_var_get_int(UiContext *ctx, const char *name); @@ -574,7 +599,8 @@ UIEXPORT void ui_notify_evt(UiObserver *observer, UiEvent *event); -UIEXPORT UiList* ui_list_new(UiContext *ctx, char *name); +UIEXPORT UiList* ui_list_new(UiContext *ctx, const char *name); +UIEXPORT UiList* ui_list_new2(UiContext *ctx, const char *name, ui_list_init_func init, void *userdata); UIEXPORT void ui_list_free(UiList *list); UIEXPORT void* ui_list_first(UiList *list); UIEXPORT void* ui_list_next(UiList *list); @@ -624,6 +650,15 @@ UIEXPORT void ui_setop_enable(int set); UIEXPORT int ui_get_setop(void); + +UIEXPORT void ui_global_list_initializer(ui_list_init_func func, void *userdata); +UIEXPORT void ui_list_class_set_first(UiList *list, void*(*first)(UiList *list)); +UIEXPORT void ui_list_class_set_next(UiList *list, void*(*next)(UiList *list)); +UIEXPORT void ui_list_class_set_get(UiList *list, void*(*get)(UiList *list, int i)); +UIEXPORT void ui_list_class_set_count(UiList *list, int(*count)(UiList *list)); +UIEXPORT void ui_list_class_set_data(UiList *list, void *data); +UIEXPORT void ui_list_class_set_iter(UiList *list, void *iter); + #ifdef __cplusplus } #endif
--- a/ui/ui/tree.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/ui/tree.h Sun Jul 20 22:04:39 2025 +0200 @@ -78,12 +78,23 @@ int *columnsize; /* + * void*(*ui_getvaluefunc)(void *elm, int col); + * * function for translating model data to view data - * first argument is the pointer returned by UiList->get or UiTree->get + * first argument is the pointer returned by UiList first|next|get * second argument is the column index * TODO: return */ - void*(*getvalue)(void*, int); + ui_getvaluefunc getvalue; + + /* + * void*(*ui_getvaluefunc2)(UiList *list, void *elm, int row, int col, void *userdata) + * + * alternative for getvalue + */ + ui_getvaluefunc2 getvalue2; + + void *getvalue2data; }; struct UiListCallbacks { @@ -104,7 +115,7 @@ }; struct UiListArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -121,6 +132,8 @@ char **static_elements; size_t static_nelm; ui_getvaluefunc getvalue; + ui_getvaluefunc2 getvalue2; + void *getvalue2data; ui_callback onactivate; void* onactivatedata; ui_callback onselection; @@ -130,14 +143,14 @@ ui_callback ondragcomplete; void* ondragcompletedata; ui_callback ondrop; - void* ondropsdata; + void* ondropdata; UiBool multiselection; UiMenuBuilder *contextmenu; const int *groups; }; -typedef void (*ui_sublist_getvalue_func)(void *sublist_userdata, void *rowdata, int index, UiSubListItem *item); +typedef void (*ui_sublist_getvalue_func)(UiList *list, void *sublist_userdata, void *rowdata, int index, UiSubListItem *item, void *userdata); struct UiSubList { UiList *value; @@ -171,7 +184,7 @@ }; struct UiSourceListArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -220,6 +233,11 @@ ui_sublist_getvalue_func getvalue; /* + * getvalue_func userdata + */ + void *getvaluedata; + + /* * activated when a list item is selected */ ui_callback onactivate; @@ -240,21 +258,28 @@ 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__ } ) +#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 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 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_badge(UiSubListItem *item, const char *badge); +UIEXPORT void ui_sublist_item_set_eventdata(UiSubListItem *item, void *eventdata); #ifdef __cplusplus
--- a/ui/ui/webview.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/ui/webview.h Sun Jul 20 22:04:39 2025 +0200 @@ -56,9 +56,9 @@ const int* groups; } UiWebviewArgs; -#define ui_webview(obj, ...) ui_webview_create(obj, (UiWebviewArgs){ __VA_ARGS__ } ) +#define ui_webview(obj, ...) ui_webview_create(obj, &(UiWebviewArgs){ __VA_ARGS__ } ) -UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs args); +UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs *args); void ui_webview_load_url(UiGeneric *g, const char *url);
--- a/ui/ui/widget.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/ui/widget.h Sun Jul 20 22:04:39 2025 +0200 @@ -35,7 +35,7 @@ #endif typedef struct UiWidgetArgs { - UiTri fill; + UiBool fill; UiBool hexpand; UiBool vexpand; UiBool hfill; @@ -48,21 +48,21 @@ } UiWidgetArgs; #ifdef UI_GTK -typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs args, void *userdata); +typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs *args, void *userdata); #elif defined(UI_QT) -typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs args, void *userdata); +typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs *args, void *userdata); #elif defined(UI_MOTIF) -typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs args, void *userdata, Widget parent, Arg *a, int n); +typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs *args, void *userdata, Widget parent, Arg *a, int n); #elif defined(UI_COCOA) -typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs args, void *userdata); +typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs *args, void *userdata); #elif defined(UI_WINUI) -typedef UIWIDGET(*ui_createwidget_func)(UiObject *obj, UiWidgetArgs args, void *userdata); +typedef UIWIDGET(*ui_createwidget_func)(UiObject *obj, UiWidgetArgs *args, void *userdata); #elif defined(UI_WIN32) -typedef UIWIDGET(*ui_createwidget_func)(UiObject *obj, UiWidgetArgs args, void *userdata); +typedef UIWIDGET(*ui_createwidget_func)(UiObject *obj, UiWidgetArgs *args, void *userdata); #endif -UIEXPORT UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs args); +UIEXPORT UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs *args); -#define ui_customwidget(obj, create_widget, userdata, ...) ui_customwidget_create(obj, create_widget, userdata, (UiWidgetArgs) { __VA_ARGS__ }) +#define ui_customwidget(obj, create_widget, userdata, ...) ui_customwidget_create(obj, create_widget, userdata, &(UiWidgetArgs) { __VA_ARGS__ }) UIEXPORT UIWIDGET ui_separator_create(UiObject *obj, UiWidgetArgs *args);
--- a/ui/ui/window.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/ui/window.h Sun Jul 20 22:04:39 2025 +0200 @@ -75,16 +75,16 @@ UIEXPORT UiObject *ui_window(const char *title, void *window_data); UIEXPORT UiObject *ui_sidebar_window(const char *title, void *window_data); UIEXPORT UiObject *ui_simple_window(const char *title, void *window_data); -UIEXPORT UiObject *ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs args); +UIEXPORT UiObject *ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args); -#define ui_dialog_window(parent, ...) ui_dialog_window_create(parent, (UiDialogWindowArgs){ __VA_ARGS__ }); -#define ui_dialog_window0(parent) ui_dialog_window_create(parent, (UiDialogWindowArgs){ 0 }); +#define ui_dialog_window(parent, ...) ui_dialog_window_create(parent, &(UiDialogWindowArgs){ __VA_ARGS__ }); +#define ui_dialog_window0(parent) ui_dialog_window_create(parent, &(UiDialogWindowArgs){ 0 }); UIEXPORT void ui_window_size(UiObject *obj, int width, int height); -#define ui_dialog(parent, ...) ui_dialog_create(parent, (UiDialogArgs){ __VA_ARGS__ } ) +#define ui_dialog(parent, ...) ui_dialog_create(parent, &(UiDialogArgs){ __VA_ARGS__ } ) -UIEXPORT void ui_dialog_create(UiObject *parent, UiDialogArgs args); +UIEXPORT void ui_dialog_create(UiObject *parent, UiDialogArgs *args); UIEXPORT void ui_openfiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata); UIEXPORT void ui_savefiledialog(UiObject *obj, const char *name, ui_callback file_selected_callback, void *cbdata);
--- a/ui/win32/Makefile Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/win32/Makefile Sun Jul 20 22:04:39 2025 +0200 @@ -31,3 +31,6 @@ $(UI_LIB): $(OBJ) $(AR) $(ARFLAGS) $(UI_LIB) $(OBJ) + +$(UI_SHLIB): $(OBJ) + $(CC) -o $(UI_SHLIB) $(LDFLAGS) $(SHLIB_LDFLAGS) $(TK_LDFLAGS) $(OBJ) -L../build/$(BUILD_LIB_DIR) -lucx
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/win32/button.c Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,33 @@ +/* + * 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" + +UIWIDGET ui_button_create(UiObject *obj, UiButtonArgs *args) { + return NULL; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/win32/button.h Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,35 @@ +/* + * 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 "../ui/button.h" +#include "container.h" + +#endif //BUTTON_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/win32/container.c Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,48 @@ +/* + * 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 "container.h" + + +/* ---------------------------- Box Container ---------------------------- */ + +static UIWIDGET box_create(UiObject *obj, UiContainerArgs *args, UiBoxOrientation orientation) { + return NULL; +} + +// public +UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs *args) { + return box_create(obj, args, UI_BOX_VERTICAL); +} + +// public +UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs *args) { + return box_create(obj, args, UI_BOX_HORIZONTAL); +} + +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/win32/container.h Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,91 @@ +/* +* 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 + +#include "../ui/container.h" + +#define CONTAINER_H + +#define UI_APPLY_LAYOUT(layout, args) \ + layout.fill = args->fill; \ + layout.hexpand = args->hexpand; \ + layout.vexpand = args->vexpand; \ + layout.hfill = args->hfill; \ + layout.vfill = args->vfill; \ + layout.override_defaults = args->override_defaults; \ + layout.colspan = args->colspan; \ + layout.rowspan = args->rowspan + +typedef struct UiLayout UiLayout; + +struct UiLayout { + UiBool fill; + UiBool newline; + char *label; + UiBool hexpand; + UiBool vexpand; + UiBool hfill; + UiBool vfill; + UiBool override_defaults; + int width; + int colspan; + int rowspan; +}; + +enum UiBoxOrientation { + UI_BOX_VERTICAL = 0, + UI_BOX_HORIZONTAL +}; +typedef enum UiBoxOrientation UiBoxOrientation; + +enum UiContainerType { + UI_CONTAINER_GENERIC = 0, + UI_CONTAINER_TABVIEW +}; +typedef enum UiContainerType UiContainerType; + +typedef struct UiContainerPrivate UiContainerPrivate; + +typedef struct UiRect { + int x; + int y; + int width; + int height; +} UiRect; + + +struct UiContainerPrivate { + UiContainerX container; + void (*prepare)(UiContainerPrivate*, UiRect*); + void (*add)(UiContainerPrivate*, UiRect*, W32Widget*); + UiContainerType type; + UiLayout layout; +}; + +#endif //CONTAINER_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/win32/grid.c Sun Jul 20 22:04:39 2025 +0200 @@ -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. + */ + +#include "grid.h" + +#include "../../ucx/cx/array_list.h" +#include "../common/context.h" + +UiGridLayout* ui_grid_container(UiObject *obj, HWND control, short padding, short columnspacing, short rowspacing) { + UiGridLayout *grid = cxZalloc(obj->ctx->allocator, sizeof(UiGridLayout)); + grid->hwnd = control; + grid->widgets = cxArrayListCreate(obj->ctx->allocator, NULL, sizeof(GridElm), 32); + grid->padding = padding; + grid->columnspacing = columnspacing; + grid->rowspacing = rowspacing; + return grid; +} + +void ui_grid_add_widget( + UiGridLayout *grid, + short x, + short y, + W32Widget *widget, + GridLayoutInfo *layout) +{ + GridElm elm; + elm.widget = widget; + elm.x = x; + elm.y = y; + elm.layout = *layout; + cxListAdd(grid->widgets, elm); +} + +void ui_grid_layout(UiGridLayout *grid) { + // TODO +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/win32/grid.h Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,82 @@ +/* +* 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 GRID_H +#define GRID_H + +#include "container.h" +#include <stdbool.h> +#include <cx/array_list.h> + +typedef struct GridElm { + W32Widget *widget; + short x; + short y; + GridLayoutInfo layout; +} GridElm; + +typedef struct GridLayoutInfo { + short margin_left; + short margin_right; + short margin_top; + short margin_bottom; + short colspan; + short rowspan; + short preferred_width; + short preferred_height; + bool hexpand; + bool vexpand; + bool hfill; + bool vfill; +} GridLayoutInfo; + +typedef struct UiGridLayout { + HWND hwnd; + + short padding; + short columnspacing; + short rowspacing; + + /* + * list element type: GridElm + */ + CxList *widgets; + +} UiGridLayout; + +UiGridLayout* ui_grid_container(UiObject *obj, HWND control, short padding, short columnspacing, short rowspacing); + +void ui_grid_add_widget( + UiGridLayout *grid, + short x, + short y, + W32Widget *widget, + GridLayoutInfo *layout); + +void ui_grid_layout(UiGridLayout *grid); + +#endif //GRID_H
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/win32/image.c Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,37 @@ +/* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2024 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 "image.h" + +void ui_image_ref(UIIMAGE img) { + // TODO +} + +void ui_image_unref(UIIMAGE img) { + // TODO +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/win32/image.h Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,42 @@ +/* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2024 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 IMAGE_H +#define IMAGE_H + +#include "../ui/image.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif //IMAGE_H
--- a/ui/win32/objs.mk Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/win32/objs.mk Sun Jul 20 22:04:39 2025 +0200 @@ -29,7 +29,11 @@ WIN32_SRC_DIR = ui/win32/ WIN32_OBJPRE = $(OBJ_DIR)$(WIN32_SRC_DIR) -WIN32OBJ = toolkit.obj +WIN32OBJ = toolkit.obj +WIN32OBJ += window.obj +WIN32OBJ += image.obj +WIN32OBJ += container.obj +WIN32OBJ += button.obj TOOLKITOBJS += $(WIN32OBJ:%=$(WIN32_OBJPRE)%) TOOLKITSOURCE += $(WIN32OBJ:%.obj=win32/%.c)
--- a/ui/win32/toolkit.c Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/win32/toolkit.c Sun Jul 20 22:04:39 2025 +0200 @@ -29,6 +29,11 @@ #include "toolkit.h" #include "Windows.h" +#include "window.h" + +#include "../common/menu.h" +#include "../common/toolbar.h" +#include "../common/document.h" #include "../common/properties.h" #include <stdio.h> @@ -44,7 +49,15 @@ void *exit_data; void ui_init(const char *appname, int argc, char **argv) { - application_name = appname; + application_name = appname; + + uic_init_global_context(); + uic_docmgr_init(); + uic_menu_init(); + uic_toolbar_init(); + uic_load_app_properties(); + + ui_window_init(); } const char* ui_appname() {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/win32/window.c Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,98 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2024 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 "Windows.h" + +#include "../common/object.h" + + +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> + + +static HINSTANCE hInstance; + +static const char *mainWindowClass = "UiMainWindow"; + +LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + switch(uMsg) { + case WM_DESTROY: + PostQuitMessage(0); + break; + default: + return DefWindowProc(hwnd, uMsg, wParam, lParam); + } + return 0; +} + +void ui_window_init(void) { + hInstance = GetModuleHandle(NULL); + + WNDCLASSEX wc = { sizeof(WNDCLASSEX) }; + wc.lpfnWndProc = WindowProc; + wc.hInstance = hInstance; + wc.lpszClassName = mainWindowClass; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + + if(!RegisterClassExA(&wc)) { + MessageBox(NULL, "RegisterClassEx failed", "Error", MB_ICONERROR); + exit(-1); + } +} + +static UiObject* create_window(const char *title, void *window_data, bool simple) { + UiObject *obj = uic_object_new_toplevel(); + obj->window = window_data; + + HWND hwnd = CreateWindowExA( + 0, + "UiMainWindow", + title, + WS_OVERLAPPEDWINDOW | WS_VISIBLE, + CW_USEDEFAULT, + CW_USEDEFAULT, + 800, + 600, + NULL, + NULL, + hInstance, + NULL); + + ShowWindow(hwnd, SW_SHOWNORMAL); + UpdateWindow(hwnd); + + return obj; +} + +UiObject *ui_window(const char *title, void *window_data) { + return create_window(title, window_data, FALSE); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/win32/window.h Sun Jul 20 22:04:39 2025 +0200 @@ -0,0 +1,51 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2024 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 WINDOW_H +#define WINDOW_H + +#include <inttypes.h> +#include "../ui/window.h" +#include "../common/context.h" +#include "../common/object.h" + +#include "toolkit.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +void ui_window_init(void); + +#ifdef __cplusplus +} +#endif + +#endif /* WINDOW_H */ +
--- a/ui/winui/container.cpp Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/winui/container.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -34,6 +34,7 @@ #include "../common/object.h" #include "util.h" +#include "../ui/widget.h" void ui_container_begin_close(UiObject* obj) { @@ -51,13 +52,13 @@ } -UIEXPORT UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs args) { +UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs *args) { UiObject* current = uic_current_obj(obj); UIWIDGET widget = create_widget(obj, args, userdata); FrameworkElement w = widget->uielement.as<FrameworkElement>(); - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); current->container->Add(w, false); @@ -66,9 +67,9 @@ // --------------------- UiBoxContainer --------------------- -static UIWIDGET ui_box(UiObject* obj, UiContainerArgs args, UiBoxContainerType type) { +static UIWIDGET ui_box(UiObject* obj, UiContainerArgs *args, UiBoxContainerType type) { UiObject* current = uic_current_obj(obj); - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); Grid grid = Grid(); current->container->Add(grid, true); @@ -78,18 +79,18 @@ ui_context_add_widget_destructor(current->ctx, widget); UiObject* newobj = uic_object_new(obj, widget); - newobj->container = new UiBoxContainer(grid, type, args.margin, args.spacing); + newobj->container = new UiBoxContainer(grid, type, args->margin, args->spacing); ui_context_add_container_destructor(current->ctx, newobj->container); uic_obj_add(obj, newobj); return widget; } -UIWIDGET ui_vbox_create(UiObject* obj, UiContainerArgs args) { +UIWIDGET ui_vbox_create(UiObject* obj, UiContainerArgs *args) { return ui_box(obj, args, UI_BOX_CONTAINER_VBOX); } -UIWIDGET ui_hbox_create(UiObject* obj, UiContainerArgs args) { +UIWIDGET ui_hbox_create(UiObject* obj, UiContainerArgs *args) { return ui_box(obj, args, UI_BOX_CONTAINER_HBOX); } @@ -161,9 +162,9 @@ // --------------------- UiGridContainer --------------------- -UIWIDGET ui_grid_create(UiObject* obj, UiContainerArgs args) { +UIWIDGET ui_grid_create(UiObject* obj, UiContainerArgs *args) { UiObject* current = uic_current_obj(obj); - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); Grid grid = Grid(); current->container->Add(grid, true); @@ -173,7 +174,7 @@ ui_context_add_widget_destructor(current->ctx, widget); UiObject* newobj = uic_object_new(obj, widget); - newobj->container = new UiGridContainer(grid, args.margin, args.columnspacing, args.rowspacing); + newobj->container = new UiGridContainer(grid, args->margin, args->columnspacing, args->rowspacing); ui_context_add_container_destructor(current->ctx, newobj->container); uic_obj_add(obj, newobj); @@ -303,7 +304,7 @@ // --------------------- UI Frame --------------------- -UIWIDGET ui_frame_create(UiObject* obj, UiFrameArgs args) { +UIWIDGET ui_frame_create(UiObject* obj, UiFrameArgs *args) { // create a grid for the frame, that contains the label and a sub-frame Grid frame = Grid(); @@ -320,7 +321,7 @@ // label int row = 0; - if (args.label) { + if (args->label) { RowDefinition rowdefLabel = RowDefinition(); gl.GridUnitType = GridUnitType::Auto; gl.Value = 0; @@ -328,7 +329,7 @@ frame.RowDefinitions().Append(rowdefLabel); TextBlock label = TextBlock(); - wchar_t* wlabel = str2wstr(args.label, nullptr); + wchar_t* wlabel = str2wstr(args->label, nullptr); winrt::hstring hstr(wlabel); label.Text(hstr); free(wlabel); @@ -359,7 +360,7 @@ // add frame to the parent container UiObject* current = uic_current_obj(obj); - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); current->container->Add(frame, true); UIElement elm = frame; @@ -368,18 +369,18 @@ // sub container UiContainer* ctn = nullptr; - switch (args.subcontainer) { + switch (args->subcontainer) { default: case UI_CONTAINER_VBOX: { - ctn = new UiBoxContainer(workarea, UI_BOX_CONTAINER_VBOX, args.margin, args.spacing); + ctn = new UiBoxContainer(workarea, UI_BOX_CONTAINER_VBOX, args->margin, args->spacing); break; } case UI_CONTAINER_HBOX: { - ctn = new UiBoxContainer(workarea, UI_BOX_CONTAINER_HBOX, args.margin, args.spacing); + ctn = new UiBoxContainer(workarea, UI_BOX_CONTAINER_HBOX, args->margin, args->spacing); break; } case UI_CONTAINER_GRID: { - ctn = new UiGridContainer(workarea, args.margin, args.columnspacing, args.rowspacing); + ctn = new UiGridContainer(workarea, args->margin, args->columnspacing, args->rowspacing); break; } } @@ -394,18 +395,18 @@ // --------------------- UI Expander --------------------- -UIWIDGET ui_expander_create(UiObject* obj, UiFrameArgs args) { +UIWIDGET ui_expander_create(UiObject* obj, UiFrameArgs *args) { Expander expander = Expander(); - if (args.label) { - wchar_t* wlabel = str2wstr(args.label, nullptr); + if (args->label) { + wchar_t* wlabel = str2wstr(args->label, nullptr); expander.Header(box_value(wlabel)); free(wlabel); } - expander.IsExpanded(args.isexpanded); + expander.IsExpanded(args->isexpanded); // add frame to the parent container UiObject* current = uic_current_obj(obj); - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); current->container->Add(expander, true); UIElement elm = expander; @@ -416,18 +417,18 @@ expander.Content(content); UiContainer* ctn = nullptr; - switch (args.subcontainer) { + switch (args->subcontainer) { default: case UI_CONTAINER_VBOX: { - ctn = new UiBoxContainer(content, UI_BOX_CONTAINER_VBOX, args.margin, args.spacing); + ctn = new UiBoxContainer(content, UI_BOX_CONTAINER_VBOX, args->margin, args->spacing); break; } case UI_CONTAINER_HBOX: { - ctn = new UiBoxContainer(content, UI_BOX_CONTAINER_HBOX, args.margin, args.spacing); + ctn = new UiBoxContainer(content, UI_BOX_CONTAINER_HBOX, args->margin, args->spacing); break; } case UI_CONTAINER_GRID: { - ctn = new UiGridContainer(content, args.margin, args.columnspacing, args.rowspacing); + ctn = new UiGridContainer(content, args->margin, args->columnspacing, args->rowspacing); break; } } @@ -442,12 +443,12 @@ // --------------------- UI ScrolledWindow --------------------- -UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs args) { +UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs *args) { ScrollViewer scrollW = ScrollViewer(); // add frame to the parent container UiObject* current = uic_current_obj(obj); - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); current->container->Add(scrollW, true); UIElement elm = scrollW; @@ -459,18 +460,18 @@ scrollW.Content(content); UiContainer* ctn = nullptr; - switch (args.subcontainer) { + switch (args->subcontainer) { default: case UI_CONTAINER_VBOX: { - ctn = new UiBoxContainer(content, UI_BOX_CONTAINER_VBOX, args.margin, args.spacing); + ctn = new UiBoxContainer(content, UI_BOX_CONTAINER_VBOX, args->margin, args->spacing); break; } case UI_CONTAINER_HBOX: { - ctn = new UiBoxContainer(content, UI_BOX_CONTAINER_HBOX, args.margin, args.spacing); + ctn = new UiBoxContainer(content, UI_BOX_CONTAINER_HBOX, args->margin, args->spacing); break; } case UI_CONTAINER_GRID: { - ctn = new UiGridContainer(content, args.margin, args.columnspacing, args.rowspacing); + ctn = new UiGridContainer(content, args->margin, args->columnspacing, args->rowspacing); break; } } @@ -520,21 +521,21 @@ return newobj; } -static UiTabView* tabview_pivot_create(UiObject* obj, UiTabViewArgs args) { +static UiTabView* tabview_pivot_create(UiObject* obj, UiTabViewArgs *args) { Pivot pivot = Pivot(); UiPivotTabView* tabview = new UiPivotTabView(obj, pivot, args); return tabview; } -UiPivotTabView::UiPivotTabView(UiObject* obj, Pivot pivot, UiTabViewArgs args) { +UiPivotTabView::UiPivotTabView(UiObject* obj, Pivot pivot, UiTabViewArgs *args) { this->current = obj; this->pivot = pivot; - this->subcontainer = args.subcontainer; - this->margin = args.margin; - this->spacing = args.spacing; - this->columnspacing = args.columnspacing; - this->rowspacing = args.rowspacing; + this->subcontainer = args->subcontainer; + this->margin = args->margin; + this->spacing = args->spacing; + this->columnspacing = args->columnspacing; + this->rowspacing = args->rowspacing; } UiObject* UiPivotTabView::AddTab(const char* label, int index) { @@ -568,7 +569,7 @@ } -static UiTabView* tabview_invisible_create(UiObject *obj, UiTabViewArgs args) { +static UiTabView* tabview_invisible_create(UiObject *obj, UiTabViewArgs *args) { Grid container = Grid(); container.HorizontalAlignment(HorizontalAlignment::Stretch); container.VerticalAlignment(VerticalAlignment::Stretch); @@ -576,14 +577,14 @@ return tabview; } -UiInvisibleTabView::UiInvisibleTabView(UiObject* obj, Grid container, UiTabViewArgs args) { +UiInvisibleTabView::UiInvisibleTabView(UiObject* obj, Grid container, UiTabViewArgs *args) { this->current = obj; this->container = container; - this->subcontainer = args.subcontainer; - this->margin = args.margin; - this->spacing = args.spacing; - this->columnspacing = args.columnspacing; - this->rowspacing = args.rowspacing; + this->subcontainer = args->subcontainer; + this->margin = args->margin; + this->spacing = args->spacing; + this->columnspacing = args->columnspacing; + this->rowspacing = args->rowspacing; this->currentIndex = -1; GridLength gl; @@ -638,7 +639,7 @@ } -static UiTabView* tabview_main_create(UiObject* obj, UiTabViewArgs args) { +static UiTabView* tabview_main_create(UiObject* obj, UiTabViewArgs *args) { TabView tabview = TabView(); tabview.IsAddTabButtonVisible(false); //tabview.CanDragTabs(false); @@ -648,14 +649,14 @@ return uitabview; } -UiMainTabView::UiMainTabView(UiObject* obj, TabView tabview, UiTabViewArgs args) { +UiMainTabView::UiMainTabView(UiObject* obj, TabView tabview, UiTabViewArgs *args) { this->current = obj; this->tabview = tabview; - this->subcontainer = args.subcontainer; - this->margin = args.margin; - this->spacing = args.spacing; - this->columnspacing = args.columnspacing; - this->rowspacing = args.rowspacing; + this->subcontainer = args->subcontainer; + this->margin = args->margin; + this->spacing = args->spacing; + this->columnspacing = args->columnspacing; + this->rowspacing = args->rowspacing; } UiObject* UiMainTabView::AddTab(const char* label, int index) { @@ -691,7 +692,7 @@ } -static UiTabView* tabview_navigationview_create(UiObject* obj, UiTabViewArgs args, UiTabViewType type) { +static UiTabView* tabview_navigationview_create(UiObject* obj, UiTabViewArgs *args, UiTabViewType type) { NavigationView navigationview = NavigationView(); UiNavigationTabView* tabview = new UiNavigationTabView(obj, navigationview, args, type); navigationview.IsBackButtonVisible(NavigationViewBackButtonVisible::Collapsed); @@ -700,14 +701,14 @@ return tabview; } -UiNavigationTabView::UiNavigationTabView(UiObject* obj, NavigationView navigationview, UiTabViewArgs args, UiTabViewType type) { +UiNavigationTabView::UiNavigationTabView(UiObject* obj, NavigationView navigationview, UiTabViewArgs *args, UiTabViewType type) { this->current = obj; this->navigationview = navigationview; this->type = type; - this->margin = args.margin; - this->spacing = args.spacing; - this->columnspacing = args.columnspacing; - this->rowspacing = args.rowspacing; + this->margin = args->margin; + this->spacing = args->spacing; + this->columnspacing = args->columnspacing; + this->rowspacing = args->rowspacing; if (type == UI_TABVIEW_NAVIGATION_TOP) { navigationview.PaneDisplayMode(NavigationViewPaneDisplayMode::Top); @@ -773,8 +774,8 @@ tabview->Select(value); } -UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs args) { - UiTabViewType type = args.tabview == UI_TABVIEW_DEFAULT ? UI_TABVIEW_NAVIGATION_TOP2 : args.tabview; +UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs *args) { + UiTabViewType type = args->tabview == UI_TABVIEW_DEFAULT ? UI_TABVIEW_NAVIGATION_TOP2 : args->tabview; UiTabView* tabview = nullptr; switch (type) { default: { @@ -806,7 +807,7 @@ // add frame to the parent container UiObject* current = uic_current_obj(obj); - UI_APPLY_LAYOUT1(current, args); + UI_APPLY_LAYOUT2(current, args); current->container->Add(tabview->GetFrameworkElement(), true); UIElement elm = tabview->GetFrameworkElement(); @@ -817,7 +818,7 @@ // TODO: add tabview destructor // bind variable - UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.value, args.varname, UI_VAR_INTEGER); + UiVar* var = uic_widget_var(obj->ctx, current->ctx, args->value, args->varname, UI_VAR_INTEGER); if (var) { UiInteger *i = (UiInteger*)var->value; i->obj = tabview; @@ -861,28 +862,28 @@ // TODO: replace placeholder implementation -UIEXPORT UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs args) { +UIEXPORT UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs *args) { UiContainerArgs boxargs = { }; boxargs.fill = UI_OFF; - return ui_hbox_create(obj, boxargs); + return ui_hbox_create(obj, &boxargs); } UIEXPORT void ui_headerbar_start_create(UiObject *obj) { UiContainerArgs boxargs = { }; boxargs.fill = UI_OFF; - ui_hbox_create(obj, boxargs); + ui_hbox_create(obj, &boxargs); } UIEXPORT void ui_headerbar_center_create(UiObject *obj) { UiContainerArgs boxargs = { }; boxargs.fill = UI_OFF; - ui_hbox_create(obj, boxargs); + ui_hbox_create(obj, &boxargs); } UIEXPORT void ui_headerbar_end_create(UiObject *obj) { UiContainerArgs boxargs = { }; boxargs.fill = UI_OFF; - ui_hbox_create(obj, boxargs); + ui_hbox_create(obj, &boxargs); }
--- a/ui/winui/container.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/winui/container.h Sun Jul 20 22:04:39 2025 +0200 @@ -140,7 +140,7 @@ struct UiPivotTabView : UiTabView { Pivot pivot; - UiPivotTabView(UiObject *obj, Pivot pivot, UiTabViewArgs args); + UiPivotTabView(UiObject *obj, Pivot pivot, UiTabViewArgs *args); UiObject* AddTab(const char* label, int index = -1); void Remove(int index); @@ -151,7 +151,7 @@ struct UiMainTabView : UiTabView { TabView tabview; - UiMainTabView(UiObject* obj, TabView tabview, UiTabViewArgs args); + UiMainTabView(UiObject* obj, TabView tabview, UiTabViewArgs *args); UiObject* AddTab(const char* label, int index = -1); void Remove(int index); @@ -164,7 +164,7 @@ UiTabViewType type; std::vector<std::tuple<NavigationViewItem, FrameworkElement> > pages; - UiNavigationTabView(UiObject* obj, NavigationView navigationview, UiTabViewArgs args, UiTabViewType type); + UiNavigationTabView(UiObject* obj, NavigationView navigationview, UiTabViewArgs *args, UiTabViewType type); UiObject* AddTab(const char* label, int index = -1); void Remove(int index); @@ -179,7 +179,7 @@ std::vector<FrameworkElement> pages; int currentIndex; - UiInvisibleTabView(UiObject *obj, Grid container, UiTabViewArgs args); + UiInvisibleTabView(UiObject *obj, Grid container, UiTabViewArgs *args); UiObject* AddTab(const char* label, int index = -1); void Remove(int index);
--- a/ui/winui/image.cpp Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/winui/image.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -47,6 +47,16 @@ UiImageSource::UiImageSource(winrt::Microsoft::UI::Xaml::Media::ImageSource& src) : imgsrc(src) {} +void UiImageSource::ref() { + refcount++; +} + +void UiImageSource::unref() { + if (--refcount == 0) { + delete this; + } +} + UIEXPORT UIWIDGET ui_imageviewer_create(UiObject *obj, UiImageViewerArgs args) { UiObject* current = uic_current_obj(obj); @@ -94,9 +104,10 @@ UiImageSource *imgdata = (UiImageSource*)data; if (g->value) { UiImageSource *prevData = (UiImageSource*)g->value; - delete prevData; + //prevData->unref(); } g->value = imgdata; + //imgdata->ref(); UiWidget* widget = (UiWidget*)g->obj; Image image = widget->uielement.as<Image>(); @@ -117,8 +128,19 @@ UiImageSource *imgdata = new UiImageSource(src); obj->set(obj, imgdata, UI_IMAGE_OBJECT_TYPE); + imgdata->unref(); free(wpath); return 0; } + +void ui_image_ref(UIIMAGE img) { + UiImageSource* imgdata = (UiImageSource*)img; + imgdata->ref(); +} + +void ui_image_unref(UIIMAGE img) { + UiImageSource* imgdata = (UiImageSource*)img; + imgdata->unref(); +}
--- a/ui/winui/image.h Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/winui/image.h Sun Jul 20 22:04:39 2025 +0200 @@ -32,10 +32,16 @@ #include "../ui/image.h" class UiImageSource { + unsigned int refcount = 1; + public: winrt::Microsoft::UI::Xaml::Media::ImageSource imgsrc { nullptr }; UiImageSource(winrt::Microsoft::UI::Xaml::Media::ImageSource& src); + + void ref(); + + void unref(); };
--- a/ui/winui/text.cpp Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/winui/text.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -68,7 +68,6 @@ if (var) { UiText* value = (UiText*)var->value; value->obj = widget; - value->undomgr = NULL; value->set = ui_textarea_set; value->get = ui_textarea_get; value->getsubstr = ui_textarea_getsubstr;
--- a/ui/winui/window.cpp Sat Apr 05 17:57:04 2025 +0200 +++ b/ui/winui/window.cpp Sun Jul 20 22:04:39 2025 +0200 @@ -147,8 +147,7 @@ } UIEXPORT UiObject* ui_simple_window(const char *title, void *window_data) { - CxMempool* mp = cxMempoolCreateSimple(256); - UiObject* obj = (UiObject*)cxCalloc(mp->allocator, 1, sizeof(UiObject)); + UiObject* obj = uic_object_new_toplevel(); obj->ctx = uic_context(obj, mp); obj->window = window_data;
--- a/ui/wpf/Makefile Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -# -# 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. -# - -$(WPF_OBJPRE)%.o: wpf/%.c - $(CC) -o $@ -c $(CFLAGS) $< - -$(UI_LIB): $(OBJ) uiw - $(AR) $(ARFLAGS) $(UI_LIB) $(OBJ) - -uiw: - cd wpf/UIwrapper; $(MSBUILD) - cp $(BUILD_ROOT)/build/UIwrapper/UIwrapper.dll $(BUILD_ROOT)/build/bin/ - cp $(BUILD_ROOT)/build/UIcore/UIcore.dll $(BUILD_ROOT)/build/bin/
--- a/ui/wpf/UIcore/Application.cs Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Windows; - -namespace UI -{ - public class Application - { - private static Application instance; - - private System.Windows.Application application; - - private Thread thread; - - public String Name; - - public IApplicationCallbacks callbacks; - - public List<Window> Windows = new List<Window>(); - public ApplicationMenu Menu = new ApplicationMenu(); - public MainToolBar ToolBar = new MainToolBar(); - - private Application() : base() - { - thread = new Thread(() => RunApplication()); - thread.SetApartmentState(ApartmentState.STA); - } - - public static Application GetInstance() - { - if (instance == null) - { - instance = new Application(); - GC.KeepAlive(instance); - } - return instance; - } - - public Thread Start() - { - thread.Start(); - return thread; - } - - private void RunApplication() - { - application = new System.Windows.Application(); - - if(callbacks != null) - { - callbacks.OnStartup(); - } - application.Run(); - if(callbacks != null) - { - callbacks.OnExit(); - } - } - - public void AddWindow(Window window) - { - Windows.Add(window); - } - - public void RemoveWindow(Window window) - { - Windows.Remove(window); - if (Windows.Count == 0) - { - application.Shutdown(); - } - } - } - - public class ResultExec<T> - { - public T Result; - public Func<T> Func; - - public void Exec() - { - Result = Func.Invoke(); - } - } - - public class VoidExec - { - public Action Action; - - public void Exec() - { - Action.Invoke(); - } - } - - public interface IApplicationCallbacks - { - void OnStartup(); - void OnOpen(); - void OnExit(); - } -}
--- a/ui/wpf/UIcore/Container.cs Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,321 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; - -namespace UI -{ - public interface Container - { - Layout Layout { get; set; } - - void Add(UIElement control, bool fill); - } - - public class Layout - { - public bool? Fill { get; set; } - public bool Hexpand { get; set; } - public bool Vexpand { get; set; } - public bool NewLine { get; set; } - public int GridWidth { get; set; } - public String Label { get; set; } - - public Layout() - { - Reset(); - } - - public bool IsFill(bool fill) - { - if (Fill != null) - { - - return (bool)Fill; - } - return fill; - } - - public void Reset() - { - Fill = null; - Hexpand = false; - Vexpand = false; - NewLine = false; - GridWidth = 1; - Label = null; - } - } - - public enum BoxOrientation - { - VERTICAL, - HORIZONTAL - } - - public class BoxContainer : Grid, Container - { - public Layout Layout { get; set; } - - private BoxOrientation Orientation; - private int Spacing; - - private int x = 0; - private int y = 0; - - private bool filled = false; - - public BoxContainer(BoxOrientation orientation, int margin, int spacing) : base() - { - Layout = new Layout(); - Margin = new Thickness(margin); - Spacing = spacing; - - Orientation = orientation; - if(Orientation == BoxOrientation.HORIZONTAL) - { - RowDefinition row = new RowDefinition(); - row.Height = new GridLength(1, GridUnitType.Star); - RowDefinitions.Add(row); - } - else - { - ColumnDefinition col = new ColumnDefinition(); - col.Width = new GridLength(1, GridUnitType.Star); - ColumnDefinitions.Add(col); - } - } - - public BoxContainer(Container parent, BoxOrientation orientation, int margin, int spacing) : this(orientation, margin, spacing) - { - parent.Add(this, true); - } - - public void Add(UIElement control, bool fill) - { - fill = Layout.IsFill(fill); - - if(Orientation == BoxOrientation.HORIZONTAL) - { - if(Spacing > 0) - { - ColumnDefinition spaceCol = new ColumnDefinition(); - spaceCol.Width = new GridLength(Spacing, GridUnitType.Pixel); - ColumnDefinitions.Add(spaceCol); - x++; - } - - ColumnDefinition col = new ColumnDefinition(); - if(filled && fill) - { - fill = false; - Console.WriteLine("BoxContainer can only contain one filled control"); - } - if(fill) - { - col.Width = new GridLength(1, GridUnitType.Star); - filled = true; - } - else - { - col.Width = GridLength.Auto; - } - ColumnDefinitions.Add(col); - } - else - { - if (Spacing > 0) - { - RowDefinition spaceRow = new RowDefinition(); - spaceRow.Height = new GridLength(Spacing, GridUnitType.Pixel); - RowDefinitions.Add(spaceRow); - y++; - } - - RowDefinition row = new RowDefinition(); - if (filled && fill) - { - fill = false; - Console.WriteLine("BoxContainer can only contain one filled control"); - } - if(fill) - { - row.Height = new GridLength(1, GridUnitType.Star); - filled = true; - } - else - { - row.Height = GridLength.Auto; - } - RowDefinitions.Add(row); - } - - Grid.SetColumn(control, x); - Grid.SetRow(control, y); - Children.Add(control); - - if(Orientation == BoxOrientation.HORIZONTAL) - { - x++; - } - else - { - y++; - } - - Layout.Reset(); - } - } - - public class GridContainer : Grid, Container - { - public Layout Layout { get; set; } - - private int X = 0; - private int Y = 0; - private int CurrentWidth = 0; - private int CurrentHeight = 0; - - private int ColSpacing; - private int RowSpacing; - - public GridContainer(Container parent, int margin, int colspacing, int rowspacing) : base() - { - Layout = new Layout(); - - Margin = new Thickness(margin); - ColSpacing = colspacing; - RowSpacing = rowspacing; - - parent.Add(this, true); - } - - public void Add(UIElement control, bool fill) - { - if(Layout.NewLine) - { - X = 0; - Y++; - } - - ColumnDefinition col; - RowDefinition row; - bool getcol = false; - if(X >= CurrentWidth) - { - if (ColSpacing > 0 && X != 0) - { - ColumnDefinition spaceCol = new ColumnDefinition(); - spaceCol.Width = new GridLength(ColSpacing, GridUnitType.Pixel); - ColumnDefinitions.Add(spaceCol); - X++; - } - - col = new ColumnDefinition(); - col.Width = GridLength.Auto; - ColumnDefinitions.Add(col); - - CurrentWidth = X + 1; - } - else - { - if (ColSpacing > 0 && X % 2 > 0) - { - X++; - } - col = ColumnDefinitions.ElementAt(X); - } - - if(getcol) - { - col = ColumnDefinitions.ElementAt(X); - } - - if (Y >= CurrentHeight) - { - if (RowSpacing > 0 && Y != 0) - { - RowDefinition spaceRow = new RowDefinition(); - spaceRow.Height = new GridLength(RowSpacing, GridUnitType.Pixel); - RowDefinitions.Add(spaceRow); - Y++; - } - - row = new RowDefinition(); - row.Height = GridLength.Auto; - RowDefinitions.Add(row); - CurrentHeight = Y + 1; - } - else - { - row = RowDefinitions.ElementAt(Y); - } - - if(Layout.Hexpand) - { - col.Width = new GridLength(1, GridUnitType.Star); - } - if(Layout.Vexpand) - { - row.Height = new GridLength(1, GridUnitType.Star); - } - - int gridwidth = Layout.GridWidth; - if(gridwidth > 1) - { - gridwidth++; - } - - Grid.SetColumn(control, X); - Grid.SetRow(control, Y); - Grid.SetColumnSpan(control, gridwidth); - Children.Add(control); - - Layout.Reset(); - X += gridwidth; - } - } - - public class ScrollViewerContainer : ScrollViewer, Container - { - public Layout Layout { get; set; } - - public ScrollViewerContainer(Container parent) : base() - { - Layout = new Layout(); - - HorizontalScrollBarVisibility = ScrollBarVisibility.Auto; - VerticalScrollBarVisibility = ScrollBarVisibility.Auto; - - parent.Add(this, true); - } - - public void Add(UIElement control, bool fill) - { - Content = control; - } - } - - public class TabViewContainer : TabControl, Container - { - public Layout Layout { get; set; } - - public TabViewContainer(Container parent) : base() - { - Layout = new Layout(); - parent.Add(this, true); - } - - public void Add(UIElement control, bool fill) - { - TabItem tab = new TabItem(); - tab.Header = Layout.Label != null ? Layout.Label : "New Tab"; - Items.Add(tab); - tab.Content = control; - Layout.Reset(); - } - } -}
--- a/ui/wpf/UIcore/Controls.cs Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; - -namespace UI -{ - public class Controls - { - public static Button Button(Container container, String label, RoutedEventHandler e) - { - Button button = new Button(); - button.Content = label; - container.Add(button, false); - - button.Click += e; - - return button; - } - - public static Label Label(Container container, String str, int alignment) - { - HorizontalAlignment a; - switch (alignment) - { - case 0: a = HorizontalAlignment.Left; break; - case 1: a = HorizontalAlignment.Right; break; - case 2: a = HorizontalAlignment.Center; break; - default: a = HorizontalAlignment.Left; break; - } - - Label label = new Label(); - label.HorizontalAlignment = a; - label.Content = str; - container.Add(label, false); - - return label; - } - - public static Label Space(Container container) - { - return Label(container, null, 2); - } - - public static Separator Separator(Container container) - { - Separator separator = new Separator(); - container.Add(separator, false); - return separator; - } - } -}
--- a/ui/wpf/UIcore/DrawingArea.cs Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; -using System.Windows.Shapes; -using System.Diagnostics; - -namespace UI -{ - public class DrawingArea : System.Windows.Controls.Canvas - { - public Action<int,int> resizeCallback; - - public Color Color; - private Brush Brush; - - public DrawingArea(Container container) : base() - { - this.SizeChanged += UpdateSize; - ResetGraphics(); - - container.Add(this, true); - } - - public void UpdateSize(object sender, SizeChangedEventArgs e) - { - if(resizeCallback != null) - { - Children.Clear(); - ResetGraphics(); - - Size s = e.NewSize; - resizeCallback((int)s.Width, (int)s.Height); - } - } - - public void Redraw() - { - if (resizeCallback != null) - { - Children.Clear(); - ResetGraphics(); - - resizeCallback((int)ActualWidth, (int)ActualHeight); - } - - } - - private void ResetGraphics() - { - Color = Color.FromRgb(0, 0, 0); - Brush = System.Windows.Media.Brushes.Black; - } - - public void SetColor(int r, int g, int b) - { - Color = Color.FromRgb((byte)r, (byte)g, (byte)b); - Brush = new SolidColorBrush(Color); - } - - public void DrawLine(int x1, int y1, int x2, int y2) - { - Line line = new Line(); - line.Stroke = Brush; - line.StrokeThickness = 1; - line.SnapsToDevicePixels = true; - - line.X1 = x1; - line.Y1 = y1; - line.X2 = x2; - line.Y2 = y2; - - Children.Add(line); - } - - public void DrawRect(int x, int y, int w, int h, bool fill) - { - Rectangle rect = new Rectangle(); - rect.Stroke = Brush; - rect.StrokeThickness = 1; - rect.SnapsToDevicePixels = true; - if(fill) - { - rect.Fill = Brush; - } - - rect.Width = w; - rect.Height = h; - SetLeft(rect, x); - SetTop(rect, y); - - Children.Add(rect); - } - } -}
--- a/ui/wpf/UIcore/MainToolBar.cs Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,77 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; - -namespace UI -{ - public class MainToolBar - { - Dictionary<string, IToolItem> Items = new Dictionary<string, IToolItem>(); - List<string> Defaults = new List<string>(); - - public MainToolBar() - { - - } - - public bool HasItems() - { - return Defaults.Count > 0 ? true : false; - } - - public void AddDefault(string itemName) - { - Defaults.Add(itemName); - } - - public void AddToolItem(string name, string label, Action<IntPtr> action) - { - ToolItem item = new ToolItem(); - item.Label = label; - item.Action = action; - Items.Add(name, item); - } - - public ToolBarTray CreateToolBarTray(IntPtr objptr) - { - ToolBarTray tray = new ToolBarTray(); - ToolBar toolbar = new ToolBar(); - tray.ToolBars.Add(toolbar); - foreach(string s in Defaults) - { - IToolItem item = Items[s]; - item.AddTo(toolbar, objptr); - } - - return tray; - } - } - - public interface IToolItem - { - void AddTo(System.Windows.Controls.ToolBar toolbar, IntPtr uiobj); - } - - public class ToolItem : IToolItem - { - public string Label { get; set; } - // TODO: icon - public Action<IntPtr> Action { get; set; } - - public void AddTo(System.Windows.Controls.ToolBar toolbar, IntPtr uiobj) - { - Button button = new Button(); - button.Content = Label; - - EventCallback e = new EventCallback(uiobj, Action); - button.Click += e.Callback; - - toolbar.Items.Add(button); - } - } -}
--- a/ui/wpf/UIcore/Menu.cs Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; -using System.Windows.Media; - -namespace UI -{ - public class ApplicationMenu - { - private List<Menu> current = new List<Menu>(); - - public List<Menu> Menus = new List<Menu>(); - - public void AddMenu(String label) - { - current.Clear(); - Menu menu = new Menu(label); - current.Add(menu); - Menus.Add(menu); - } - - public Boolean IsEmpty() - { - return Menus.Count == 0 ? true : false; - } - - public void AddSubMenu(String label) - { - Menu menu = new Menu(label); - current.Last().Items.Add(menu); - current.Add(menu); - } - - public void EndSubMenu() - { - current.Remove(current.Last()); - } - - public void AddMenuItem(String label, Action<IntPtr> action) - { - if(current.Count != 0) - { - MenuItem item = new MenuItem(label, action); - current.Last().Items.Add(item); - } - } - - public System.Windows.Controls.Menu CreateMenu(IntPtr uiobj) - { - System.Windows.Controls.Menu menu = new System.Windows.Controls.Menu(); - menu.Background = new SolidColorBrush(Color.FromRgb(255, 255, 255)); - foreach (Menu m in Menus) - { - System.Windows.Controls.MenuItem i = new System.Windows.Controls.MenuItem(); - i.Header = m.Label; - m.AddItems(i, uiobj); - menu.Items.Add(i); - } - return menu; - } - } - - public interface IMenuItem - { - void AddTo(System.Windows.Controls.MenuItem menu, IntPtr uiobj); - } - - public class Menu : IMenuItem - { - public String Label; - public List<IMenuItem> Items = new List<IMenuItem>(); - - public Menu(String label) - { - Label = label; - } - - public void AddItems(System.Windows.Controls.MenuItem i, IntPtr uiobj) - { - foreach (IMenuItem item in Items) - { - item.AddTo(i, uiobj); - } - } - - void IMenuItem.AddTo(System.Windows.Controls.MenuItem menu, IntPtr uiobj) - { - System.Windows.Controls.MenuItem i = new System.Windows.Controls.MenuItem(); - i.Header = Label; - AddItems(i, uiobj); - menu.Items.Add(i); - } - } - - public class MenuItem : IMenuItem - { - String Label; - Action<IntPtr> Action; - - public MenuItem(String label, Action<IntPtr> action) - { - Label = label; - Action = action; - } - - void IMenuItem.AddTo(System.Windows.Controls.MenuItem menu, IntPtr uiobj) - { - System.Windows.Controls.MenuItem i = new System.Windows.Controls.MenuItem(); - EventCallback cb = new EventCallback(uiobj, Action); - i.Click += cb.Callback; - i.Header = Label; - menu.Items.Add(i); - } - } -}
--- a/ui/wpf/UIcore/Properties/AssemblyInfo.cs Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// Allgemeine Informationen über eine Assembly werden über die folgenden -// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, -// die mit einer Assembly verknüpft sind. -[assembly: AssemblyTitle("UIcore")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("UIcore")] -[assembly: AssemblyCopyright("Copyright © 2015")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar -// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von -// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest. -[assembly: ComVisible(false)] - -// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird -[assembly: Guid("e93c93b6-d270-4178-998f-7e68d9591874")] - -// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: -// -// Hauptversion -// Nebenversion -// Buildnummer -// Revision -// -// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern -// übernehmen, indem Sie "*" eingeben: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")]
--- a/ui/wpf/UIcore/TextArea.cs Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,79 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace UI -{ - public class TextArea : System.Windows.Controls.TextBox - { - public TextArea(Container container, String text, bool textarea) : base() - { - bool fill = false; - if (textarea) - { - AcceptsReturn = true; - IsUndoEnabled = false; // we need our own undo stack - VerticalScrollBarVisibility = System.Windows.Controls.ScrollBarVisibility.Auto; - HorizontalScrollBarVisibility = System.Windows.Controls.ScrollBarVisibility.Auto; - fill = true; - } - else - { - HorizontalScrollBarVisibility = System.Windows.Controls.ScrollBarVisibility.Auto; - MinWidth = 15; - } - - if (text != null) - { - Text = text; - } - - container.Add(this, fill); - } - - - // ------------------ UiText methods ------------------ - - public void SetText(String str) - { - Text = str; - } - - public String GetText() - { - return Text; - } - - public String GetSubString(int begin, int end) - { - return null; - } - - public void Insert(int pos, String str) - { - - } - - public int Position() - { - return CaretIndex; - } - - public int Selection() - { - return 0; - } - - public int Length() - { - return Text.Length; - } - - public void Remove(int begin, int end) - { - - } - } -}
--- a/ui/wpf/UIcore/Toolkit.cs Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,27 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Windows; - -namespace UI -{ - public class EventCallback - { - public IntPtr Object; - public Action<IntPtr> Action; - - public EventCallback(IntPtr uiobj, Action<IntPtr> action) - { - Object = uiobj; - Action = action; - } - - public void Callback(object sender, RoutedEventArgs a) - { - Action.Invoke(Object); - } - } -}
--- a/ui/wpf/UIcore/UIcore.csproj Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,68 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> - <PropertyGroup> - <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> - <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> - <ProjectGuid>{8573F7D8-F05F-4195-9005-1C219B976146}</ProjectGuid> - <OutputType>Library</OutputType> - <AppDesignerFolder>Properties</AppDesignerFolder> - <RootNamespace>UIcore</RootNamespace> - <AssemblyName>UIcore</AssemblyName> - <TargetFrameworkVersion>v4.5</TargetFrameworkVersion> - <FileAlignment>512</FileAlignment> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> - <DebugSymbols>true</DebugSymbols> - <DebugType>full</DebugType> - <Optimize>true</Optimize> - <OutputPath>..\..\..\build\UIcore\</OutputPath> - <DefineConstants>DEBUG;TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - <PlatformTarget>AnyCPU</PlatformTarget> - </PropertyGroup> - <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> - <DebugType>pdbonly</DebugType> - <Optimize>true</Optimize> - <OutputPath>..\..\..\build\UIcore\</OutputPath> - <DefineConstants>TRACE</DefineConstants> - <ErrorReport>prompt</ErrorReport> - <WarningLevel>4</WarningLevel> - </PropertyGroup> - <ItemGroup> - <Reference Include="PresentationCore" /> - <Reference Include="PresentationFramework" /> - <Reference Include="System" /> - <Reference Include="System.Core" /> - <Reference Include="System.Windows" /> - <Reference Include="System.Windows.Controls.Ribbon" /> - <Reference Include="System.Xaml" /> - <Reference Include="System.Xml.Linq" /> - <Reference Include="System.Data.DataSetExtensions" /> - <Reference Include="Microsoft.CSharp" /> - <Reference Include="System.Data" /> - <Reference Include="System.Xml" /> - <Reference Include="WindowsBase" /> - </ItemGroup> - <ItemGroup> - <Compile Include="Container.cs" /> - <Compile Include="Controls.cs" /> - <Compile Include="DrawingArea.cs" /> - <Compile Include="MainToolBar.cs" /> - <Compile Include="Menu.cs" /> - <Compile Include="TextArea.cs" /> - <Compile Include="Toolkit.cs" /> - <Compile Include="Window.cs" /> - <Compile Include="Application.cs" /> - <Compile Include="Properties\AssemblyInfo.cs" /> - </ItemGroup> - <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> - <!-- To modify your build process, add your task inside one of the targets below and uncomment it. - Other similar extension points exist, see Microsoft.Common.targets. - <Target Name="BeforeBuild"> - </Target> - <Target Name="AfterBuild"> - </Target> - --> -</Project> \ No newline at end of file
--- a/ui/wpf/UIcore/Window.cs Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using System.Windows; -using System.Windows.Controls; - -namespace UI -{ - public class MainWindow : Window, Container - { - public Layout Layout - { - get - { - return Container.Layout; - } - set - { - Container.Layout = value; - } - } - - public IntPtr Object; - public Container Container; - - public MainWindow(String title, IntPtr uiobj) - { - Title = title; - Object = uiobj; - Width = 300; - Height = 300; - - Grid windowGrid = new Grid(); - ColumnDefinition column = new ColumnDefinition(); - column.Width = new GridLength(1, GridUnitType.Star); - windowGrid.ColumnDefinitions.Add(column); - this.AddChild(windowGrid); - int rowIndex = 0; - - // menu - Application app = Application.GetInstance(); - System.Windows.Controls.Menu menu = null; - if (!app.Menu.IsEmpty()) - { - menu = app.Menu.CreateMenu(uiobj); - - RowDefinition menuRow = new RowDefinition(); - menuRow.Height = GridLength.Auto; - windowGrid.RowDefinitions.Add(menuRow); - - Grid.SetRow(menu, rowIndex); - Grid.SetColumn(menu, 0); - windowGrid.Children.Add(menu); - rowIndex++; - } - - // toolbar - if(app.ToolBar.HasItems()) - { - System.Windows.Controls.ToolBarTray tray = app.ToolBar.CreateToolBarTray(uiobj); - RowDefinition menuRow = new RowDefinition(); - menuRow.Height = GridLength.Auto; - windowGrid.RowDefinitions.Add(menuRow); - - Grid.SetRow(tray, rowIndex); - Grid.SetColumn(tray, 0); - windowGrid.Children.Add(tray); - rowIndex++; - - if(menu != null) - { - menu.Background = tray.Background; - } - } - - // content - RowDefinition contentRow = new RowDefinition(); - contentRow.Height = new GridLength(1, GridUnitType.Star); - windowGrid.RowDefinitions.Add(contentRow); - BoxContainer vbox = new BoxContainer(BoxOrientation.VERTICAL, 0, 0); - Grid.SetColumn(vbox, 0); - Grid.SetRow(vbox, rowIndex); - windowGrid.Children.Add(vbox); - rowIndex++; - - Container = vbox; - - Closed += CloseEvent; - } - - public void ShowWindow() - { - this.Show(); - Application.GetInstance().AddWindow(this); - } - - public void CloseEvent(object sender, System.EventArgs e) - { - Application.GetInstance().RemoveWindow(this); - } - - public void Add(UIElement control, bool fill) - { - Container.Add(control, fill); - } - } -}
--- a/ui/wpf/UIwrapper/UIwrapper.sln Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,40 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.25420.1 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "UIwrapper", "UIwrapper\UIwrapper.vcxproj", "{367C474F-D7EA-44E3-9CB7-A4A35DCE9CC5}" - ProjectSection(ProjectDependencies) = postProject - {8573F7D8-F05F-4195-9005-1C219B976146} = {8573F7D8-F05F-4195-9005-1C219B976146} - EndProjectSection -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UIcore", "..\UIcore\UIcore.csproj", "{8573F7D8-F05F-4195-9005-1C219B976146}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {367C474F-D7EA-44E3-9CB7-A4A35DCE9CC5}.Debug|Any CPU.ActiveCfg = Debug|x64 - {367C474F-D7EA-44E3-9CB7-A4A35DCE9CC5}.Debug|Any CPU.Build.0 = Debug|x64 - {367C474F-D7EA-44E3-9CB7-A4A35DCE9CC5}.Debug|x64.ActiveCfg = Debug|x64 - {367C474F-D7EA-44E3-9CB7-A4A35DCE9CC5}.Debug|x64.Build.0 = Debug|x64 - {367C474F-D7EA-44E3-9CB7-A4A35DCE9CC5}.Release|Any CPU.ActiveCfg = Release|Win32 - {367C474F-D7EA-44E3-9CB7-A4A35DCE9CC5}.Release|x64.ActiveCfg = Release|x64 - {367C474F-D7EA-44E3-9CB7-A4A35DCE9CC5}.Release|x64.Build.0 = Release|x64 - {8573F7D8-F05F-4195-9005-1C219B976146}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {8573F7D8-F05F-4195-9005-1C219B976146}.Debug|Any CPU.Build.0 = Debug|Any CPU - {8573F7D8-F05F-4195-9005-1C219B976146}.Debug|x64.ActiveCfg = Debug|Any CPU - {8573F7D8-F05F-4195-9005-1C219B976146}.Debug|x64.Build.0 = Debug|Any CPU - {8573F7D8-F05F-4195-9005-1C219B976146}.Release|Any CPU.ActiveCfg = Release|Any CPU - {8573F7D8-F05F-4195-9005-1C219B976146}.Release|Any CPU.Build.0 = Release|Any CPU - {8573F7D8-F05F-4195-9005-1C219B976146}.Release|x64.ActiveCfg = Release|Any CPU - {8573F7D8-F05F-4195-9005-1C219B976146}.Release|x64.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal
--- a/ui/wpf/UIwrapper/UIwrapper/AssemblyInfo.cpp Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,38 +0,0 @@ -#include "stdafx.h" - -using namespace System; -using namespace System::Reflection; -using namespace System::Runtime::CompilerServices; -using namespace System::Runtime::InteropServices; -using namespace System::Security::Permissions; - -// -// Allgemeine Informationen über eine Assembly werden über die folgenden -// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern, -// die mit einer Assembly verknüpft sind. -// -[assembly:AssemblyTitleAttribute(L"UIwrapper")]; -[assembly:AssemblyDescriptionAttribute(L"")]; -[assembly:AssemblyConfigurationAttribute(L"")]; -[assembly:AssemblyCompanyAttribute(L"")]; -[assembly:AssemblyProductAttribute(L"UIwrapper")]; -[assembly:AssemblyCopyrightAttribute(L"Copyright (c) 2015")]; -[assembly:AssemblyTrademarkAttribute(L"")]; -[assembly:AssemblyCultureAttribute(L"")]; - -// -// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten: -// -// Hauptversion -// Nebenversion -// Buildnummer -// Revision -// -// Sie können alle Werte angeben oder für die Revisions- und Buildnummer den Standard -// übernehmen, indem Sie "*" eingeben: - -[assembly:AssemblyVersionAttribute("1.0.*")]; - -[assembly:ComVisible(false)]; - -[assembly:CLSCompliantAttribute(true)]; \ No newline at end of file
--- a/ui/wpf/UIwrapper/UIwrapper/ReadMe.txt Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,30 +0,0 @@ -======================================================================== - DYNAMIC LINK LIBRARY: UIwrapper-Projektübersicht -======================================================================== - -Diese UIwrapper-DLL wurde vom Anwendungs-Assistenten für Sie erstellt. - -Diese Datei bietet eine Übersicht über den Inhalt der einzelnen Dateien, aus -denen Ihre UIwrapper-Anwendung besteht. - -UIwrapper.vcxproj - Dies ist die Hauptprojektdatei für VC++-Projekte, die mit dem Anwendungs-Assistenten generiert werden. Sie enthält Informationen über die Version von Visual C++, mit der die Datei generiert wurde, sowie über die Plattformen, Konfigurationen und Projektfunktionen, die im Anwendungs-Assistenten ausgewählt wurden. - -UIwrapper.vcxproj.filters - Dies ist die Filterdatei für VC++-Projekte, die mithilfe eines Anwendungs-Assistenten erstellt werden. Sie enthält Informationen über die Zuordnung zwischen den Dateien im Projekt und den Filtern. Diese Zuordnung wird in der IDE zur Darstellung der Gruppierung von Dateien mit ähnlichen Erweiterungen unter einem bestimmten Knoten verwendet (z. B. sind CPP-Dateien dem Filter "Quelldateien" zugeordnet). - -UIwrapper.cpp - Dies ist die Hauptquelldatei der DLL. - -UIwrapper.h - Diese Datei enthält eine Klassendeklaration. - -AssemblyInfo.cpp - Enthält benutzerdefinierte Attribute zum Ändern von Assemblymetadaten. - -///////////////////////////////////////////////////////////////////////////// -Weitere Hinweise: - -Der Anwendungs-Assistent weist Sie mit "TODO:" auf Teile des Quellcodes hin, die Sie ergänzen oder anpassen sollten. - -/////////////////////////////////////////////////////////////////////////////
--- a/ui/wpf/UIwrapper/UIwrapper/Stdafx.cpp Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ -// stdafx.cpp : Quelldatei, die nur die Standard-Includes einbindet. -// UIwrapper.pch ist der vorkompilierte Header. -// stdafx.obj enthält die vorkompilierten Typinformationen. - -#include "stdafx.h"
--- a/ui/wpf/UIwrapper/UIwrapper/Stdafx.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -// stdafx.h : Includedatei für Standardsystem-Includedateien -// oder häufig verwendete projektspezifische Includedateien, -// die nur in unregelmäßigen Abständen geändert werden. - -#pragma once - -
--- a/ui/wpf/UIwrapper/UIwrapper/UIwrapper.vcxproj Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup Label="ProjectConfigurations"> - <ProjectConfiguration Include="Debug|Win32"> - <Configuration>Debug</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Debug|x64"> - <Configuration>Debug</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|Win32"> - <Configuration>Release</Configuration> - <Platform>Win32</Platform> - </ProjectConfiguration> - <ProjectConfiguration Include="Release|x64"> - <Configuration>Release</Configuration> - <Platform>x64</Platform> - </ProjectConfiguration> - </ItemGroup> - <PropertyGroup Label="Globals"> - <ProjectGuid>{367C474F-D7EA-44E3-9CB7-A4A35DCE9CC5}</ProjectGuid> - <TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion> - <Keyword>ManagedCProj</Keyword> - <RootNamespace>UIwrapper</RootNamespace> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <UseDebugLibraries>true</UseDebugLibraries> - <PlatformToolset>v140</PlatformToolset> - <CLRSupport>true</CLRSupport> - <CharacterSet>Unicode</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <UseDebugLibraries>true</UseDebugLibraries> - <PlatformToolset>v140</PlatformToolset> - <CLRSupport>true</CLRSupport> - <CharacterSet>Unicode</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <PlatformToolset>v140</PlatformToolset> - <CLRSupport>true</CLRSupport> - <CharacterSet>Unicode</CharacterSet> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> - <ConfigurationType>DynamicLibrary</ConfigurationType> - <UseDebugLibraries>false</UseDebugLibraries> - <PlatformToolset>v140</PlatformToolset> - <CLRSupport>true</CLRSupport> - <CharacterSet>Unicode</CharacterSet> - </PropertyGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> - <ImportGroup Label="ExtensionSettings"> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets"> - <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> - </ImportGroup> - <PropertyGroup Label="UserMacros" /> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <LinkIncremental>true</LinkIncremental> - <OutDir>$(SolutionDir)..\..\..\build\UIwrapper\</OutDir> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <LinkIncremental>true</LinkIncremental> - <OutDir>$(SolutionDir)..\..\..\build\UIwrapper\</OutDir> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <LinkIncremental>false</LinkIncremental> - </PropertyGroup> - <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <LinkIncremental>false</LinkIncremental> - <OutDir>$(SolutionDir)..\..\..\build\UIwrapper\</OutDir> - <IntDir>$(SolutionDir)..\..\..\build\UIwrapper\$(Configuration)\</IntDir> - <LibraryPath>$(LibraryPath)</LibraryPath> - </PropertyGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <Optimization>Disabled</Optimization> - <PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <PrecompiledHeader>Use</PrecompiledHeader> - <AdditionalUsingDirectories>$(SolutionDir)..\..\..\build\UIcore\;%(AdditionalUsingDirectories)</AdditionalUsingDirectories> - </ClCompile> - <Link> - <GenerateDebugInformation>true</GenerateDebugInformation> - <AdditionalDependencies /> - <AdditionalLibraryDirectories>C:\Users\Olaf\Projekte\toolkit\build\UIcore\</AdditionalLibraryDirectories> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <Optimization>Disabled</Optimization> - <PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <PrecompiledHeader>Use</PrecompiledHeader> - <AdditionalUsingDirectories>$(SolutionDir)..\..\..\build\UIcore\;%(AdditionalUsingDirectories)</AdditionalUsingDirectories> - </ClCompile> - <Link> - <GenerateDebugInformation>true</GenerateDebugInformation> - <AdditionalDependencies> - </AdditionalDependencies> - <AdditionalLibraryDirectories> - </AdditionalLibraryDirectories> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <PrecompiledHeader>Use</PrecompiledHeader> - </ClCompile> - <Link> - <GenerateDebugInformation>true</GenerateDebugInformation> - <AdditionalDependencies /> - </Link> - </ItemDefinitionGroup> - <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> - <ClCompile> - <WarningLevel>Level3</WarningLevel> - <PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions> - <PrecompiledHeader>Use</PrecompiledHeader> - <AdditionalUsingDirectories>$(SolutionDir)..\..\..\build\UIcore\;%(AdditionalUsingDirectories)</AdditionalUsingDirectories> - <DebugInformationFormat>None</DebugInformationFormat> - </ClCompile> - <Link> - <GenerateDebugInformation>true</GenerateDebugInformation> - <AdditionalDependencies> - </AdditionalDependencies> - </Link> - </ItemDefinitionGroup> - <ItemGroup> - <Reference Include="PresentationCore" /> - <Reference Include="PresentationFramework" /> - <Reference Include="System" /> - <Reference Include="System.Data" /> - <Reference Include="System.Windows" /> - <Reference Include="System.Windows.Controls.Ribbon" /> - <Reference Include="System.Xaml" /> - <Reference Include="System.Xml" /> - <Reference Include="WindowsBase" /> - </ItemGroup> - <ItemGroup> - <ClInclude Include="controls.h" /> - <ClInclude Include="container.h" /> - <ClInclude Include="graphics.h" /> - <ClInclude Include="menu.h" /> - <ClInclude Include="resource.h" /> - <ClInclude Include="Stdafx.h" /> - <ClInclude Include="toolbar.h" /> - <ClInclude Include="toolkit.h" /> - <ClInclude Include="window.h" /> - </ItemGroup> - <ItemGroup> - <ClCompile Include="AssemblyInfo.cpp" /> - <ClCompile Include="controls.cpp" /> - <ClCompile Include="graphics.cpp" /> - <ClCompile Include="menu.cpp" /> - <ClCompile Include="container.cpp" /> - <ClCompile Include="toolbar.cpp" /> - <ClCompile Include="window.cpp" /> - <ClCompile Include="Stdafx.cpp"> - <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader> - <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Create</PrecompiledHeader> - <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader> - <PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader> - </ClCompile> - <ClCompile Include="toolkit.cpp" /> - </ItemGroup> - <ItemGroup> - <Text Include="ReadMe.txt" /> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="app.rc" /> - </ItemGroup> - <ItemGroup> - <Image Include="app.ico" /> - </ItemGroup> - <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> - <ImportGroup Label="ExtensionTargets"> - </ImportGroup> -</Project> \ No newline at end of file
--- a/ui/wpf/UIwrapper/UIwrapper/UIwrapper.vcxproj.filters Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,88 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <ItemGroup> - <Filter Include="Quelldateien"> - <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> - <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions> - </Filter> - <Filter Include="Headerdateien"> - <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> - <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions> - </Filter> - <Filter Include="Ressourcendateien"> - <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier> - <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions> - </Filter> - </ItemGroup> - <ItemGroup> - <ClInclude Include="Stdafx.h"> - <Filter>Headerdateien</Filter> - </ClInclude> - <ClInclude Include="resource.h"> - <Filter>Headerdateien</Filter> - </ClInclude> - <ClInclude Include="toolkit.h"> - <Filter>Headerdateien</Filter> - </ClInclude> - <ClInclude Include="window.h"> - <Filter>Headerdateien</Filter> - </ClInclude> - <ClInclude Include="menu.h"> - <Filter>Headerdateien</Filter> - </ClInclude> - <ClInclude Include="controls.h"> - <Filter>Headerdateien</Filter> - </ClInclude> - <ClInclude Include="container.h"> - <Filter>Headerdateien</Filter> - </ClInclude> - <ClInclude Include="toolbar.h"> - <Filter>Headerdateien</Filter> - </ClInclude> - <ClInclude Include="graphics.h"> - <Filter>Headerdateien</Filter> - </ClInclude> - </ItemGroup> - <ItemGroup> - <ClCompile Include="AssemblyInfo.cpp"> - <Filter>Quelldateien</Filter> - </ClCompile> - <ClCompile Include="Stdafx.cpp"> - <Filter>Quelldateien</Filter> - </ClCompile> - <ClCompile Include="window.cpp"> - <Filter>Quelldateien</Filter> - </ClCompile> - <ClCompile Include="toolkit.cpp"> - <Filter>Quelldateien</Filter> - </ClCompile> - <ClCompile Include="menu.cpp"> - <Filter>Quelldateien</Filter> - </ClCompile> - <ClCompile Include="controls.cpp"> - <Filter>Quelldateien</Filter> - </ClCompile> - <ClCompile Include="container.cpp"> - <Filter>Quelldateien</Filter> - </ClCompile> - <ClCompile Include="toolbar.cpp"> - <Filter>Quelldateien</Filter> - </ClCompile> - <ClCompile Include="graphics.cpp"> - <Filter>Quelldateien</Filter> - </ClCompile> - </ItemGroup> - <ItemGroup> - <Text Include="ReadMe.txt" /> - </ItemGroup> - <ItemGroup> - <ResourceCompile Include="app.rc"> - <Filter>Ressourcendateien</Filter> - </ResourceCompile> - </ItemGroup> - <ItemGroup> - <Image Include="app.ico"> - <Filter>Ressourcendateien</Filter> - </Image> - </ItemGroup> -</Project> \ No newline at end of file
--- a/ui/wpf/UIwrapper/UIwrapper/UIwrapper.vcxproj.user Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> - <PropertyGroup /> -</Project> \ No newline at end of file
--- a/ui/wpf/UIwrapper/UIwrapper/container.cpp Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,78 +0,0 @@ - - -#include "stdafx.h" -#include <stdio.h> - -#include "container.h" - -#using "UIcore.dll" - -UI_EXPORT void* __stdcall UIvbox(gcroot<UI::Container^> *parent, int margin, int spacing) { - UI::BoxContainer ^vbox = gcnew UI::BoxContainer(*parent, UI::BoxOrientation::VERTICAL, margin, spacing); - gcroot<UI::BoxContainer^> *container = new gcroot<UI::BoxContainer^>(); - *container = vbox; - return container; -} - -UI_EXPORT void* __stdcall UIhbox(gcroot<UI::Container^> *parent, int margin, int spacing) { - UI::BoxContainer ^hbox = gcnew UI::BoxContainer(*parent, UI::BoxOrientation::HORIZONTAL, margin, spacing); - gcroot<UI::BoxContainer^> *container = new gcroot<UI::BoxContainer^>(); - *container = hbox; - return container; -} - -UI_EXPORT void* __stdcall UIgrid(gcroot<UI::Container^> *parent, int margin, int columnspacing, int rowspacing) { - UI::GridContainer ^grid = gcnew UI::GridContainer(*parent, margin, columnspacing, rowspacing); - gcroot<UI::GridContainer^> *container = new gcroot<UI::GridContainer^>(); - *container = grid; - return container; -} - -UI_EXPORT void* __stdcall UIscrolledwindow(gcroot<UI::Container^> *parent) { - UI::ScrollViewerContainer ^scrollviewer = gcnew UI::ScrollViewerContainer(*parent); - gcroot<UI::ScrollViewerContainer^> *container = new gcroot<UI::ScrollViewerContainer^>(); - *container = scrollviewer; - return container; -} - -UI_EXPORT void* __stdcall UItabview(gcroot<UI::Container^> *parent) { - UI::TabViewContainer ^tabview = gcnew UI::TabViewContainer(*parent); - gcroot<UI::TabViewContainer^> *container = new gcroot<UI::TabViewContainer^>(); - *container = tabview; - return container; -} - -UI_EXPORT void __stdcall UItab(gcroot<UI::Container^> *container, char *label) { - UI::Container ^ct = *container; - ct->Layout->Label = gcnew String(label); -} - - - -/* ------------------- layout functions ------------------- */ - -UI_EXPORT void __stdcall UIlayout_fill(gcroot<UI::Container^> *container, int fill) { - UI::Container ^ct = *container; - ct->Layout->Fill = fill != 0; -} - -UI_EXPORT void __stdcall UIlayout_hexpand(gcroot<UI::Container^> *container, int expand) { - UI::Container ^ct = *container; - ct->Layout->Hexpand = expand != 0; -} - -UI_EXPORT void __stdcall UIlayout_vexpand(gcroot<UI::Container^> *container, int expand) { - UI::Container ^ct = *container; - ct->Layout->Vexpand = expand != 0; -} - -UI_EXPORT void __stdcall UIlayout_gridwidth(gcroot<UI::Container^> *container, int width) { - UI::Container ^ct = *container; - ct->Layout->GridWidth = width; -} - -UI_EXPORT void __stdcall UIlayout_newline(gcroot<UI::Container^> *container) { - UI::Container ^ct = *container; - ct->Layout->NewLine = true; -} -
--- a/ui/wpf/UIwrapper/UIwrapper/container.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,5 +0,0 @@ - - -#pragma once - -#include "toolkit.h"
--- a/ui/wpf/UIwrapper/UIwrapper/controls.cpp Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,110 +0,0 @@ - - -#include "stdafx.h" -#include <stdio.h> - -#include "controls.h" - -#using "UIcore.dll" - -/* ------------------------------ Buttons ------------------------------ */ - -UI_EXPORT void* __stdcall UIbutton(gcroot<UI::Container^> *container, char *label, UIcallback f, void *eventdata) { - gcroot<Button^> *button = new gcroot<Button^>(); - - EventWrapper ^evt = gcnew EventWrapper(f, eventdata); - RoutedEventHandler ^handler = gcnew RoutedEventHandler(evt, &EventWrapper::Callback); - - *button = UI::Controls::Button(*container, gcnew String(label), handler); - return button; -} - - -/* ------------------------------ Labels ------------------------------ */ - -UI_EXPORT void* __stdcall UIlabel(gcroot<UI::Container^> *container, char *label, int alignment) { - gcroot<Label^> *control = new gcroot<Label^>(); - *control = UI::Controls::Label(*container, gcnew String(label), alignment); - return control; -} - -UI_EXPORT void* __stdcall UIspace(gcroot<UI::Container^> *container) { - gcroot<Label^> *control = new gcroot<Label^>(); - *control = UI::Controls::Space(*container); - return control; -} - -UI_EXPORT void* __stdcall UIseparator(gcroot<UI::Container^> *container) { - gcroot<Separator^> *control = new gcroot<Separator^>(); - *control = UI::Controls::Separator(*container); - return control; -} - - - -/* ------------------------------ Textarea ------------------------------ */ - -UI_EXPORT void* __stdcall UItextarea(gcroot<UI::Container^> *container, char *text) { - String ^str = nullptr; - if (text) { - str = gcnew String(text); - } - - gcroot<UI::TextArea^> *textarea = new gcroot<UI::TextArea^>(); - *textarea = gcnew UI::TextArea(*container, str, true); - - return textarea; -} - -UI_EXPORT void __stdcall UItextarea_set(gcroot<UI::TextArea^> *textarea, char *str) { - (*textarea)->SetText(gcnew String(str)); -} - -UI_EXPORT char* __stdcall UItextarea_get(gcroot<UI::TextArea^> *textarea) { - String ^str = (*textarea)->GetText(); - return (char*)(void*)Marshal::StringToHGlobalAnsi(str); -} - -UI_EXPORT char* __stdcall UItextarea_getsubstr(gcroot<UI::TextArea^> *textarea, int begin, int end) { - String ^str = (*textarea)->GetSubString(begin, end); - return (char*)(void*)Marshal::StringToHGlobalAnsi(str); -} - -UI_EXPORT void __stdcall UItextarea_insert(gcroot<UI::TextArea^> *textarea, int position, char *str) { - // TODO -} - -UI_EXPORT int __stdcall UItextarea_position(gcroot<UI::TextArea^> *textarea) { - return (*textarea)->Position(); -} - -UI_EXPORT void __stdcall UItextarea_selection(gcroot<UI::TextArea^> *textarea, int *begin, int *end) { - // TODO -} - -UI_EXPORT int __stdcall UItextarea_length(gcroot<UI::TextArea^> *textarea) { - return (*textarea)->Length(); -} - -UI_EXPORT void __stdcall UItextarea_remove(gcroot<UI::TextArea^> *textarea, int begin, int end) { - // TODO -} - -UI_EXPORT void __stdcall UIfreestr(char *str) { - Marshal::FreeHGlobal((IntPtr)(void*)str); -} - - -/* ------------------------------ Textfield ------------------------------ */ - -UI_EXPORT void* __stdcall UItextfield(gcroot<UI::Container^> *container, char *text) { - String ^str = nullptr; - if (text) { - str = gcnew String(text); - } - - gcroot<UI::TextArea^> *textfield = new gcroot<UI::TextArea^>(); - *textfield = gcnew UI::TextArea(*container, str, false); - - return textfield; -} \ No newline at end of file
--- a/ui/wpf/UIwrapper/UIwrapper/controls.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ - - -#pragma once - -#include "toolkit.h" -
--- a/ui/wpf/UIwrapper/UIwrapper/graphics.cpp Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,63 +0,0 @@ -#include "stdafx.h" -#include <stdio.h> - -#include "graphics.h" - -#using "UIcore.dll" - - -DrawEventWrapper::DrawEventWrapper(void *gc, UIdrawfunc callback, void *eventdata) { - this->callback = callback; - this->eventdata = eventdata; - this->gc = gc; - action = gcnew Action<int,int>(this, &DrawEventWrapper::Callback); -} - - -void DrawEventWrapper::Callback(int width, int height) -{ - if (callback) - { - UI::DrawingArea ^d = (UI::DrawingArea^)PtrToObject(gc); - callback(gc, eventdata, width, height); - } -} - - -UI_EXPORT void* __stdcall UIdrawingarea(gcroot<UI::Container^> *container, UIdrawfunc f, void *data) -{ - gcroot<UI::DrawingArea^> *canvas = new gcroot<UI::DrawingArea^>(); - *canvas = gcnew UI::DrawingArea(*container); - - DrawEventWrapper ^ev = gcnew DrawEventWrapper(ObjectToPtr(*canvas), f, data); - (*canvas)->resizeCallback = ev->action; - - return canvas; -} - - -UI_EXPORT void __stdcall UIdrawingarea_redraw(gcroot<UI::DrawingArea^> *drawingarea) -{ - (*drawingarea)->Redraw(); -} - - -/* ------------------------- drawing functions ------------------------- */ - -UI_EXPORT void __stdcall UIgraphics_color(void *g, int red, int green, int blue) -{ - UI::DrawingArea ^d = (UI::DrawingArea^)PtrToObject(g); - d->SetColor(red, green, blue); -} - -UI_EXPORT void __stdcall UIdraw_line(void *g, int x1, int y1, int x2, int y2) -{ - UI::DrawingArea ^d = (UI::DrawingArea^)PtrToObject(g); - d->DrawLine(x1, y1, x2, y2); -} - -UI_EXPORT void __stdcall UIdraw_rect(void *g, int x, int y, int w, int h, int fill) -{ - UI::DrawingArea ^d = (UI::DrawingArea^)PtrToObject(g); - d->DrawRect(x, y, w, h, fill ? true : false); -}
--- a/ui/wpf/UIwrapper/UIwrapper/graphics.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -#pragma once - -#include "toolkit.h" - -typedef void(*UIdrawfunc)(void *gc, void *event, int width, int height); - -public ref class DrawEventWrapper { -public: - UIdrawfunc callback = NULL; - void *eventdata = NULL; - void *gc; - Action<int,int> ^action; - - DrawEventWrapper(void *gc, UIdrawfunc callback, void *eventdata); - - void Callback(int width, int height); -};
--- a/ui/wpf/UIwrapper/UIwrapper/menu.cpp Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,26 +0,0 @@ - -#include "stdafx.h" -#include <stdio.h> - -#include "menu.h" - -#using "UIcore.dll" - -UI_EXPORT void __stdcall UImenu(char *label) { - UI::Application::GetInstance()->Menu->AddMenu(gcnew String(label)); -} - -UI_EXPORT void __stdcall UIsubmenu(char *label) { - UI::Application::GetInstance()->Menu->AddSubMenu(gcnew String(label)); -} - -UI_EXPORT void __stdcall UIsubmenu_end() { - UI::Application::GetInstance()->Menu->EndSubMenu(); -} - - -UI_EXPORT void __stdcall UImenuitem(char *label, UIcallback f, void *eventdata) { - ObjEventWrapper ^e = gcnew ObjEventWrapper(f, eventdata); - UI::Application::GetInstance()->Menu->AddMenuItem(gcnew String(label), e->GetAction()); -} -
--- a/ui/wpf/UIwrapper/UIwrapper/menu.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ - -#pragma once - -#include "toolkit.h" \ No newline at end of file
--- a/ui/wpf/UIwrapper/UIwrapper/resource.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,3 +0,0 @@ -//{{NO_DEPENDENCIES}} -// Microsoft Visual C++ generated include file. -// Used by app.rc
--- a/ui/wpf/UIwrapper/UIwrapper/toolbar.cpp Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* -* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. -* -* Copyright 2015 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 "stdafx.h" -#include <stdio.h> - -#include "toolbar.h" - -#using "UIcore.dll" - -UI_EXPORT void __stdcall UItoolitem(char *name, char *label, UIcallback f, void *eventdata) { - ObjEventWrapper ^e = gcnew ObjEventWrapper(f, eventdata); - UI::Application::GetInstance()->ToolBar->AddToolItem(gcnew String(name), gcnew String(label), e->GetAction()); -} - - - - - -UI_EXPORT void __stdcall UItoolbar_add_default(char *name) { - UI::Application::GetInstance()->ToolBar->AddDefault(gcnew String(name)); -} -
--- a/ui/wpf/UIwrapper/UIwrapper/toolbar.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* -* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. -* -* Copyright 2015 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. -*/ - - -#pragma once - -#include "toolkit.h"
--- a/ui/wpf/UIwrapper/UIwrapper/toolkit.cpp Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,127 +0,0 @@ -// Dies ist die Haupt-DLL. - -#include "stdafx.h" -#include <stdio.h> - -#include "toolkit.h" - -#using "UIcore.dll" - -static UIcallback startup_func; -void *startup_data; -static UIcallback open_func; -void *open_data; -static UIcallback exit_func; -void *exit_data; - -public ref class AppCallbacks : public UI::IApplicationCallbacks { -public: - UIcallback startupFunc = NULL; - void *startupData = NULL; - UIcallback openFunc = NULL; - void *openData = NULL; - UIcallback exitFunc = NULL; - void *exitData = NULL; - - virtual void __clrcall OnStartup() { - if (startupFunc) { - startupFunc(NULL, startupData); - } - } - virtual void __clrcall OnOpen() { - if (openFunc) { - openFunc(NULL, openData); - } - } - virtual void __clrcall OnExit() { - if (exitFunc) { - exitFunc(NULL, exitData); - } - } -}; - - -void* ObjectToPtr(Object ^obj) { - GCHandle handle = GCHandle::Alloc(obj); - IntPtr pointer = GCHandle::ToIntPtr(handle); - return pointer.ToPointer(); -} - -Object^ PtrToObject(void *ptr) { - GCHandle h = GCHandle::FromIntPtr(IntPtr(ptr)); - Object^ object = h.Target; - //h.Free(); - return object; -} - -// EventWrapper - -ObjEventWrapper::ObjEventWrapper(UIcallback callback, void *eventdata) { - this->callback = callback; - this->eventdata = eventdata; - action = gcnew Action<IntPtr>(this, &ObjEventWrapper::Callback); -} - -Action<IntPtr>^ ObjEventWrapper::GetAction() { - return action; -} - -void ObjEventWrapper::Callback(IntPtr uiobj) { - if (callback) { - callback(uiobj.ToPointer(), eventdata); - } -} - - -EventWrapper::EventWrapper(UIcallback callback, void *eventdata) { - this->callback = callback; - this->eventdata = eventdata; -} - -void EventWrapper::Callback(Object ^sender, RoutedEventArgs ^e) { - if (callback) { - callback(NULL, eventdata); - } -} - - - -UI_EXPORT void __stdcall UIinit(char *appname) { - UI::Application ^app = UI::Application::GetInstance(); - app->Name = gcnew String(appname); -} - -UI_EXPORT void __stdcall UIonstartup(UIcallback f, void *userdata) { - startup_func = f; - startup_data = userdata; -} - -UI_EXPORT void __stdcall UIonopen(UIcallback f, void *userdata) { - open_func = f; - open_data = userdata; -} - -UI_EXPORT void __stdcall UIonexit(UIcallback f, void *userdata) { - exit_func = f; - exit_data = userdata; -} - -UI_EXPORT void __stdcall UImain() { - AppCallbacks ^ac = gcnew AppCallbacks(); - ac->startupFunc = startup_func; - ac->startupData = startup_data; - ac->openFunc = open_func; - ac->openData = open_data; - ac->exitFunc = exit_func; - ac->exitData = exit_data; - - UI::Application ^app = UI::Application::GetInstance(); - app->callbacks = ac; - - Thread ^thread = app->Start(); - thread->Join(); -} - -UI_EXPORT void __stdcall UIshow(gcroot<UI::MainWindow^> *window) { - (*window)->ShowWindow(); -}
--- a/ui/wpf/UIwrapper/UIwrapper/toolkit.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,42 +0,0 @@ -// UIwrapper.h - -#pragma once - -#include <vcclr.h> - -using namespace System; -using namespace System::Runtime::InteropServices; -using namespace System::Threading; -using namespace System::Windows; -using namespace System::Windows::Controls; - -#define UI_EXPORT extern "C" __declspec(dllexport) - -extern "C" typedef void(*UIcallback)(void*, void*); - -void* ObjectToPtr(Object ^obj); -Object^ PtrToObject(void *ptr); - -public ref class ObjEventWrapper { - UIcallback callback = NULL; - void *eventdata = NULL; - Action<IntPtr> ^action; - -public: - ObjEventWrapper(UIcallback callback, void *eventdata); - - Action<IntPtr>^ GetAction(); - - void Callback(IntPtr uiobj); -}; - -public ref class EventWrapper { - UIcallback callback = NULL; - void *eventdata = NULL; - - -public: - EventWrapper(UIcallback callback, void *eventdata); - void Callback(Object ^sender, RoutedEventArgs ^e); -}; -
--- a/ui/wpf/UIwrapper/UIwrapper/window.cpp Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ - - -#include "stdafx.h" -#include <stdio.h> - -#include "window.h" - -#using "UIcore.dll" - -UI_EXPORT void* __stdcall UIwindow(char *title, void *uiobj) { - UI::MainWindow ^window = gcnew UI::MainWindow(gcnew String(title), IntPtr(uiobj)); - gcroot<UI::MainWindow^> *ptr = new gcroot<UI::MainWindow^>(); - *ptr = window; - return ptr; -} - -
--- a/ui/wpf/UIwrapper/UIwrapper/window.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,6 +0,0 @@ - - -#pragma once - -#include "toolkit.h" -
--- a/ui/wpf/button.c Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,58 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2015 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 "button.h" -#include "../common/object.h" - -UIWIDGET ui_button(UiObject *obj, char *label, ui_callback f, void *data) { - UiEventData *event = NULL; - ui_callback callback = NULL; - if(f) { - event = malloc(sizeof(UiEventData)); - event->obj = obj; - event->callback = f; - event->user_data = data; - event->value = 0; - callback = (ui_callback)ui_button_callback; - } - - UiContainer *container = uic_get_current_container(obj); - return UIbutton(container, label, callback, event); -} - -void ui_button_callback(UiObject *obj, UiEventData *e) { - UiEvent event; - event.obj = e->obj; - event.document = event.obj->ctx->document; - event.window = event.obj->window; - event.intval = 0; - e->callback(&event, e->user_data); -}
--- a/ui/wpf/button.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2015 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 "../ui/button.h" -#include "toolkit.h" - -#ifdef __cplusplus -extern "C" { -#endif - -UI_IMPORT UIWIDGET __stdcall UIbutton(void *container, char *label, ui_callback f, void *event); - -void ui_button_callback(UiObject *obj, UiEventData *e); - -#ifdef __cplusplus -} -#endif - -#endif /* BUTTON_H */ -
--- a/ui/wpf/container.c Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,147 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2015 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 "container.h" -#include "../common/object.h" - -UIWIDGET ui_vbox(UiObject *obj) { - return ui_vbox_sp(obj, 0, 0); -} - -UIWIDGET ui_hbox(UiObject *obj) { - return ui_hbox_sp(obj, 0, 0); -} - -UIWIDGET ui_vbox_sp(UiObject *obj, int margin, int spacing) { - UiContainer *ct = uic_get_current_container(obj); - - UIWIDGET vbox = UIvbox(ct, margin, spacing); - - UiObject *newobj = uic_object_new(obj, vbox); - newobj->container = (UiContainer*)vbox; - uic_obj_add(obj, newobj); - - return vbox; -} - -UIWIDGET ui_hbox_sp(UiObject *obj, int margin, int spacing) { - UiContainer *ct = uic_get_current_container(obj); - - UIWIDGET hbox = UIhbox(ct, margin, spacing); - - UiObject *newobj = uic_object_new(obj, hbox); - newobj->container = (UiContainer*)hbox; - uic_obj_add(obj, newobj); - - return hbox; -} - -UIWIDGET ui_grid(UiObject *obj) { - return ui_grid_sp(obj, 0, 0, 0); -} - -UIWIDGET ui_grid_sp(UiObject *obj, int margin, int columnspacing, int rowspacing) { - UiContainer *ct = uic_get_current_container(obj); - - UIWIDGET grid = UIgrid(ct, margin, columnspacing, rowspacing); - - UiObject *newobj = uic_object_new(obj, grid); - newobj->container = (UiContainer*)grid; - uic_obj_add(obj, newobj); - - return grid; -} - -UIWIDGET ui_scrolledwindow(UiObject *obj) { - UiContainer *ct = uic_get_current_container(obj); - - UIWIDGET scrolledwindow = UIscrolledwindow(ct); - - UiObject *newobj = uic_object_new(obj, scrolledwindow); - newobj->container = (UiContainer*)scrolledwindow; - uic_obj_add(obj, newobj); - - return scrolledwindow; -} - -/* - * TODO: sidebar - */ - -UIWIDGET ui_tabview(UiObject *obj) { - UiContainer *ct = uic_get_current_container(obj); - - UIWIDGET tabview = UItabview(ct); - - UiObject *newobj = uic_object_new(obj, tabview); - newobj->container = (UiContainer*)tabview; - uic_obj_add(obj, newobj); - - return tabview; -} - -void ui_tab(UiObject *obj, char *title) { - UiContainer *ct = uic_get_current_container(obj); - UItab(ct, title); -} - - -/* - * -------------------- Layout Functions -------------------- - * - * functions for setting layout attributes for the current container - * - */ - -void ui_layout_fill(UiObject *obj, UiBool fill) { - UiContainer *ct = uic_get_current_container(obj); - UIlayout_fill(ct, fill); -} - -void ui_layout_hexpand(UiObject *obj, UiBool expand) { - UiContainer *ct = uic_get_current_container(obj); - UIlayout_hexpand(ct, expand); -} - -void ui_layout_vexpand(UiObject *obj, UiBool expand) { - UiContainer *ct = uic_get_current_container(obj); - UIlayout_vexpand(ct, expand); -} - -void ui_layout_gridwidth(UiObject *obj, int width) { - UiContainer *ct = uic_get_current_container(obj); - UIlayout_gridwidth(ct, width); -} - -void ui_newline(UiObject *obj) { - UiContainer *ct = uic_get_current_container(obj); - UIlayout_newline(ct); -} \ No newline at end of file
--- a/ui/wpf/container.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2015 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" - -#ifdef __cplusplus -extern "C" { -#endif - -UI_IMPORT void* __stdcall UIvbox(UiContainer *parent, int margin, int spacing); -UI_IMPORT void* __stdcall UIhbox(UiContainer *parent, int margin, int spacing); -UI_IMPORT void* __stdcall UIgrid(UiContainer *parent, int margin, int columnspacing, int rowspacing); - -UI_IMPORT void* __stdcall UIscrolledwindow(UiContainer *parent); - -UI_IMPORT void* __stdcall UItabview(UiContainer *parent); -UI_IMPORT void __stdcall UItab(UiContainer *container, char *label); - -UI_IMPORT void __stdcall UIlayout_fill(UiContainer *container, int fill); -UI_IMPORT void __stdcall UIlayout_hexpand(UiContainer *container, int expand); -UI_IMPORT void __stdcall UIlayout_vexpand(UiContainer *container, int expand); -UI_IMPORT void __stdcall UIlayout_gridwidth(UiContainer *container, int width); - -UI_IMPORT void __stdcall UIlayout_newline(UiContainer *container); - -#ifdef __cplusplus -} -#endif - -#endif /* CONTAINER_H */ -
--- a/ui/wpf/graphics.c Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,74 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -#include "graphics.h" -#include "container.h" -#include "../../ucx/mempool.h" -#include "../common/context.h" -#include "../common/object.h" - -UIWIDGET ui_drawingarea(UiObject *obj, ui_drawfunc f, void *userdata) { - UiDrawEvent *eventdata = NULL; - ui_draw_callback cb = NULL; - if(f) { - eventdata = malloc(sizeof(UiDrawEvent)); - eventdata->obj = obj; - eventdata->draw = f; - eventdata->userdata = userdata; - cb = ui_draw_event; - } - - UiContainer *container = uic_get_current_container(obj); - return UIdrawingarea(container, cb, eventdata); -} - -void ui_draw_event(void *gc, UiDrawEvent *event, int width, int height) { - UiEvent e; - e.obj = event->obj; - e.window = e.obj->window; - e.document = e.obj->ctx->document; - e.eventdata = NULL; - e.intval = 0; - - UiWPFGraphics g; - g.g.width = width; - g.g.height = height; - g.gc = gc; - - event->draw(&e, &g.g, event->userdata); -} - - -void ui_drawingarea_mousehandler(UiObject *obj, UIWIDGET widget, ui_callback f, void *u) { - -} - -void ui_drawingarea_getsize(UIWIDGET drawingarea, int *width, int *height) { - -} - -void ui_drawingarea_redraw(UIWIDGET drawingarea) { - UIdrawingarea_redraw(drawingarea); -} - - -/* ------------------------- drawing functions ------------------------- */ - -void ui_graphics_color(UiGraphics *g, int red, int green, int blue) { - UiWPFGraphics *wg = (UiWPFGraphics*)g; - UIgraphics_color(wg->gc, red, green, blue); -} - -void ui_draw_line(UiGraphics *g, int x1, int y1, int x2, int y2) { - UiWPFGraphics *wg = (UiWPFGraphics*)g; - UIdraw_line(wg->gc, x1, y1, x2, y2); -} - -void ui_draw_rect(UiGraphics *g, int x, int y, int w, int h, int fill) { - UiWPFGraphics *wg = (UiWPFGraphics*)g; - UIdraw_rect(wg->gc, x, y, w, h, fill); -} - -void ui_draw_text(UiGraphics *g, int x, int y, UiTextLayout *text) { - -}
--- a/ui/wpf/graphics.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * To change this license header, choose License Headers in Project Properties. - * To change this template file, choose Tools | Templates - * and open the template in the editor. - */ - -/* - * File: graphics.h - * Author: Olaf - * - * Created on 22. Januar 2017, 18:34 - */ - -#ifndef GRAPHICS_H -#define GRAPHICS_H - -#include "toolkit.h" -#include "../ui/graphics.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct UiDrawEvent { - UiObject *obj; - ui_drawfunc draw; - void *userdata; -} UiDrawEvent; - -typedef struct UiWPFGraphics { - UiGraphics g; - void *gc; -} UiWPFGraphics; - -typedef void(*ui_draw_callback)(void *gc, UiDrawEvent *event, int width, int height); - -UI_IMPORT UIWIDGET __stdcall UIdrawingarea(void *container, ui_draw_callback f, void *userdata); - -UI_IMPORT void __stdcall UIdrawingarea_redraw(UIWIDGET drawingarea); - -void ui_draw_event(void *gc, UiDrawEvent *event, int width, int height); - -// drawing functions - -UI_IMPORT void __stdcall UIgraphics_color(UiGraphics *g, int red, int green, int blue); -UI_IMPORT void __stdcall UIdraw_line(UiGraphics *g, int x1, int y1, int x2, int y2); -UI_IMPORT void __stdcall UIdraw_rect(UiGraphics *g, int x, int y, int w, int h, int fill); -//void UIdraw_text(UiGraphics *g, int x, int y, UiTextLayout *text); - - -#ifdef __cplusplus -} -#endif - -#endif /* GRAPHICS_H */ -
--- a/ui/wpf/label.c Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -#include <stdio.h> -#include <stdlib.h> - -#include "label.h" -#include "container.h" -#include "../../ucx/mempool.h" -#include "../common/context.h" -#include "../common/object.h" - -UIWIDGET ui_label(UiObject *obj, char *label) { - return UIlabel(uic_get_current_container(obj), label, 2); -} - -UIWIDGET ui_llabel(UiObject *obj, char *label) { - return UIlabel(uic_get_current_container(obj), label, 0); -} - -UIWIDGET ui_rlabel(UiObject *obj, char *label) { - return UIlabel(uic_get_current_container(obj), label, 1); -} - -UIWIDGET ui_space(UiObject *obj) { - return UIspace(uic_get_current_container(obj)); -} - -UIWIDGET ui_separator(UiObject *obj) { - return UIseparator(uic_get_current_container(obj)); -}
--- a/ui/wpf/label.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -/* - * File: label.h - * Author: Olaf - * - * Created on 19. Januar 2016, 18:12 - */ - -#ifndef LABEL_H -#define LABEL_H - -#include "toolkit.h" - -#ifdef __cplusplus -extern "C" { -#endif - -UI_IMPORT UIWIDGET __stdcall UIlabel(void *container, char *label, int alignment); - -UI_IMPORT UIWIDGET __stdcall UIspace(void *container); - -UI_IMPORT UIWIDGET __stdcall UIseparator(void *container); - -#ifdef __cplusplus -} -#endif - -#endif /* LABEL_H */ -
--- a/ui/wpf/menu.c Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,72 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2014 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 "menu.h" - -void ui_menu(char *label) { - UImenu(label); -} - -void ui_submenu(char *label) { - UIsubmenu(label); -} - -void ui_submenu_end() { - UIsubmenu_end(); -} - -void ui_menuitem(char *label, ui_callback f, void *userdata) { - UIcallback cb = NULL; - void *e = NULL; - if (f) { - UiEventData *event = malloc(sizeof(UiEventData)); - event->obj = NULL; - event->user_data = userdata; - event->callback = f; - event->value = 0; - cb = (UIcallback)ui_obj_callback; - e = event; - } - - UImenuitem(label, cb, e); -} - - -void ui_obj_callback(UiObject *obj, UiEventData *e) { - UiEvent event; - event.obj = obj; - event.window = obj->window; - event.intval = 0; - event.eventdata = NULL; - event.document = obj->ctx->document; - e->callback(&event, e->user_data); -}
--- a/ui/wpf/menu.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,32 +0,0 @@ -/* - * File: menu.h - * Author: Olaf - * - * Created on 25. Januar 2015, 13:37 - */ - -#ifndef MENU_H -#define MENU_H - -#include "../ui/menu.h" -#include "toolkit.h" - -#ifdef __cplusplus -extern "C" { -#endif - -UI_IMPORT void __stdcall UImenu(char *label); -UI_IMPORT void __stdcall UIsubmenu(char *label); -UI_IMPORT void __stdcall UIsubmenu_end(); -UI_IMPORT void __stdcall UImenuitem(char *label, UIcallback f, void *udata); - - - -void ui_obj_callback(UiObject *obj, UiEventData *e); - -#ifdef __cplusplus -} -#endif - -#endif /* MENU_H */ -
--- a/ui/wpf/objs.mk Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,43 +0,0 @@ -# -# 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. -# - -WPF_SRC_DIR = ui/wpf/ -WPF_OBJPRE = $(OBJ_DIR)$(WPF_SRC_DIR) - -WPFOBJ = toolkit.o -WPFOBJ += window.o -WPFOBJ += container.o -WPFOBJ += menu.o -WPFOBJ += toolbar.o -WPFOBJ += button.o -WPFOBJ += label.o -WPFOBJ += text.o -WPFOBJ += graphics.o - -TOOLKITOBJS += $(WPFOBJ:%=$(WPF_OBJPRE)%) -TOOLKITSOURCE += $(WPFOBJ:%.o=wpf/%.c)
--- a/ui/wpf/text.c Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,140 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2015 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 "text.h" - -UIWIDGET ui_textarea(UiObject *obj, UiText *value) { - UiContainer *container = uic_get_current_container(obj); - UIWIDGET textarea = UItextarea(container, value ? value->value : NULL); - - if(value) { - value->get = ui_textarea_get; - value->set = ui_textarea_set; - value->getsubstr = ui_textarea_getsubstr; - value->insert = ui_textarea_insert; - value->position = ui_textarea_position; - value->selection = ui_textarea_selection; - value->length = ui_textarea_length; - value->remove = ui_textarea_remove; - value->value = NULL; - value->obj = textarea; - if(!value->undomgr) { - //value->undomgr = ; - } - } - - return textarea; -} - -UIWIDGET ui_textarea_nv(UiObject *obj, char *varname) { - UiVar *var = uic_connect_var(obj->ctx, varname, UI_VAR_TEXT); - if(var) { - UiText *value = var->value; - return ui_textarea(obj, value); - } else { - // TODO: error - } - return NULL; -} - -char* ui_textarea_get(UiText *text) { - if(text->value) { - UIfreestr(text->value); - } - text->value = UItextarea_get(text->obj); - return text->value; -} - -void ui_textarea_set(UiText *text, char *str) { - if(text->value) { - UIfreestr(text->value); - text->value = NULL; - } - UItextarea_set(text->obj, str); -} - -char* ui_textarea_getsubstr(UiText *text, int begin, int end) { - if(text->value) { - UIfreestr(text->value); - } - text->value = UItextarea_getsubstr(text->obj, begin, end); - return text->value; -} - -void ui_textarea_insert(UiText *text, int pos, char *str) { - if(text->value) { - UIfreestr(text->value); - text->value = NULL; - } - UItextarea_insert(text->obj, pos, str); -} - -int ui_textarea_position(UiText *text) { - return UItextarea_position(text->obj); -} - -void ui_textarea_selection(UiText *text, int *begin, int *end) { - UItextarea_selection(text->obj, begin, end); -} - -int ui_textarea_length(UiText *text) { - return UItextarea_length(text->obj); -} - -void ui_textarea_remove(UiText *text, int begin, int end) { - if(text->value) { - UIfreestr(text->value); - text->value = NULL; - } - UItextarea_remove(text->obj, begin, end); -} - - -UIWIDGET ui_textfield(UiObject *obj, UiString *value) { - UiContainer *container = uic_get_current_container(obj); - UIWIDGET textfield = UItextfield(container, value ? value->value : NULL); - - if(value) { - // TODO - } - return textfield; -} - -UIWIDGET ui_textfield_nv(UiObject *obj, char *varname) { - UiVar *var = uic_connect_var(obj->ctx, varname, UI_VAR_STRING); - if(var) { - UiString *value = var->value; - return ui_textfield(obj, value); - } else { - // TODO: error - } - return NULL; -}
--- a/ui/wpf/text.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,69 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2015 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 TEXT_H -#define TEXT_H - -#include "../ui/text.h" -#include "toolkit.h" - -#ifdef __cplusplus -extern "C" { -#endif - -UI_IMPORT UIWIDGET __stdcall UItextarea(void *container, char *text); - -char* ui_textarea_get(UiText *text); -void ui_textarea_set(UiText *text, char *str); -char* ui_textarea_getsubstr(UiText *text, int begin, int end); -void ui_textarea_insert(UiText *text, int pos, char *str); -int ui_textarea_position(UiText *text); -void ui_textarea_selection(UiText *text, int *begin, int *end); -int ui_textarea_length(UiText *text); -void ui_textarea_remove(UiText *text, int begin, int end); - -UI_IMPORT void __stdcall UItextarea_set(UIWIDGET textarea, char *str); -UI_IMPORT char* __stdcall UItextarea_get(UIWIDGET textarea); -UI_IMPORT char* __stdcall UItextarea_getsubstr(UIWIDGET textarea, int begin, int end); -UI_IMPORT void __stdcall UItextarea_insert(UIWIDGET textarea, int pos, char *str); -UI_IMPORT int __stdcall UItextarea_position(UIWIDGET textarea); -UI_IMPORT void __stdcall UItextarea_selection(UIWIDGET textarea, int *begin, int *end); -UI_IMPORT int __stdcall UItextarea_length(UIWIDGET textarea); -UI_IMPORT void __stdcall UItextarea_remove(UIWIDGET textarea, int begin, int end); - -UI_IMPORT void __stdcall UIfreestr(char *str); - - -UI_IMPORT UIWIDGET __stdcall UItextfield(void *container, char *text); - -#ifdef __cplusplus -} -#endif - -#endif /* TEXT_H */ -
--- a/ui/wpf/toolbar.c Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,56 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2015 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 "toolbar.h" -#include "menu.h" -#include "../common/context.h" - -void ui_toolitem(char *name, char *label, ui_callback f, void *udata) { - UIcallback cb = NULL; - void *e = NULL; - if (f) { - UiEventData *event = malloc(sizeof(UiEventData)); - event->obj = NULL; - event->user_data = udata; - event->callback = f; - event->value = 0; - cb = (UIcallback)ui_obj_callback; - e = event; - } - - UItoolitem(name, label, cb, e); -} - -void ui_toolbar_add_default(char *name) { - UItoolbar_add_default(name); -} - -
--- a/ui/wpf/toolbar.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2015 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 TOOLBAR_H -#define TOOLBAR_H - -#include "../ui/toolbar.h" -#include "toolkit.h" - -#ifdef __cplusplus -extern "C" { -#endif - -UI_IMPORT void __stdcall UItoolitem(char *name, char *label, UIcallback callback, void *eventdata); - - -UI_IMPORT void __stdcall UItoolbar_add_default(char *name); - - -#ifdef __cplusplus -} -#endif - -#endif /* TOOLBAR_H */ -
--- a/ui/wpf/toolkit.c Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2014 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 "toolkit.h" - - -void ui_init(char *appname, int argc, char **argv) { - UIinit(appname); -} - -void ui_onstartup(ui_callback f, void *userdata) { - UIonstartup(f, userdata); -} - -void ui_onopen(ui_callback f, void *userdata) { - UIonopen(f, userdata); -} - -void ui_onexit(ui_callback f, void *userdata) { - UIonexit(f, userdata); -} - -void ui_main() { - UImain(); -} - -void ui_show(UiObject *obj) { - UIshow(obj->widget); -} - -void ui_set_enabled(UIWIDGET widget, int enabled) { - -} - -void ui_set_show_all(UIWIDGET widget, int value) { - -} \ No newline at end of file
--- a/ui/wpf/toolkit.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,66 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2014 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" - -#ifdef __cplusplus -extern "C" { -#endif - -#define UI_IMPORT __declspec(dllimport) -__declspec(dllimport) int __stdcall myfunc(char *str); - -typedef struct UiEventData { - UiObject *obj; - ui_callback callback; - void *user_data; - int value; -} UiEventData; - -typedef void(*UIcallback)(void*,void*); - -UI_IMPORT void __stdcall UIinit(char *appname); - -UI_IMPORT void __stdcall UIonstartup(ui_callback f, void *userdata); -UI_IMPORT void __stdcall UIonopen(ui_callback f, void *userdata); -UI_IMPORT void __stdcall UIonexit(ui_callback f, void *userdata); -UI_IMPORT void __stdcall UImain(); -UI_IMPORT void __stdcall UIshow(UIWIDGET widget); - -#ifdef __cplusplus -} -#endif - -#endif /* TOOLKIT_H */ -
--- a/ui/wpf/window.c Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,49 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2015 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 <string.h> - -#include "../ui/window.h" -#include "../ui/properties.h" -#include "../common/context.h" - -#include "window.h" - -UiObject* ui_window(char *title, void *window_data) { - UcxMempool *mp = ucx_mempool_new(256); - UiObject *obj = ucx_mempool_calloc(mp, 1, sizeof(UiObject)); - obj->widget = UIwindow(title, obj); - obj->ctx = uic_context(obj, mp); - obj->container = (UiContainer*)obj->widget; - //obj->window = window_data; - //obj->next = NULL; - - return obj; -}
--- a/ui/wpf/window.h Sat Apr 05 17:57:04 2025 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. - * - * Copyright 2015 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 WINDOW_H -#define WINDOW_H - -#include "toolkit.h" - -#ifdef __cplusplus -extern "C" { -#endif - -UI_IMPORT UIWIDGET __stdcall UIwindow(char *title, void *uiobj); - -#ifdef __cplusplus -} -#endif - -#endif /* WINDOW_H */ -