]> uap-core.de Git - note.git/commitdiff
show list of image attachments
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 31 Mar 2025 19:12:02 +0000 (21:12 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 31 Mar 2025 19:12:02 +0000 (21:12 +0200)
55 files changed:
application/Makefile
application/attachment.c
application/window.c
configure
make/project.xml
ui/Makefile
ui/cocoa/GridLayout.m
ui/cocoa/appdelegate.m
ui/cocoa/menu.h [new file with mode: 0644]
ui/cocoa/menu.m [new file with mode: 0644]
ui/cocoa/objs.mk
ui/cocoa/text.m
ui/cocoa/toolkit.m
ui/common/condvar.c
ui/common/context.h
ui/common/objs.mk
ui/common/properties.c
ui/common/threadpool.c
ui/gtk/container.h
ui/gtk/image.c
ui/gtk/image.h
ui/gtk/objs.mk
ui/gtk/widget.c
ui/qt/Makefile
ui/qt/button.cpp
ui/qt/button.h
ui/qt/container.cpp
ui/qt/container.h
ui/qt/graphics.cpp
ui/qt/graphics.h
ui/qt/label.cpp
ui/qt/menu.cpp
ui/qt/menu.h
ui/qt/model.cpp
ui/qt/model.h
ui/qt/qt5.pro [new file with mode: 0644]
ui/qt/stock.cpp
ui/qt/stock.h
ui/qt/text.cpp
ui/qt/text.h
ui/qt/toolbar.cpp
ui/qt/toolbar.h
ui/qt/toolkit.cpp
ui/qt/toolkit.h
ui/qt/tree.cpp
ui/qt/tree.h
ui/qt/window.cpp
ui/ui/container.h
ui/ui/image.h
ui/ui/toolkit.h
ui/ui/widget.h
ui/win32/Makefile [new file with mode: 0644]
ui/win32/objs.mk [new file with mode: 0644]
ui/win32/toolkit.c [new file with mode: 0644]
ui/win32/toolkit.h [new file with mode: 0644]

index 0549e3e4a0f500a63ba36f84b64e45497668a8b8..89823cba5a67ba723bc51d173c919d402669bc63 100644 (file)
@@ -56,8 +56,8 @@ TEST_BIN = ../build/bin/notetest$(APP_EXT)
 
 all: $(APP_BIN) $(TEST_BIN)
 
-$(APP_BIN): $(MAIN_OBJ) $(OBJ) $(BUILD_ROOT)/build/lib/libuitk.a 
-       $(CC) -o $(APP_BIN) $(MAIN_OBJ) $(OBJ) -L$(BUILD_ROOT)/build/lib -luitk -lucx -lidav -ldbutils -lmd4c $(LDFLAGS) $(TK_LDFLAGS) $(DAV_LDFLAGS) $(DBU_LDFLAGS)
+$(APP_BIN): $(MAIN_OBJ) $(OBJ) 
+       $(LD) -o $(APP_BIN) $(MAIN_OBJ) $(OBJ) -L$(BUILD_ROOT)/build/lib -luitk -lucx -lidav -ldbutils -lmd4c $(LDFLAGS) $(TK_LDFLAGS) $(DAV_LDFLAGS) $(DBU_LDFLAGS)
 
 $(TEST_BIN): $(OBJ) $(TEST_OBJ) $(BUILD_ROOT)/build/lib/libuitk.a 
        $(CC) -o $(TEST_BIN) $(TEST_OBJ) $(OBJ) -L$(BUILD_ROOT)/build/lib -luitk -lucx -lidav -ldbutils -lmd4c $(LDFLAGS) $(TK_LDFLAGS) $(DAV_LDFLAGS) $(DBU_LDFLAGS)
index 3bb2f52478482167cb172dff363f750b80d218d1..b51678f7c8bdb2cea5e3e5f5c449ed9267b046f5 100644 (file)
@@ -72,6 +72,7 @@ void attachment_item(UiObject *obj, int index, void *elm, void *userdata) {
     Attachment *attachment = elm;
     
     if(attachment->type == NOTE_ATTACHMENT_IMAGE) {
-        ui_imageviewer(obj, .value = attachment->ui->img, .scrollarea = FALSE);
+        UIWIDGET imgviewer = ui_imageviewer(obj, .value = attachment->ui->img, .scrollarea = FALSE, .autoscale = TRUE);
+        ui_widget_set_size(imgviewer, 100, 80);
     }
 }
index 85333e1cf39c331e3cb1367c26f10ba228d0544c..73a247af67e2b18acd20dd46f8e1e793f2966b86 100644 (file)
@@ -89,9 +89,11 @@ void window_create() {
                         ui_button(obj, .icon = "insert-link");
                     }
                     ui_hbox_w(obj, wdata->attachments, .margin = 10, .fill = UI_OFF) {
-                        ui_scrolledwindow(obj, .name = "note_attachments_sw") {
+                        void *sw;
+                        ui_scrolledwindow_w(obj, sw, .name = "note_attachments_sw") {
                             ui_itemlist(obj, .varname = "note_attachments", .container = UI_CONTAINER_HBOX, .create_ui = attachment_item, .userdata = wdata);
                         }
+                        ui_widget_set_size(sw, -1, 120);
                     }
                     //ui_set_visible(wdata->attachments, FALSE);
                     //ui_widget_set_groups(obj->ctx, wdata->attachments, (ui_enablefunc)ui_set_visible, APP_STATE_NOTE_HAS_ATTACHMENTS, -1);
index e2b8929c1dde5b421475535db20b16df67f97e6f..32aae079595ae253f24cf0256b8409c18ea9cf37 100755 (executable)
--- a/configure
+++ b/configure
@@ -72,7 +72,7 @@ Installation directories:
 Options:
   --debug                 add extra compile flags for debug builds
   --release               add extra compile flags for release builds
-  --toolkit=(libadwaita|gtk4|gtk3|cocoa|motif)
+  --toolkit=(libadwaita|gtk4|gtk3|cocoa|qt5|motif)
 
 __EOF__
 }
@@ -245,6 +245,9 @@ __EOF__
 # check languages
 lang_c=
 lang_cpp=
+if detect_cpp_compiler ; then
+    lang_cpp=1
+fi
 if detect_c_compiler ; then
     lang_c=1
 fi
@@ -677,6 +680,44 @@ dependency_error_gtk2legacy()
     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... "
@@ -815,6 +856,9 @@ do
             break
         fi
 
+        cat >> "$TEMP_DIR/make.mk" << __EOF__
+LD = \$(CC)
+__EOF__
         break
     done
     break
@@ -830,6 +874,7 @@ do
         cat >> "$TEMP_DIR/make.mk" << __EOF__
 OBJ_EXT = .o
 LIB_EXT = .a
+LIB_PREFIX = lib
 PACKAGE_SCRIPT = package_osx.sh
 __EOF__
         break
@@ -850,6 +895,7 @@ do
         cat >> "$TEMP_DIR/make.mk" << __EOF__
 OBJ_EXT = .o
 LIB_EXT = .a
+LIB_PREFIX = lib
 PACKAGE_SCRIPT = package_unix.sh
 __EOF__
         break
@@ -959,6 +1005,21 @@ APP_PLATFORM_SRC = cocoa-text.m
 __EOF__
     return 0
 }
+checkopt_toolkit_qt5()
+{
+    VERR=0
+    if dependency_error_qt5 ; then
+        VERR=1
+    fi
+    if [ $VERR -ne 0 ]; then
+        return 1
+    fi
+    cat >> "$TEMP_DIR/make.mk" << __EOF__
+TOOLKIT = qt
+LD = \$(CXX)
+__EOF__
+    return 0
+}
 checkopt_toolkit_motif()
 {
     VERR=0
@@ -1164,6 +1225,14 @@ else
             ERROR=1
             DEPENDENCIES_FAILED="option 'toolkit' $DEPENDENCIES_FAILED"
         fi
+    elif [ "$OPT_TOOLKIT" = "qt5" ]; then
+        echo "  toolkit: $OPT_TOOLKIT" >> $TEMP_DIR/options
+        if checkopt_toolkit_qt5 ; 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
index 3b9cacc06490edab2d3e8339238e2433ea32da84..29773682eec796d3da9020f8ee193e20779f9945 100644 (file)
@@ -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">
                <!-- webview unsupported -->
        </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>
-       
        <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>
        <dependency platform="macos">
                <make>OBJ_EXT = .o</make>
                <make>LIB_EXT = .a</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>LIB_PREFIX = lib</make>
                <make>PACKAGE_SCRIPT = package_unix.sh</make>
        </dependency>
        
                                <make>TOOLKIT = cocoa</make>
                                <make>APP_PLATFORM_SRC = cocoa-text.m</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>
                        <value str="qt5">
                                <dependencies>qt5</dependencies>
                                <make>TOOLKIT = qt</make>
-                               <make>LD = $(CXX)</make>
+                               <make>LD = \$(CXX)</make>
                        </value>
-                       <value str="qt4">
-                               <dependencies>qt4</dependencies>
-                               <make>TOOLKIT = qt</make>
-                               <make>LD = $(CXX)</make>
-                       </value>
-                       -->
                        <value str="motif">
                                <dependencies>motif</dependencies>
                                <make>TOOLKIT = motif</make>
index a0d11482c5f3ef788e4e2e1da597baf3c63e57d8..6905986c4862966add9767c8f85f99b28c33291b 100644 (file)
@@ -33,7 +33,7 @@ OBJ_DIR = ../build/
 
 include common/objs.mk
 
-UI_LIB = ../build/lib/libuitk$(LIB_EXT)
+UI_LIB = ../build/lib/$(LIB_PREFIX)uitk$(LIB_EXT)
 
 include $(TOOLKIT)/objs.mk
 OBJ = $(TOOLKITOBJS) $(COMMONOBJS)
@@ -42,6 +42,6 @@ all: $(UI_LIB)
 
 include $(TOOLKIT)/Makefile
 
-$(COMMON_OBJPRE)%.o: common/%.c
+$(COMMON_OBJPRE)uic_%$(OBJ_EXT): common/%.c
        $(CC) -o $@ -c -I../ucx/ $(CFLAGS) $(TK_CFLAGS) $<
 
index 401fe42f393175f2a5e1a84907fcacc00d8eab46..c937948cae3b196754670f1b0bde048d3b5459d4 100644 (file)
@@ -53,7 +53,6 @@
     NSSize s1 = _test.intrinsicContentSize;
     NSEdgeInsets e1 = _test.alignmentRectInsets;
     
-    printf("fuck\n");
 }
  */
 
             GridDef *row = &rows[y];
             
             NSSize size = elm->view.intrinsicContentSize;
+            NSSize size2 = elm->view.fittingSize;
             NSEdgeInsets alignment = elm->view.alignmentRectInsets;
+            // TODO: remove alignment
+            alignment.left = 0;
+            alignment.right = 0;
+            alignment.top = 0;
+            alignment.bottom = 0;
+            if(size.width == NSViewNoIntrinsicMetric) {
+                size.width = size2.width;
+            }
+            if(size.height == NSViewNoIntrinsicMetric) {
+                size.height = size2.height;
+            }
             if(size.width != NSViewNoIntrinsicMetric) {
                 CGFloat width = size.width + alignment.left + alignment.right;
                 if(width > cols[elm->x].preferred_size && elm->colspan <= 1 && span_max == 1) {
                 for(int c=elm->x;c<end_col;c++) {
                     cwidth += cols[c].size;
                 }
-                frame.size.width = cwidth;
+                frame.size.width = cwidth + + alignment.left + alignment.right;
             } else {
-                frame.size.width = col->size;
+                frame.size.width = col->size + alignment.left + alignment.right;
             }
         } else {
-            frame.size.width = elm->preferred_width;
+            frame.size.width = elm->preferred_width + alignment.left + alignment.right;
         }
         if(elm->vfill) {
             if(elm->rowspan > 1) {
             frame.size.height = elm->preferred_height;
         }
         frame.origin.x = col->pos - (alignment.left+alignment.right)/2;
-        frame.origin.y = viewFrame.size.height - row->pos - frame.size.height + ((alignment.top+alignment.right)/2);
+        //frame.origin.y = viewFrame.size.height - row->pos - frame.size.height + ((alignment.top+alignment.right)/2);
+        frame.origin.y = viewFrame.size.height - row->pos - frame.size.height;
         elm->view.frame = frame;
     }
     
     elm.margin = 0;
     elm.colspan = _uilayout.colspan;
     elm.rowspan = _uilayout.rowspan;
-    elm.hfill = _uilayout.hfill;
-    elm.vfill = _uilayout.vfill;
-    elm.hexpand = _uilayout.hexpand;
-    elm.vexpand = _uilayout.vexpand;
+    if(_uilayout.fill) {
+        elm.hfill = TRUE;
+        elm.vfill = TRUE;
+        elm.hexpand = TRUE;
+        elm.vexpand = TRUE;
+    } else {
+        elm.hfill = _uilayout.hfill;
+        elm.vfill = _uilayout.vfill;
+        elm.hexpand = _uilayout.hexpand;
+        elm.vexpand = _uilayout.vexpand;
+    }
     elm.view = view;
     cxListAdd(_children, &elm);
     
index 38226cfe2da94862f1a5bbb68cbb6491b34b85e6..ae4d3fca891094d3276dc6afcf3faeac5ffbd3d2 100644 (file)
 #import "AppDelegate.h"
 
 #import "toolkit.h"
+#import "menu.h"
 
 @implementation AppDelegate
 
 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
+    ui_menu_init();
     ui_cocoa_onstartup();
 }
 
diff --git a/ui/cocoa/menu.h b/ui/cocoa/menu.h
new file mode 100644 (file)
index 0000000..9836fa3
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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/menu.h"
+#import "toolkit.h"
+
+#import "../common/menu.h"
+
+void ui_menu_init(void);
+
+typedef void(*ui_menu_add_f)(NSMenu*, int, UiMenuItemI*);
+
+void add_menu_widget(NSMenu *parent, int i, UiMenuItemI *item);
+void add_menuitem_widget(NSMenu *parent, int i, UiMenuItemI *item);
+void add_menuseparator_widget(NSMenu *parent, int i, UiMenuItemI *item);
+void add_checkitem_widget(NSMenu *parent, int i, UiMenuItemI *item);
+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);
diff --git a/ui/cocoa/menu.m b/ui/cocoa/menu.m
new file mode 100644 (file)
index 0000000..10dd588
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * 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 <stdarg.h>
+
+#import "menu.h"
+#import "window.h"
+
+static ui_menu_add_f createMenuItem[] = {
+    /* UI_MENU                 */ add_menu_widget,
+    /* UI_MENU_ITEM            */ add_menuitem_widget,
+    /* UI_MENU_CHECK_ITEM      */ add_checkitem_widget,
+    /* UI_MENU_RADIO_ITEM      */ add_radioitem_widget,
+    /* UI_MENU_ITEM_LIST       */ add_menuitem_list_widget,
+    /* UI_MENU_CHECKITEM_LIST  */ add_menuitem_list_widget,
+    /* UI_MENU_RADIOITEM_LIST  */ add_menuitem_list_widget,
+    /* UI_MENU_SEPARATOR       */ add_menuseparator_widget
+};
+
+static void add_menu_items(NSMenu *parent, int i, UiMenu *menu) {
+    UiMenuItemI *it = menu->items_begin;
+    int index = 0;
+    while(it) {
+        createMenuItem[it->type](parent, index, it);
+        it = it->next;
+        index++;
+    }
+}
+
+void add_menu_widget(NSMenu *parent, int i, UiMenuItemI *item) {
+    UiMenu *it = (UiMenu*)item;
+    NSString *str = [[NSString alloc] initWithUTF8String:it->label];
+    NSMenu *menu = [[NSMenu alloc] initWithTitle: str];
+    NSMenuItem *menuItem = [parent addItemWithTitle:str action:nil keyEquivalent:@""];
+    [parent setSubmenu:menu forItem:menuItem];
+    
+    add_menu_items(menu, i, it);
+}
+
+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:@""];
+}
+
+void add_menuseparator_widget(NSMenu *parent, int i, UiMenuItemI *item) {
+    
+}
+
+void add_checkitem_widget(NSMenu *parent, int i, UiMenuItemI *item) {
+    
+}
+
+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) {
+    
+}
+
+
+void ui_menu_init(void) {
+    UiMenu *menus_begin = uic_get_menu_list();
+    UiMenu *ls = menus_begin;
+    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:@""];
+            [[NSApp mainMenu] setSubmenu:menu forItem:menuItem];
+            
+            add_menu_items(menu, 0, ls);
+        }
+        ls = (UiMenu*)ls->item.next;
+    }
+}
index 9324579ceda02dc59e1491fccf6db3a7af9a0c6b..f3f20c7c290a16ade1ab843c230c53a295b9797d 100644 (file)
@@ -40,6 +40,7 @@ COCOAOBJ += window.o
 COCOAOBJ += Container.o
 COCOAOBJ += button.o
 COCOAOBJ += text.o
+COCOAOBJ += menu.o
 
 TOOLKITOBJS += $(COCOAOBJ:%=$(COCOA_OBJPRE)%)
 TOOLKITSOURCE += $(COCOAOBJ:%.o=cocoa/%.m)
index 74d6a790ced6fddac8fdb750c81086089dc22223..37d04a8c320ec92b937114b3dcdc6d38d9919048 100644 (file)
 #import <objc/runtime.h>
 
 UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs args) {
-    //NSScrollView *scrollview = [[NSScrollView alloc] initWithFrame:(NSRect){ 0, 0, 40, 40}];
-    NSTextView *textview = [[NSTextView alloc] initWithFrame:(NSRect){ 0, 0, 40, 40}];
-    //scrollview.documentView = textview;
+    NSTextView *textview = [[NSTextView alloc] init];
+    textview.autoresizingMask = NSViewWidthSizable;
+    textview.minSize = NSMakeSize(0, 0);
+    textview.maxSize = NSMakeSize(FLT_MAX, FLT_MAX);
+    
+    NSScrollView *scrollview = [[NSScrollView alloc] init];
+    scrollview.hasVerticalScroller = YES;
+    scrollview.documentView = textview;
     
     UiLayout layout = UI_INIT_LAYOUT(args);
-    ui_container_add(obj, textview, &layout, TRUE);
+    ui_container_add(obj, scrollview, &layout, TRUE);
     
-    return (__bridge void*)textview;
+    return (__bridge void*)scrollview;
 }
index 9299672ee18620dfa152f8c26fd4e960825ebbef..2501a3f65ffc7260262812f24a4d2f5768396307 100644 (file)
@@ -34,6 +34,8 @@
 #include "../common/toolbar.h"
 #include "../common/threadpool.h"
 
+#import "menu.h"
+
 #import "AppDelegate.h"
 
 static const char *application_name;
index c61e70c55bc9a115216c9db819dcdd5c275207a7..16f49549932d89fb1725d474eaa360961756a425 100644 (file)
@@ -26,6 +26,8 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifndef _WIN32
+
 #include "condvar.h"
 
 #include <stdlib.h>
@@ -68,3 +70,5 @@ void ui_condvar_destroy(UiCondVar *var) {
     free(p);
     
 }
+
+#endif
\ No newline at end of file
index fdcd6a886d679ac2ee621d69681d60bf02e439de..f07b6da02eaae547ba5a63fc12b0b0104e9cb08d 100644 (file)
@@ -45,9 +45,7 @@ typedef struct UiListPtr     UiListPtr;
 typedef struct UiListVar     UiListVar;
 typedef struct UiGroupWidget UiGroupWidget;
 
-typedef enum UiVarType UiVarType;
-
-enum UiVarType {
+typedef enum UiVarType {
     UI_VAR_SPECIAL = 0,
     UI_VAR_INTEGER,
     UI_VAR_DOUBLE,
@@ -56,7 +54,7 @@ enum UiVarType {
     UI_VAR_LIST,
     UI_VAR_RANGE,
     UI_VAR_GENERIC
-};
+} UiVarType;
 
 struct UiContext {
     UiContext     *parent;
index b8980afb1239382950af4fd493c2e712b96876ea..bc1b385abe8977a874d0a26749ce68566879aced 100644 (file)
 COMMON_SRC_DIR = ui/common/
 COMMON_OBJPRE = $(OBJ_DIR)$(COMMON_SRC_DIR)
 
-COMMON_OBJ = context.o
-COMMON_OBJ += document.o
-COMMON_OBJ += object.o
-COMMON_OBJ += types.o
-COMMON_OBJ += menu.o
-COMMON_OBJ += properties.o
-COMMON_OBJ += menu.o
-COMMON_OBJ += toolbar.o
-COMMON_OBJ += ucx_properties.o
-COMMON_OBJ += threadpool.o
-COMMON_OBJ += condvar.o
+COMMON_OBJ = context$(OBJ_EXT)
+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)
 
-TOOLKITOBJS += $(COMMON_OBJ:%=$(COMMON_OBJPRE)%)
-TOOLKITSOURCE += $(COMMON_OBJ:%.o=common/%.c)
+TOOLKITOBJS += $(COMMON_OBJ:%=$(COMMON_OBJPRE)uic_%)
+TOOLKITSOURCE += $(COMMON_OBJ:%$(OBJ_EXT)=common/%.c)
 
index 45a9b4e80deeb9c61e81e18484da43ac3db09dcb..1d7311a49dec18f6fedbcdb68c9c5aee3e0b2242 100644 (file)
@@ -116,7 +116,7 @@ char* ui_configfile(char *name) {
 
 static int ui_mkdir(char *path) {
 #ifdef _WIN32
-    return mkdir(path);
+    return _mkdir(path);
 #else
     return mkdir(path, S_IRWXU);
 #endif
index d3725c999da419b67df12b2590cf23a1f49c4ba8..7a37407621b98d8556fd53120accb700c1df605d 100644 (file)
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#ifndef _WIN32
+
 #include "threadpool.h"
 #include "context.h"
 
-#ifndef _WIN32
-
 #include <pthread.h>
 #include <stdio.h>
 #include <string.h>
index e7734add376786f09d184831c6d1c2edf137d7a0..b39a3e4f4b485cd5368d98ecd0ceedb0e97ee831 100644 (file)
@@ -42,7 +42,7 @@
 #ifdef __cplusplus
 extern "C" {
 #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)
@@ -51,15 +51,14 @@ typedef void (*ui_container_add_f)(UiContainer*, GtkWidget*, UiBool);
 
 typedef struct UiDocumentView UiDocumentView;
 
-typedef struct UiLayout UiLayout;
-typedef enum UiLayoutBool UiLayoutBool;
 
-enum UiLayoutBool {
+typedef enum UiLayoutBool {
     UI_LAYOUT_UNDEFINED = 0,
     UI_LAYOUT_TRUE,
     UI_LAYOUT_FALSE,
-};
+} UiLayoutBool;
 
+typedef struct UiLayout UiLayout;
 struct UiLayout {
     UiLayoutBool fill;
     UiBool       newline;
index 3c2a0e6498f631c6e30609233d9c5ca79b21f4ee..41c9b44ef615d8d0943dbe46c3ed2a923661c58e 100644 (file)
 #include "../common/context.h"
 #include "../common/object.h"
 
+static void imageviewer_destroy(UiImageViewer *iv) {
+    if(iv->pixbuf) {
+        g_object_unref(iv->pixbuf);
+    }
+    free(iv);
+}
+
+#if GTK_MAJOR_VERSION >= 4
+
+static void imageviewer_draw(
+        GtkDrawingArea *drawingarea,
+        cairo_t *cr,
+        int width,
+        int height,
+        gpointer userdata)
+{
+    ui_cairo_draw_image(userdata, cr, width, height);
+}
 
-UIWIDGET ui_imageviewer_create(UiObject *obj, UiImageViewerArgs args) {
-    UiObject *current = uic_current_obj(obj);
-    
-    GtkWidget *scrolledwindow = SCROLLEDWINDOW_NEW();
-#if GTK_CHECK_VERSION(4, 0, 0)
-    GtkWidget *image = gtk_picture_new();
 #else
-    GtkWidget *image = gtk_image_new();
+
+static gboolean imageviewer_draw(GtkWidget *widget, cairo_t *cr, gpointer userdata) {
+    int width = gtk_widget_get_allocated_width(widget);
+    int height = gtk_widget_get_allocated_height(widget);
+    ui_cairo_draw_image(userdata, cr, width, height);
+    return FALSE;
+}
+
 #endif
+
+UIWIDGET ui_imageviewer_create(UiObject *obj, UiImageViewerArgs args) {
+    UiObject *current = uic_current_obj(obj);
     
-    ui_set_name_and_style(image, args.name, args.style_class);
+    GtkWidget *drawingarea = gtk_drawing_area_new();
+    GtkWidget *toplevel;
+    GtkWidget *widget = drawingarea;
+      
+    gtk_widget_set_size_request(drawingarea, 100, 100);
     
 #if GTK_MAJOR_VERSION < 4
     GtkWidget *eventbox = gtk_event_box_new();
-    SCROLLEDWINDOW_SET_CHILD(scrolledwindow, eventbox);
-    gtk_container_add(GTK_CONTAINER(eventbox), image);
-#else
-    SCROLLEDWINDOW_SET_CHILD(scrolledwindow, image);
-    GtkWidget *eventbox = image;
+    gtk_container_add(GTK_CONTAINER(eventbox), drawingarea);
+    widget = eventbox;
 #endif
     
-    UI_APPLY_LAYOUT1(current, args);
-    current->container->add(current->container, scrolledwindow, TRUE);
+    if(args.scrollarea) {
+        toplevel = SCROLLEDWINDOW_NEW();
+        SCROLLEDWINDOW_SET_CHILD(toplevel, widget);
+        args.adjustwidgetsize = TRUE;
+    } else {
+        toplevel = widget;
+    }
+    
+    UiImageViewer *imgviewer = malloc(sizeof(UiImageViewer));
+    memset(imgviewer, 0, sizeof(UiImageViewer));
+    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->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);
+    imgviewer->var = var;
+    imgviewer->widget = drawingarea;
+    
     if(var) {
         UiGeneric *value = var->value;
         value->get = ui_imageviewer_get;
         value->get_type = ui_imageviewer_get_type;
         value->set = ui_imageviewer_set;
-        value->obj = image;
+        value->obj = imgviewer;
         if(value->value && value->type && !strcmp(value->type, UI_IMAGE_OBJECT_TYPE)) {
             GdkPixbuf *pixbuf = value->value;
             value->value = NULL;
@@ -72,20 +123,164 @@ UIWIDGET ui_imageviewer_create(UiObject *obj, UiImageViewerArgs args) {
         }
     }
     
+#if GTK_MAJOR_VERSION >= 4
+    gtk_drawing_area_set_draw_func(
+            GTK_DRAWING_AREA(drawingarea),
+            imageviewer_draw,
+            imgviewer,
+            NULL);
+    
+    if(args.useradjustable) {
+        gtk_widget_set_focusable(drawingarea, TRUE);
+    }
+    
+    GtkEventController *scrollcontroller = gtk_event_controller_scroll_new(GTK_EVENT_CONTROLLER_SCROLL_VERTICAL);
+    g_signal_connect(scrollcontroller, "scroll", G_CALLBACK(ui_imageviewer_scroll), imgviewer);
+    gtk_widget_add_controller(GTK_WIDGET(drawingarea), GTK_EVENT_CONTROLLER(scrollcontroller));
+    
+    GtkGesture *drag = gtk_gesture_drag_new();
+    g_signal_connect(drag, "drag-begin", G_CALLBACK(ui_imageviewer_drag_begin_cb), imgviewer);
+    g_signal_connect(drag, "drag-end", G_CALLBACK(ui_imageviewer_drag_end_cb), imgviewer);
+    g_signal_connect(drag, "drag-update", G_CALLBACK(ui_imageviewer_drag_update_cb), imgviewer);
+    gtk_widget_add_controller(GTK_WIDGET(drawingarea), GTK_EVENT_CONTROLLER(drag));
+    
+#elif GTK_MAJOR_VERSION == 3
+    g_signal_connect(
+            drawingarea,
+            "draw",
+            G_CALLBACK(imageviewer_draw),
+            imgviewer);
+    
+    gtk_widget_add_events(eventbox, GDK_SCROLL_MASK);
+    
+    g_signal_connect(
+            eventbox,
+            "scroll-event",
+            G_CALLBACK(ui_imageviewer_scroll_event),
+            imgviewer);
+    g_signal_connect(
+            eventbox,
+            "button-press-event",
+            G_CALLBACK(ui_imageviewer_button_press_event),
+            imgviewer);
+    g_signal_connect(
+            eventbox,
+            "button-release-event",
+            G_CALLBACK(ui_imageviewer_button_release_event),
+            imgviewer);
+
+#endif
+    
     if(args.contextmenu) {
-        UIMENU menu = ui_contextmenu_create(args.contextmenu, obj, eventbox);
-        ui_widget_set_contextmenu(eventbox, menu);
+        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);
     
-    return scrolledwindow;
+    return toplevel;
+}
+
+static void imageviewer_reset(UiImageViewer *imgviewer) {
+    imgviewer->isautoscaled = FALSE;
+    imgviewer->transx = 0;
+    imgviewer->transy;
+    imgviewer->begin_transx = 0;
+    imgviewer->begin_transy = 0;
+    imgviewer->scale = 1;
+    imgviewer->user_scale = 1;
+}
+
+UIWIDGET ui_imageviewer_reset(UIWIDGET w) {
+    UiImageViewer *imgviewer = g_object_get_data(G_OBJECT(w), "uiimageviewer");
+    if(imgviewer) {
+        imageviewer_reset(imgviewer);
+        gtk_widget_queue_draw(w);
+    }
+}
+
+UIWIDGET ui_imageviewer_set_autoscale(UIWIDGET w, UiBool set) {
+    UiImageViewer *imgviewer = g_object_get_data(G_OBJECT(w), "uiimageviewer");
+    if(imgviewer) {
+        imgviewer->autoscale = set;
+    }
+}
+
+UIWIDGET ui_imageviewer_set_adjustwidgetsize(UIWIDGET w, UiBool set) {
+    UiImageViewer *imgviewer = g_object_get_data(G_OBJECT(w), "uiimageviewer");
+    if(imgviewer) {
+        imgviewer->adjustwidgetsize = set;
+    }
+}
+
+UIWIDGET ui_imageviewer_set_useradjustable(UIWIDGET w, UiBool set) {
+    UiImageViewer *imgviewer = g_object_get_data(G_OBJECT(w), "uiimageviewer");
+    if(imgviewer) {
+        imgviewer->useradjustable = set;
+    }
+}
+
+void ui_cairo_draw_image(UiImageViewer *imgviewer, cairo_t *cr, int width, int height) {
+    if(!imgviewer->pixbuf) {
+        return;
+    }
+    
+    GdkPixbuf *pixbuf = imgviewer->pixbuf;
+    double dpixwidth = (double)gdk_pixbuf_get_width(pixbuf);
+    double dpixheight = (double)gdk_pixbuf_get_height(pixbuf);
+    
+    double dwidth = width;
+    double dheight = height;
+    double scale = 1;
+    // if autoscale is enabled, scale the image to fill available space
+    // if useradjustable is also enabled, the autoscaling is only done once
+    if(imgviewer->autoscale && imgviewer->scale != 0) {
+        if(!imgviewer->isautoscaled) {
+            scale = dwidth / dpixwidth;
+            if(dpixheight * scale > dheight) {
+                scale = dheight / dpixheight;
+            }
+
+            if(imgviewer->useradjustable) {
+                imgviewer->isautoscaled = TRUE;
+            }
+            
+            imgviewer->scale = scale;
+        } else {
+            scale = imgviewer->scale;
+        }
+        
+        imgviewer->user_scale = scale;
+    } else {
+        // user-adjusted scaling
+        //scale = 1 + ((double)imgviewer->zoom / (double)imgviewer->zoom_scale);
+        scale = imgviewer->user_scale;
+    }
+
+    dpixwidth *= scale;
+    dpixheight *= scale;
+    double x = (dwidth - dpixwidth) / 2;
+    double y = (dheight - dpixheight) / 2;
+    
+    x += imgviewer->transx;
+    y += imgviewer->transy;
+    
+    cairo_translate(cr, x, y);
+    cairo_scale(cr, scale, scale);
+    
+    gdk_cairo_set_source_pixbuf(cr, pixbuf, 0, 0);
+    cairo_paint(cr);
 }
 
 void* ui_imageviewer_get(UiGeneric *g) {
+    UiImageViewer *imgviewer = g->obj;
+    g->value = imgviewer->pixbuf;
     return g->value;
 }
 
 const char* ui_imageviewer_get_type(UiGeneric *g) {
-    
+    return UI_IMAGE_OBJECT_TYPE;
 }
 
 int ui_imageviewer_set(UiGeneric *g, void *value, const char *type) {
@@ -93,25 +288,24 @@ int ui_imageviewer_set(UiGeneric *g, void *value, const char *type) {
         return 1;
     }
     
-    // TODO: do we need to free the previous value here?
-    
-    g->value = value;
-    g->type = type;
     GdkPixbuf *pixbuf = value;
     
-    if(pixbuf) {
+    UiImageViewer *imgviewer = g->obj;
+    g->value = pixbuf;
+    
+    imageviewer_reset(imgviewer);
+    
+    if(imgviewer->pixbuf) {
+        g_object_unref(imgviewer->pixbuf);
+    }
+    imgviewer->pixbuf = pixbuf;
+    
+    if(imgviewer->adjustwidgetsize && !imgviewer->autoscale) {
         int width = gdk_pixbuf_get_width(pixbuf);
         int height = gdk_pixbuf_get_height(pixbuf);
-        
-#if GTK_CHECK_VERSION(4, 0, 0)
-        GdkTexture *texture = gdk_texture_new_for_pixbuf(pixbuf);
-        gtk_picture_set_paintable(GTK_PICTURE(g->obj), GDK_PAINTABLE(texture));
-#else
-        gtk_image_set_from_pixbuf(GTK_IMAGE(g->obj), pixbuf);
-#endif
-        gtk_widget_set_size_request(g->obj, width, height);
+        gtk_widget_set_size_request(imgviewer->widget, width, height);
     }
-
+    gtk_widget_queue_draw(imgviewer->widget);
     
     return 0;
 }
@@ -130,6 +324,91 @@ int ui_image_load_file(UiGeneric *obj, const char *path) {
     } else {
         obj->value = pixbuf;
     }
-    
+       
     return 0;
 }
+
+#if GTK_MAJOR_VERSION >= 4
+
+gboolean ui_imageviewer_scroll(
+        GtkEventControllerScroll *widget,
+        gdouble dx,
+        gdouble dy,
+        gpointer userdata)
+{
+    UiImageViewer *imgviewer = userdata;
+    if(imgviewer->useradjustable) {
+        double step = dy / imgviewer->zoom_scale;
+        if(imgviewer->user_scale - step > 0) {
+            imgviewer->user_scale -= step;
+        }
+        
+        imgviewer->scale = 0; // disable autoscale
+        gtk_widget_queue_draw(imgviewer->widget);
+        return TRUE;
+    }
+    return FALSE;
+}
+
+void ui_imageviewer_drag_begin_cb(
+        GtkGestureDrag* self,
+        gdouble start_x,
+        gdouble start_y,
+        gpointer userdata)
+{
+    UiImageViewer *imgviewer = userdata;
+    imgviewer->begin_transx = imgviewer->transx;
+    imgviewer->begin_transy = imgviewer->transy;
+}
+
+void ui_imageviewer_drag_end_cb(
+        GtkGestureDrag* self,
+        gdouble x,
+        gdouble y,
+        gpointer userdata)
+{
+    
+}
+
+void ui_imageviewer_drag_update_cb(
+        GtkGestureDrag* self,
+        gdouble x,
+        gdouble y,
+        gpointer userdata)
+{
+    UiImageViewer *imgviewer = userdata;
+    if(imgviewer->useradjustable) {
+        imgviewer->transx = imgviewer->begin_transx + x;
+        imgviewer->transy = imgviewer->begin_transy + y;
+        gtk_widget_queue_draw(imgviewer->widget);
+    }
+}
+
+#else
+
+gboolean ui_imageviewer_scroll_event(
+        GtkWidget *widget,
+        GdkEventScroll event,
+        gpointer userdata)
+{
+    printf("scroll event\n");
+    return FALSE;
+}
+
+gboolean ui_imageviewer_button_press_event(
+        GtkWidget *widget,
+        GdkEventButton event,
+        gpointer userdata)
+{
+    printf("button pressed\n");
+}
+
+gboolean ui_imageviewer_button_release_event(
+        GtkWidget *widget,
+        GdkEventButton event,
+        gpointer userdata)
+{
+    printf("button released\n");
+}
+
+#endif
index 00c205d89d71eb5d7ec57a6ddbda39b962435619..7e9bf9f0104c6b8fa1224d5121a6f430e5dd86ce 100644 (file)
 extern "C" {
 #endif
 
+typedef struct UiImageViewer {
+    GtkWidget *widget;
+    UiVar *var;
+    int padding_left;
+    int padding_right;
+    int padding_top;
+    int padding_bottom;
+    UiBool autoscale;
+    UiBool adjustwidgetsize;
+    UiBool useradjustable;
+    GdkPixbuf *pixbuf;
+    
+    double zoom_scale;
+    int transx;
+    int transy;
+    int begin_transx;
+    int begin_transy;
+    UiBool isautoscaled;
+    double user_scale;
+    double scale;
+} UiImageViewer;
+
+void ui_cairo_draw_image(UiImageViewer *imgviewer, cairo_t *cr, int width, int height);
 
 void* ui_imageviewer_get(UiGeneric *g);
 const char* ui_imageviewer_get_type(UiGeneric *g);
 int ui_imageviewer_set(UiGeneric *g, void *value, const char *type);
 
+#if GTK_MAJOR_VERSION >= 4
+
+gboolean ui_imageviewer_scroll(
+        GtkEventControllerScroll *widget,
+        gdouble dx,
+        gdouble dy,
+        gpointer userdata);
+
+void ui_imageviewer_drag_begin_cb(
+        GtkGestureDrag* self,
+        gdouble start_x,
+        gdouble start_y,
+        gpointer userdata);
+
+void ui_imageviewer_drag_end_cb(
+        GtkGestureDrag* self,
+        gdouble x,
+        gdouble y,
+        gpointer userdata);
+
+void ui_imageviewer_drag_update_cb(
+        GtkGestureDrag* self,
+        gdouble x,
+        gdouble y,
+        gpointer userdata);
+
+#else
+
+gboolean ui_imageviewer_scroll_event(
+        GtkWidget *widget,
+        GdkEventScroll event,
+        gpointer userdata);
+
+gboolean ui_imageviewer_button_press_event(
+        GtkWidget *widget,
+        GdkEventButton event,
+        gpointer userdata);
+
+gboolean ui_imageviewer_button_release_event(
+        GtkWidget *widget,
+        GdkEventButton event,
+        gpointer userdata);
+
+#endif
+
 #ifdef __cplusplus
 }
 #endif
index ed89f4d41a47e5010192bd3831c457ab0f66f892..abad5a0679c8ab7a816f25b1260ab08ae5bbcffe 100644 (file)
@@ -47,6 +47,7 @@ GTKOBJ += entry.o
 GTKOBJ += dnd.o
 GTKOBJ += headerbar.o
 GTKOBJ += webview.o
+GTKOBJ += widget.o
 
 TOOLKITOBJS += $(GTKOBJ:%=$(GTK_OBJPRE)%)
 TOOLKITSOURCE += $(GTKOBJ:%.o=gtk/%.c)
index 63d047805a72e208af0b28bf717244f1f712d843..505bca6499eff47839e533897e5f24edf717a224 100644 (file)
@@ -41,3 +41,20 @@ UIEXPORT UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func cre
     
     return widget;
 }
+
+UIWIDGET ui_separator_create(UiObject *obj, UiWidgetArgs *args) {
+    UiObject* current = uic_current_obj(obj);
+    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);
+    return widget;
+}
+
+void ui_widget_set_size(UIWIDGET w, int width, int height) {
+    gtk_widget_set_size_request(w, width, height);
+}
+
+void ui_widget_redraw(UIWIDGET w) {
+    gtk_widget_queue_draw(w);
+}
index a1e7f99c45d8e147de244e47c81851cf09eda741..824c467f03a493311c8561f27f2661c0f551c781 100644 (file)
@@ -30,8 +30,8 @@ QT_MAKEFILE = ../build/ui/qt/Makefile.mk
 
 UI_QT_LIB = ../build/ui/qt/
 
-$(QT_MAKEFILE): qt/qt4.pro
-       qmake-qt4 -o - qt/qt4.pro > $(QT_MAKEFILE)
+$(QT_MAKEFILE): qt/$(QT_PRO_FILE)
+       $(QMAKE) -o - $< > $(QT_MAKEFILE)
 
 $(UI_LIB): $(QT_MAKEFILE) $(OBJ) FORCE
        $(MAKE) -f $(QT_MAKEFILE)
index 04b84a4ad8211af2292cba1961f65f5d2ba6c2f9..311c611430e289fc4e8dfb1fa66971738363fa24 100644 (file)
 #include "container.h"
 #include "toolkit.h"
 
-UIWIDGET ui_button(UiObject *obj, char *label, ui_callback f, void *data) {
-    QString str = QString::fromUtf8(label);
+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);
+    QPushButton *button = new QPushButton(str);
+    
+    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);
+    
+    return button;
+}
+
+static void togglebutton_event(UiEvent *event, UiEventWrapper *wrapper) {
+    QPushButton *button = (QPushButton*)wrapper->customdata1;
+    event->intval = button->isChecked();
+    if(wrapper->var) {
+        event->eventdata = wrapper->var->value;
+    }
+}
+
+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);
     QPushButton *button = new QPushButton(str);
+    button->setCheckable(true);
     
-    if(f) {
-        UiEventWrapper *event = new UiEventWrapper(obj, f, data);
+    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);
+        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()));
+    }
+    
+    if(var) {
+        UiInteger *i = (UiInteger*)var->value;
+        
+        if(i->value) {
+            button->setChecked(true);
+        }
+        
+        i->obj = button;
+        i->get = ui_togglebutton_get;
+        i->set = ui_togglebutton_set;
     }
     
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->add(button, false);
+    ctn->add(button, false);
     
     return button;
 }
 
+int64_t ui_togglebutton_get(UiInteger *value) {
+    QPushButton *button = (QPushButton*)value->obj;
+    value->value = button->isChecked();
+    return value->value;
+}
 
+void ui_togglebutton_set(UiInteger *value, int64_t i) {
+    QPushButton *button = (QPushButton*)value->obj;
+    value->value = i;
+    if(i != 0) {
+        button->setChecked(true);
+    }
+}
 
-// TODO: checkbox
+static void checkbox_event(UiEvent *event, UiEventWrapper *wrapper) {
+    QPushButton *button = (QPushButton*)wrapper->customdata1;
+    event->intval = button->isChecked();
+    if(wrapper->var) {
+        event->eventdata = wrapper->var->value;
+    }
+}
 
 
-UIWIDGET ui_radiobutton(UiObject *obj, char *label, UiInteger *rgroup)  {
-    QString str = QString::fromUtf8(label);
-    QRadioButton *button = new QRadioButton(str);
-    button->setAutoExclusive(false);
-    
-    if(rgroup) {
-        QButtonGroup *buttonGroup = (QButtonGroup*)rgroup->obj;
-        if(!buttonGroup) {
-            buttonGroup = new QButtonGroup();
-            rgroup->obj = buttonGroup;
-            button->setChecked(true);
+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);
+    QCheckBox *checkbox = new QCheckBox(str);
+    
+    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);
+        event->var = var;
+        event->customdata1 = checkbox;
+        event->prepare_event = checkbox_event;
+        checkbox->connect(checkbox, SIGNAL(clicked()), event, SLOT(slot()));
+        checkbox->connect(checkbox, SIGNAL(destroyed()), event, SLOT(destroy()));
+    }
+    
+    if(var) {
+        UiInteger *i = (UiInteger*)var->value;
+        
+        if(i->value) {
+            checkbox->setChecked(true);
         }
-        buttonGroup->addButton(button, buttonGroup->buttons().size());
         
-        rgroup->get = ui_radiobutton_get;
-        rgroup->set = ui_radiobutton_set;
+        i->obj = checkbox;
+        i->get = ui_checkbox_get;
+        i->set = ui_checkbox_set;
     }
     
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->add(button, false);
+    ctn->add(checkbox, false);
     
-    return button;
+    return checkbox;
 }
 
-int ui_radiobutton_get(UiInteger *value) {
-    QButtonGroup *buttonGroup = (QButtonGroup*)value->obj;
-    value->value = buttonGroup->checkedId();
+int64_t ui_checkbox_get(UiInteger *value) {
+    QPushButton *button = (QPushButton*)value->obj;
+    value->value = button->isChecked();
     return value->value;
 }
 
-void ui_radiobutton_set(UiInteger *value, int i) {
-    QButtonGroup *buttonGroup = (QButtonGroup*)value->obj;
-    QAbstractButton *button = buttonGroup->button(i);
-    if(button) {
+void ui_checkbox_set(UiInteger *value, int64_t i) {
+    QPushButton *button = (QPushButton*)value->obj;
+    value->value = i;
+    if(i != 0) {
         button->setChecked(true);
-        value->value = i;
     }
 }
index 1761333eed4c21d5ee9cd22c8ad347bd8bc3c984..b848ec6785ee9f88ff4294f4145e8dcc7d896dc3 100644 (file)
 #include <QPushButton>
 #include <QRadioButton>
 #include <QButtonGroup>
+#include <QCheckBox>
 
 extern "C" {
     
-int ui_radiobutton_get(UiInteger *value);
+   
+int64_t ui_togglebutton_get(UiInteger *value);
+void ui_togglebutton_set(UiInteger *value, int64_t i);
 
-void ui_radiobutton_set(UiInteger *value, int i);
+int64_t ui_checkbox_get(UiInteger *value);
+void ui_checkbox_set(UiInteger *value, int64_t i);
+    
+int64_t ui_radiobutton_get(UiInteger *value);
+void ui_radiobutton_set(UiInteger *value, int64_t i);
 
 }
 
index 9cb27d8080482ef58f28e41125f37e7eac835126..bf5bf93b7270f3f574e77e69d4ceeb4bc2d35529 100644 (file)
 
 #include <stdio.h>
 #include "container.h"
+#include "../common/object.h"
+
+#include <cx/mempool.h>
 
 #include <QSpacerItem>
 #include <QStackedWidget>
+#include <QLabel>
 
+static void delete_container(UiContainerPrivate *ct) {
+    delete ct;
+}
+
+void ui_container_add(UiObject *obj, UiContainerPrivate *ct) {
+    UiContainerX *container = (UiContainerX*)ui_malloc(obj->ctx, sizeof(UiContainerX));
+    container->close = 0;
+    container->container = ct;
+    container->prev = NULL;
+    container->next = NULL;
+    cxMempoolRegister(obj->ctx->mp, ct, (cx_destructor_func)delete_container);
+    uic_object_push_container(obj, container);
+}
 
 /* -------------------- UiBoxContainer -------------------- */
 
 UiBoxContainer::UiBoxContainer(QBoxLayout* box) {
-    this->current = NULL;
-    this->menu = NULL;
     this->box = box;
     box->setContentsMargins(QMargins(0,0,0,0));
     box->setSpacing(0);
@@ -71,36 +86,47 @@ void UiBoxContainer::add(QWidget* widget, bool fill) {
     current = widget;
 }
 
-UIWIDGET ui_box(UiObject *obj, QBoxLayout::Direction dir) {
-    UiContainer *ct = uic_get_current_container(obj);
+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);
-    ct->add(widget, true);
+    ctn->add(widget, true);
     
-    UiObject *newobj = uic_object_new(obj, widget);
-    newobj->container = new UiBoxContainer(box);
-    uic_obj_add(obj, newobj);
+    ui_container_add(obj, new UiBoxContainer(box));
     
     return widget;
 }
 
-UIWIDGET ui_vbox(UiObject *obj) {
-    return ui_box(obj, QBoxLayout::TopToBottom);
+UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs args) {
+    return ui_box(obj, args, QBoxLayout::TopToBottom);
 }
 
-UIWIDGET ui_hbox(UiObject *obj) {
-    return ui_box(obj, QBoxLayout::LeftToRight);
+UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs args) {
+    return ui_box(obj, args, QBoxLayout::LeftToRight);
 }
 
 
-
 /* -------------------- UiGridContainer -------------------- */
 
-UiGridContainer::UiGridContainer(QGridLayout* grid, int margin, int columnspacing, int rowspacing) {
+UiGridContainer::UiGridContainer(
+        QGridLayout *grid,
+        int margin,
+        int columnspacing,
+        int rowspacing,
+        bool def_hexpand,
+        bool def_vexpand,
+        bool def_hfill,
+        bool def_vfill)
+{
     this->current = NULL;
-    this->menu = NULL;
     this->grid = grid;
+    this->def_hexpand = def_hexpand;
+    this->def_vexpand = def_vexpand;
+    this->def_hfill = def_hfill;
+    this->def_vfill = def_vfill;
     grid->setContentsMargins(QMargins(margin, margin, margin, margin));
     grid->setHorizontalSpacing(columnspacing);
     grid->setVerticalSpacing(rowspacing);
@@ -113,144 +139,149 @@ void UiGridContainer::add(QWidget* widget, bool fill) {
         y++;
     }
     
-    Qt::Alignment alignment = Qt::AlignTop;
-    grid->setColumnStretch(x, layout.hexpand ? 1 : 0);
+    int hexpand = false;
+    int vexpand = false;
+    int hfill = false;
+    int vfill = false;
+    if(!layout.override_defaults) {
+        if(def_hexpand) {
+            hexpand = true;
+            hfill = true;
+        } else if(def_hfill) {
+            hfill = true;
+        }
+        if(def_vexpand) {
+            vexpand = true;
+            vfill = true;
+        } else if(def_vfill) {
+            vfill = true;
+        }
+    }
+    
+    if(layout.fill != UI_LAYOUT_UNDEFINED) {
+        fill = ui_lb2bool(layout.fill);
+    }
+    if(layout.hexpand) {
+        hexpand = true;
+        //hfill = true;
+    } else if(layout.hfill) {
+        hfill = true;
+    }
     if(layout.vexpand) {
+        vexpand = true;
+        //vfill = true;
+    } else if(layout.vfill) {
+        vfill = true;
+    }
+    if(fill) {
+        hfill = true;
+        vfill = true;
+    }
+    
+    if(hexpand) {
+        col_expanding = true;
+    }
+    if(vexpand) {
+        row_expanding = true;
+    }
+    
+    if(hexpand) {
+        grid->setColumnStretch(x, 1);
+    }
+    if(vexpand) {
         grid->setRowStretch(y, 1);
-        alignment = 0;
-    } else {
-        grid->setRowStretch(y, 0);
     }
     
-    int gwidth = layout.gridwidth > 0 ? layout.gridwidth : 1;
+    Qt::Alignment alignment = 0;
+    if(!hfill) {
+        alignment = Qt::AlignLeft;
+    }
+    if(!vfill) {
+        alignment = Qt::AlignTop;
+    }
+    
+    int colspan = layout.colspan > 0 ? layout.colspan : 1;
+    int rowspan = layout.rowspan > 0 ? layout.rowspan : 1;
+    
+    grid->addWidget(widget, y, x, rowspan, colspan, alignment);
+    
+    if(x > max_x) {
+        max_x = x;
+    }
+    if(y > max_y) {
+        max_y = y;
+    }
     
-    grid->addWidget(widget, y, x, 1, gwidth, alignment);
-    x += gwidth;
+    x += colspan;
     
     ui_reset_layout(layout);
     current = widget;
 }
 
-UIWIDGET ui_grid(UiObject *obj) {
-    return ui_grid_sp(obj, 0, 0, 0);
+void UiGridContainer::end() {
+    if(!col_expanding) {
+        QSpacerItem *filler = new QSpacerItem(0, 0);
+        x = max_x + 1;
+        grid->setColumnStretch(x, 1);
+        grid->addItem(filler, 0, x, 1, 1, 0);
+    }
+    if(!row_expanding) {
+        QSpacerItem *filler = new QSpacerItem(0, 0);
+        y++;
+        grid->setRowStretch(y, 1);
+        grid->addItem(filler, y, 0, 1, 1, 0);
+    }
 }
 
-UIWIDGET ui_grid_sp(UiObject *obj, int margin, int columnspacing, int rowspacing) {
-    UiContainer *ct = uic_get_current_container(obj);
+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);
-    ct->add(widget, true);
+    ctn->add(widget, true);
     
-    UiObject *newobj = uic_object_new(obj, widget);
-    newobj->container = new UiGridContainer(grid, margin, columnspacing, rowspacing);
-    uic_obj_add(obj, newobj);
+    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));
     
     return widget;
 }
 
 
-/* -------------------- UiTabViewContainer -------------------- */
 
-UiTabViewContainer::UiTabViewContainer(QTabWidget* tabwidget) {
-    this->current = NULL;
-    this->menu = NULL;
-    this->tabwidget = tabwidget;
-}
+/* -------------------- Container Helper Functions -------------------- */
 
-void UiTabViewContainer::add(QWidget* widget, bool fill) {
-    QString str = QString::fromUtf8(layout.label);
-    tabwidget->addTab(widget, str);
+void ui_container_begin_close(UiObject *obj) {
+    obj->container_end->close = true;
 }
 
-
-/* -------------------- UiStackContainer -------------------- */
-
-UiStackContainer::UiStackContainer(QStackedWidget *stack) {
-    this->stack = stack;
-}
-
-void UiStackContainer::add(QWidget* widget, bool fill) {
-    stack->addWidget(widget);
-    current = widget;
-}
-
-UIWIDGET ui_tabview(UiObject *obj) {
-    QStackedWidget *tabwidget = new QStackedWidget();
-    
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->add(tabwidget, true);
-    
-    UiObject *tabviewobj = uic_object_new(obj, tabwidget);
-    tabviewobj->container = new UiStackContainer(tabwidget);
-    uic_obj_add(obj, tabviewobj);
-    
-    return tabwidget;
-}
-
-void ui_tab(UiObject *obj, char *title) {
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->layout.label = title;
-    ui_vbox(obj);
-}
-
-void ui_select_tab(UIWIDGET tabview, int tab) {
-    QStackedWidget *w = (QStackedWidget*)tabview;
-    w->setCurrentIndex(tab);
-}
-
-
-/* -------------------- UiSidebarContainer -------------------- */
-
-UiSidebarContainer::UiSidebarContainer(QSplitter *splitter) {
-    this->splitter = splitter;
-}
-
-UIWIDGET ui_sidebar(UiObject *obj) {
-    QSplitter *splitter = new QSplitter(Qt::Horizontal);
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->add(splitter, true);
-    
-    UiObject *left = uic_object_new(obj, splitter);
-    left->container = new UiSidebarContainer(splitter);
-    
-    UiObject *right = uic_object_new(obj, splitter);
-    right->container = new UiSidebarContainer(splitter);
-    
-    uic_obj_add(obj, right);
-    uic_obj_add(obj, left);
-    
-    return splitter;
-}
-
-void UiSidebarContainer::add(QWidget *widget, bool fill) {
-    splitter->addWidget(widget);
-}
-
-
-/* -------------------- layout functions -------------------- */
-
-void ui_layout_fill(UiObject *obj, UiBool fill) {
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->layout.fill = ui_bool2lb(fill);
-}
-
-void ui_layout_hexpand(UiObject *obj, UiBool expand) {
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->layout.hexpand = expand;
+int ui_container_finish(UiObject *obj) {
+    if(obj->container_end->close) {
+        UiContainerPrivate *ctn = (UiContainerPrivate*)obj->container_end->container;
+        ctn->end();
+        ui_end_new(obj);
+        return 0;
+    }
+    return 1;
 }
 
-void ui_layout_vexpand(UiObject *obj, UiBool expand) {
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->layout.vexpand = expand;
-}
 
-void ui_layout_gridwidth(UiObject *obj, int width) {
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->layout.gridwidth = width;
-}
+/*
+ * -------------------- Layout Functions --------------------
+ * 
+ * functions for setting layout attributes for the current container
+ *
+ */
 
 void ui_newline(UiObject *obj) {
-    UiContainer *ct = uic_get_current_container(obj);
+    UiContainerPrivate *ct = ui_obj_container(obj);
     ct->layout.newline = TRUE;
 }
index 1a1c35386ed46f4e7be0296af4b02fc1d2c11213..16ced63893ba9ec67d5d477e4c090deca64e4437 100644 (file)
@@ -30,6 +30,7 @@
 #define        CONTAINER_H
 
 #include "toolkit.h"
+#include "../ui/container.h"
 #include "window.h"
 
 #include <string.h>
 #include <QStackedWidget>
 #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
+
+#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)
-#define ui_reset_layout(layout) memset(&(layout), 0, sizeof(UiLayout))
 
-typedef struct UiLayout UiLayout;
+#define ui_obj_container(obj) (UiContainerPrivate*)((UiContainerX*)obj->container_end)->container
 
-enum UiLayoutBool {
+typedef enum UiLayoutBool {
     UI_LAYOUT_UNDEFINED = 0,
     UI_LAYOUT_TRUE,
     UI_LAYOUT_FALSE,
-};
-typedef enum UiLayoutBool UiLayoutBool;
+} UiLayoutBool;
 
+typedef struct UiLayout UiLayout;
 struct UiLayout {
-    UiLayoutBool fill;
-    bool newline;
-    char *label;
-    bool hexpand;
-    bool vexpand;
-    int  gridwidth;
+    UiTri        fill;
+    UiBool       newline;
+    char         *label;
+    UiBool       hexpand;
+    UiBool       vexpand;
+    UiBool       hfill;
+    UiBool       vfill;
+    UiBool       override_defaults;
+    int          width;
+    int          colspan;
+    int          rowspan;
 };
 
-struct UiContainer {
+struct UiContainerPrivate {
     UiLayout layout; 
     UIWIDGET current;
-    QMenu    *menu;
 
     virtual void add(QWidget *widget, bool fill) = 0;
+    virtual void end() {}
 };
 
-class UiBoxContainer : public UiContainer {
+class UiBoxContainer : public UiContainerPrivate {
 public:
     QBoxLayout  *box;
     bool        hasStretchedWidget = false;
@@ -80,40 +96,36 @@ public:
     virtual void add(QWidget *widget, bool fill);
 };
 
-class UiGridContainer : public UiContainer {
+class UiGridContainer : public UiContainerPrivate {
 public:
     QGridLayout *grid;
     int x = 0;
     int y = 0;
+    bool def_hexpand;
+    bool def_vexpand;
+    bool def_hfill;
+    bool def_vfill;
+    bool col_expanding = false;
+    bool row_expanding = false;
+    int max_x;
+    int max_y;
     
-    UiGridContainer(QGridLayout *grid, int margin, int columnspacing, int rowspacing);
+    UiGridContainer(
+            QGridLayout *grid,
+            int margin,
+            int columnspacing,
+            int rowspacing,
+            bool def_hexpand,
+            bool def_vexpand,
+            bool def_hfill,
+            bool def_vfill);
     
     virtual void add(QWidget *widget, bool fill);
+    virtual void end();
 };
 
-class UiTabViewContainer : public UiContainer {
-public:
-    QTabWidget *tabwidget;
-    
-    UiTabViewContainer(QTabWidget *tabwidget);
-    virtual void add(QWidget *widget, bool fill);
-};
+void ui_container_add(UiObject *obj, UiContainerPrivate *ct);
 
-class UiStackContainer : public UiContainer {
-public:
-    QStackedWidget *stack;
-    
-    UiStackContainer(QStackedWidget *stack);
-    virtual void add(QWidget *widget, bool fill);
-};
-
-class UiSidebarContainer : public UiContainer {
-public:
-    QSplitter *splitter;
-    
-    UiSidebarContainer(QSplitter *splitter);
-    virtual void add(QWidget *widget, bool fill);
-};
 
 #endif /* CONTAINER_H */
 
index d9a03c1a41000be5b526e8c503c129241819af64..f3a9de2de68f76833c83df33bfcef62dbe085112 100644 (file)
 #include "container.h"
 
 
-DrawingArea::DrawingArea(UiObject *obj, ui_drawfunc cb, void *data) {
-    object = obj;
-    drawCallback = cb;
-    userdata = data;
-}
-
-DrawingArea::~DrawingArea() {
-    
-}
-
-void DrawingArea::paintEvent(QPaintEvent *event) {
-    QPainter painter(this);
-    
-    UiQtGraphics g;
-    g.g.width = this->width();
-    g.g.height = this->height();
-    g.painter = &painter;
-    
-    UiEvent ev;
-    ev.obj = object;
-    ev.window = object->window;
-    ev.document = object->ctx->document;
-    ev.eventdata = NULL;
-    ev.intval = 0;
-    
-    drawCallback(&ev, &g.g, userdata);
-}
-
-
-
-UIWIDGET ui_drawingarea(UiObject *obj, ui_drawfunc f, void *userdata) {
-    DrawingArea *widget = new DrawingArea(obj, f, userdata);
-    
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->add(widget, true);
-    
-    return widget;
-}
-
-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) {
-    
-}
-
-
-/* -------------------- text layout functions -------------------- */
-
-UiTextLayout* ui_text(UiGraphics *g) {
-    UiTextLayout *textlayout = new UiTextLayout();
-    return textlayout;
-}
-
-void ui_text_free(UiTextLayout *text) {
-    delete text;
-}
-
-void ui_text_setstring(UiTextLayout *layout, char *str) {
-    layout->text.setText(QString::fromUtf8(str));
-}
-
-void ui_text_setstringl(UiTextLayout *layout, char *str, int len) {
-    layout->text.setText(QString::fromUtf8(str, len));
-}
-
-void ui_text_setfont(UiTextLayout *layout, char *font, int size) {
-    layout->font = QFont(QString::fromUtf8(font), size);
-}
-
-void ui_text_getsize(UiTextLayout *layout, int *width, int *height) {
-    QSizeF size = layout->text.size();
-    *width = (int)size.width();
-    *height = (int)size.height();
-}
-
-void ui_text_setwidth(UiTextLayout *layout, int width) {
-    layout->text.setTextWidth((qreal)width);
-}
-
-
-/* -------------------- drawing functions -------------------- */
-
-void ui_graphics_color(UiGraphics *g, int red, int green, int blue) {
-    UiQtGraphics *gr = (UiQtGraphics*)g;
-    gr->color = QColor(red, green, blue);
-    gr->painter->setPen(gr->color);
-}
-
-void ui_draw_line(UiGraphics *g, int x1, int y1, int x2, int y2) {
-    UiQtGraphics *gr = (UiQtGraphics*)g;
-    
-    gr->painter->drawLine(x1, y1, x2, y2);
-}
-
-void ui_draw_rect(UiGraphics *g, int x, int y, int w, int h, int fill) {
-    UiQtGraphics *gr = (UiQtGraphics*)g;
-    
-    QRect rect(x, y, w, h);
-    if(fill) {
-        gr->painter->fillRect(rect, gr->color);
-        
-    } else {
-        gr->painter->drawRect(rect);
-    }
-}
-
-void ui_draw_text(UiGraphics *g, int x, int y, UiTextLayout *text) {
-    UiQtGraphics *gr = (UiQtGraphics*)g;
-    
-    gr->painter->setFont(text->font);
-    gr->painter->drawStaticText(x, y, text->text);
-}
 
index b4c5f0b01b01bd415bef081513b4ca0f7ee015a2..62d4df241002e0430fa8f8fafb2280fd23487d01 100644 (file)
 #include <QColor>
 #include <QStaticText>
 
-typedef struct UiQtGraphics {
-    UiGraphics g;
-    QPainter   *painter;
-    QColor     color;
-} UiXlibGraphics;
-
-struct UiTextLayout {
-    QStaticText text;
-    QFont font;
-};
-
-
-class DrawingArea : public QWidget {
-    Q_OBJECT
-    
-    UiObject    *object;
-    ui_drawfunc drawCallback;
-    void        *userdata;
-    
-public:
-    DrawingArea(UiObject *obj, ui_drawfunc cb, void *data);
-    ~DrawingArea();
-    
-    virtual void paintEvent(QPaintEvent * event);
-};
 
 #endif /* GRAPHICS_H */
 
index 85bfc5702d19bfb6dac90a7ab7becbe58294dd1f..ef7a9fcd085290f4cc0a87f67749980521e0b770 100644 (file)
 #include "label.h"
 #include "container.h"
 #include "toolkit.h"
+#include "ui/display.h"
 
-UIWIDGET ui_label(UiObject *obj, char *label) {
-    QString str = QString::fromUtf8(label);
+
+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);
     QLabel *widget = new QLabel(str);
     
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->add(widget, false);
+    Qt::AlignmentFlag align = Qt::AlignCenter;
+    if(args.align == UI_ALIGN_LEFT) {
+        align = Qt::AlignLeft;
+    } else if(args.align == UI_ALIGN_RIGHT) {
+        align = Qt::AlignRight;
+    }
+    widget->setAlignment(align);
+    
+    ctn->add(widget, false);
     
     return widget;
 }
 
-UIWIDGET ui_space(UiObject *obj) {
-    // TODO: maybe there is a better widget for this purpose
-    QLabel *widget = new QLabel();
-    
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->add(widget, true);
-    
-    return widget;
+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;
+    return ui_label_create(obj, args);
 }
index 6482e01b0c3fe5ceade6328390147c0d2d648a0a..86bf75f18b2eb2c4231ea78e85e2b749a4277b3e 100644 (file)
 #include "menu.h"
 #include "toolkit.h"
 #include "../common/context.h"
+#include "../common/menu.h"
 #include "../ui/properties.h"
 #include "../ui/window.h"
 #include "stock.h"
 #include "container.h"
 
-static UcxList *menus;
-static UcxList *current;
 
-/* -------------------------- UiMenu -------------------------- */
+static ui_menu_add_f createMenuItem[] = {
+    /* UI_MENU                 */ add_menu_widget,
+    /* UI_MENU_ITEM            */ add_menuitem_widget,
+    /* UI_MENU_CHECK_ITEM      */ add_checkitem_widget,
+    /* UI_MENU_RADIO_ITEM      */ add_radioitem_widget,
+    /* UI_MENU_ITEM_LIST       */ add_menuitem_list_widget,
+    /* UI_MENU_CHECKITEM_LIST  */ add_menuitem_list_widget,
+    /* UI_MENU_RADIOITEM_LIST  */ add_menuitem_list_widget,
+    /* UI_MENU_SEPARATOR       */ add_menuseparator_widget
+};
 
-UiMenu::UiMenu(char* label) {
-    this->items = NULL;
-    this->label = label;
-}
-
-void UiMenu::addMenuItem(UiMenuItemI* item) {
-    items = ucx_list_append(items, item);
-}
-
-void UiMenu::addTo(UiObject *obj, QMenuBar *menubar, QMenu *menu) {
-    QMenu *m = NULL;
-    if(menubar) {
-        m = menubar->addMenu(label);
-    } else {
-        m = menu->addMenu(label);
+/*
+ * create all menu child items
+ */
+static void add_menu_items(QMenu *parent, int i, UiMenu *menu, UiObject *obj) {
+    UiMenuItemI *it = menu->items_begin;
+    int index = 0;
+    while(it) {
+        createMenuItem[it->type](parent, index, it, obj);
+        it = it->next;
+        index++;
+    }
+}
+
+void add_menu_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj) {
+    UiMenu *m = (UiMenu*)item;
+    QMenu *menu = parent->addMenu(m->label);
+    add_menu_items(menu, i, m, obj);
+}
+
+static UiAction* create_action(
+        UiObject *obj,
+        const char *icon,
+        const char *label,
+        ui_callback callback,
+        void *userdata,
+        int *states)
+{
+    QString str = QString::fromUtf8(label);
+    UiAction *action = new UiAction(obj, str, callback, userdata);
+    if(icon) {
+        action->setIcon(QIcon::fromTheme(icon));
+        action->setIconVisibleInMenu(true);
     }
     
-    UCX_FOREACH(elm, items) {
-        UiMenuItemI *item = (UiMenuItemI*)elm->data;
-        item->addTo(obj, NULL, m);
+    if(states) {
+        size_t nstates = uic_group_array_size(states);
+        uic_add_group_widget_i(obj->ctx, action, (ui_enablefunc)ui_action_enable, states, nstates);
+        action->setEnabled(false);
     }
+    
+    return action;
 }
 
-
-/* -------------------------- UiMenuItem -------------------------- */
-
-UiMenuItem::UiMenuItem(char* label, ui_callback f, void* userdata) {
-    this->label = label;
-    this->callback = f;
-    this->userdata = userdata;
-    this->groups = NULL;
-}
-
-void UiMenuItem::addGroup(int group) {
-    groups = ucx_list_append(groups, (void*)(intptr_t)group);
-}
-
-void UiMenuItem::setCheckable(bool c) {
-    checkable = c;
-}
-
-void UiMenuItem::addTo(UiObject *obj, QMenuBar *menubar, QMenu *menu) {
-    QString str = QString::fromUtf8(label);
-    UiAction *action = new UiAction(obj, str, callback, userdata);
-    action->setCheckable(checkable);
-    if(checkable) {
-        action->setChecked(false);
-    }
-    menu->addAction(action);
+void add_menuitem_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj) {
+    UiMenuItem *it = (UiMenuItem*)item;
+    UiAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->groups);
+    parent->addAction(action);
     QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger()));
 }
 
-
-/* -------------------------- UiStMenuItem -------------------------- */
-
-UiStMenuItem::UiStMenuItem(char* stockid, ui_callback f, void* userdata) {
-    this->stockid = stockid;
-    this->callback = f;
-    this->userdata = userdata;
-    this->groups = NULL;
-}
-
-void UiStMenuItem::addGroup(int group) {
-    groups = ucx_list_append(groups, (void*)(intptr_t)group);
+void add_menuseparator_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj) {
+    parent->addSeparator();
 }
 
-void UiStMenuItem::addTo(UiObject *obj, QMenuBar *menubar, QMenu *menu) {
-    UiStockItem *stockItem = ui_get_stock_item(stockid);
+void add_checkitem_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj) {
+    UiMenuCheckItem *it = (UiMenuCheckItem*)item;
     
-    QString str = QString::fromUtf8(stockItem->label);
-    UiAction *action = new UiAction(obj, str, callback, userdata);
-    action->setIcon(QIcon::fromTheme(stockItem->icon_name));
-    action->setIconVisibleInMenu(true);
-    menu->addAction(action);
-    //UiEventWrapper *ev = new UiEventWrapper(callback, userdata);
-    QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger()));
-}
-
-
-/* -------------------------- UiMenuSeparator -------------------------- */
-
-void UiMenuSeparator::addTo(UiObject* obj, QMenuBar* menubar, QMenu* menu) {
-    menu->addSeparator();
-}
-
-
-/* -------------------------- UiCheckItemNV -------------------------- */
-
-UiCheckItemNV::UiCheckItemNV(char* label, char* varname) {
-    this->label = label;
-    this->varname = varname;
-}
-
-void UiCheckItemNV::addTo(UiObject* obj, QMenuBar* menubar, QMenu* menu) {
-    QString str = QString::fromUtf8(label);
-    UiAction *action = new UiAction(obj, str, NULL, NULL);
+    UiAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->groups);
+    parent->addAction(action);
     action->setCheckable(true);
-    menu->addAction(action);
-    QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger()));
+    action->prepare_event = ui_checkableaction_prepare_event;
     
-    UiVar *var = uic_connect_var(obj->ctx, varname, UI_VAR_INTEGER);
+    UiVar* var = uic_widget_var(obj->ctx, obj->ctx, NULL, it->varname, UI_VAR_INTEGER);
     if(var) {
         UiInteger *value = (UiInteger*)var->value;
-        action->setChecked(value->value);
         value->obj = action;
-        value->get = ui_checkitem_get;
-        value->set = ui_checkitem_set;
-        value = 0;
-    } else {
-        // TODO: error
+        value->get = ui_checkableaction_get;
+        value->set = ui_checkableaction_set;
+        
+        action->setChecked((bool)value->value);
     }
+    action->var = var;
 }
 
-
-/* -------------------------- UiAction -------------------------- */
-
-UiAction::UiAction(UiObject *obj, QString &label, ui_callback f, void* userdata) : QAction(label, NULL) {
-    //QAction(label, NULL);
-    this->obj = obj;
-    this->callback = f;
-    this->userdata = userdata;
-}
-
-void UiAction::trigger() {
-    if(!callback) {
-        return;
-    }
+void add_radioitem_widget(QMenu *parent, int index, UiMenuItemI *item, UiObject *obj) {
+    UiMenuRadioItem *it = (UiMenuRadioItem*)item;
     
-    UiEvent e;
-    e.obj = obj;
-    e.window = obj->window;
-    e.document = obj->ctx->document;
-    e.eventdata = NULL;
+    UiAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->groups);
+    parent->addAction(action);
+    action->setCheckable(true);
+    action->prepare_event = ui_actiongroup_prepare_event;
     
-    if(isCheckable()) {
-        e.intval = isChecked();
+    UiVar* var = uic_widget_var(obj->ctx, obj->ctx, NULL, it->varname, UI_VAR_INTEGER);
+    if(var) {
+        UiInteger *value = (UiInteger*)var->value;
+        QActionGroup *group = (QActionGroup*)value->obj;
+        if(!group) {
+            group = new QActionGroup(parent);
+            value->obj = group;
+        }
+        group->addAction(action);
+        value->get = ui_actiongroup_get;
+        value->set = ui_actiongroup_set;
+        if(value->value != 0) {
+            ui_actiongroup_set(value, value->value);
+        }
+    }
+    action->var;
+}
+
+void ui_actiongroup_prepare_event(UiEvent *event, UiAction *action) {
+    if(action->var) {
+        UiInteger *value = (UiInteger*)action->var->value;
+        event->eventdata = value;
+        event->intval = value->get(value);
+    }
+}
+
+int64_t ui_actiongroup_get(UiInteger *value) {
+    QActionGroup *group = (QActionGroup*)value->obj;
+    auto actions = group->actions();
+    int i = 1;
+    foreach(const QAction *action, actions) {
+        if(action->isChecked()) {
+            value->value = i;
+            break;
+        }
+        i++;
+    }
+    return value->value;
+}
+
+void ui_actiongroup_set(UiInteger *value, int64_t i) {
+    QActionGroup *group = (QActionGroup*)value->obj;
+    auto actions = group->actions();
+    if(i > 0) {
+        if(i-1 < actions.size()) {
+            actions[i]->setEnabled(true);
+        }
+        value->value = i;
     } else {
-        e.intval = 0;
-    }
-    
-    callback(&e, userdata);
-}
-
-
-void ui_menu(char *label) {
-    // free current menu hierarchy
-    ucx_list_free(current);
-    
-    // create menu
-    UiMenu *menu = new UiMenu(label);
-    
-    current = ucx_list_prepend(NULL, menu);
-    menus = ucx_list_append(menus, menu);
-}
-
-void ui_submenu(char *label) {
-    UiMenu *menu = new UiMenu(label);
-    
-    // add submenu to current menu
-    UiMenu *cm = (UiMenu*)current->data;
-    cm->addMenuItem(menu);
-    
-    // set the submenu to current menu
-    current = ucx_list_prepend(current, menu);
-}
-
-void ui_submenu_end() {
-    if(ucx_list_size(current) < 2) {
-        return;
-    }
-    current = ucx_list_remove(current, current);
-    //UcxList *c = current;
-}
-
-
-void ui_menuitem(char *label, ui_callback f, void *userdata) {
-    ui_menuitem_gr(label, f, userdata, -1);
-}
-
-void ui_menuitem_st(char *stockid, ui_callback f, void *userdata) {
-    ui_menuitem_stgr(stockid, f, userdata, -1);
-}
-
-void ui_menuitem_gr(char *label, ui_callback f, void *userdata, ...) {
-    if(!current) {
-        return;
+        foreach(QAction *action, actions) {
+            action->setEnabled(false);
+        }
+        value->value = 0;
     }
-    
-    UiMenuItem *item = new UiMenuItem(label, f, userdata);
-    
-    // add groups
-    va_list ap;
-    va_start(ap, userdata);
-    int group;
-    while((group = va_arg(ap, int)) != -1) {
-        item->addGroup(group);
-    }
-    va_end(ap);
-    
-    UiMenu *cm = (UiMenu*)current->data;
-    cm->addMenuItem(item);
 }
 
-void ui_menuitem_stgr(char *stockid, ui_callback f, void *userdata, ...) {
-    if(!current) {
-        return;
-    }
-    
-    UiStMenuItem *item = new UiStMenuItem(stockid, f, userdata);
-    
-    // add groups
-    va_list ap;
-    va_start(ap, userdata);
-    int group;
-    while((group = va_arg(ap, int)) != -1) {
-        item->addGroup(group);
-    }
-    va_end(ap);
-    
-    UiMenu *cm = (UiMenu*)current->data;
-    cm->addMenuItem(item);
-}
-
-void ui_menuseparator() {
-    if(!current) {
-        return;
-    }
+void add_menuitem_list_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj) {
     
-    UiMenuSeparator *item = new UiMenuSeparator();
-    UiMenu *cm = (UiMenu*)current->data;
-    cm->addMenuItem(item);
 }
 
-void ui_checkitem(char *label, ui_callback f, void *userdata) {
-    if(!current) {
-        return;
-    }
-    
-    UiMenuItem *item = new UiMenuItem(label, f, userdata);
-    item->setCheckable(true);
-    
-    UiMenu *cm = (UiMenu*)current->data;
-    cm->addMenuItem(item);
-}
 
-void ui_checkitem_nv(char *label, char *vname) {
-    if(!current) {
+void ui_add_menus(UiObject *obj, QMainWindow *window) {
+    UiMenu *menus_begin = uic_get_menu_list();
+    if(menus_begin == NULL) {
         return;
     }
     
-    UiCheckItemNV *item = new UiCheckItemNV(label, vname);
-    
-    UiMenu *cm = (UiMenu*)current->data;
-    cm->addMenuItem(item);
-}
-
-void ui_menuitem_list(UiList *items, ui_callback f, void *userdata) {
-    
-}
-
-void ui_add_menus(UiObject *obj, QMainWindow *window) {
     QMenuBar *mb = window->menuBar();
     
-    UCX_FOREACH(elm, menus) {
-        UiMenu *menu = (UiMenu*)elm->data;
-        menu->addTo(obj, mb, NULL);        
+    UiMenu *ls = menus_begin;
+    while(ls) {
+        if(ls->item.type == UI_MENU) {
+            QMenu *menu = mb->addMenu(ls->label);
+            add_menu_items(menu, 0, ls, obj);
+        }        
+        ls = (UiMenu*)ls->item.next;
     }
 }
 
-int ui_checkitem_get(UiInteger *i) {
-    QAction *action = (QAction*)i->obj;
-    i->value = action->isChecked();
-    return i->value;
-}
-
-void ui_checkitem_set(UiInteger *i, int value) {
-    QAction *action = (QAction*)i->obj;
-    i->value = value;
-    action->setChecked(value);
-}
-
-
-/*
- * widget menu functions
- */
-
-UiContextMenuHandler::UiContextMenuHandler(QWidget *widget, QMenu* menu) {
-    this->widget = widget;
-    this->menu = menu;
-}
-
-void UiContextMenuHandler::contextMenuEvent(const QPoint & pos) {
-    menu->popup(widget->mapToGlobal(pos));
-}
-UIMENU ui_contextmenu(UiObject *obj) {
-    UiContainer *ct = uic_get_current_container(obj);
-    return ui_contextmenu_w(obj, ct->current);
-}
-
-UIMENU ui_contextmenu_w(UiObject *obj, UIWIDGET widget) {
-    UiContainer *ct = uic_get_current_container(obj);
-    
-    QMenu *menu = new QMenu(widget);
-    widget->setContextMenuPolicy(Qt::CustomContextMenu);
-    
-    UiContextMenuHandler *handler = new UiContextMenuHandler(widget, menu);
-    QObject::connect(
-            widget,
-            SIGNAL(customContextMenuRequested(QPoint)),
-            handler,
-            SLOT(contextMenuEvent(QPoint)));
-    
-    ct->menu = menu;
-    
-    return menu;
-}
-
-void ui_contextmenu_popup(UIMENU menu) {
-    
-}
-
-void ui_widget_menuitem(UiObject *obj, char *label, ui_callback f, void *userdata) {
-    ui_widget_menuitem_gr(obj, label, f, userdata, -1);
-}
-
-void ui_widget_menuitem_gr(UiObject *obj, char *label, ui_callback f, void *userdata, ...) {
-    UiContainer *ct = uic_get_current_container(obj);
-    if(!ct->menu) {
-        return;
+void ui_checkableaction_prepare_event(UiEvent *event, UiAction *action) {
+    if(action->var) {
+        event->eventdata = action->var->value;
     }
-    
-    // add groups
-    UcxList *groups = NULL;
-    va_list ap;
-    va_start(ap, userdata);
-    int group;
-    while((group = va_arg(ap, int)) != -1) {
-        ucx_list_append(groups, (void*)(intptr_t)group);
-    }
-    va_end(ap);
-    
-    // create menuitem
-    QString str = QString::fromUtf8(label);
-    UiAction *action = new UiAction(obj, str, f, userdata);
-    ct->menu->addAction(action);
-    QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger()));
+    event->intval = action->isChecked();
 }
 
-void ui_widget_menuitem_st(UiObject *obj, char *stockid, ui_callback f, void *userdata) {
-    ui_widget_menuitem_stgr(obj, stockid, f, userdata, -1);
+int64_t ui_checkableaction_get(UiInteger *value) {
+    UiAction *action= (UiAction*)value->obj;
+    value->value = action->isChecked();
+    return value->value;
 }
 
-void ui_widget_menuitem_stgr(UiObject *obj, char *stockid, ui_callback f, void *userdata, ...) {
-    UiContainer *ct = uic_get_current_container(obj);
-    if(!ct->menu) {
-        return;
-    }
-    
-    // add groups
-    UcxList *groups = NULL;
-    va_list ap;
-    va_start(ap, userdata);
-    int group;
-    while((group = va_arg(ap, int)) != -1) {
-        ucx_list_append(groups, (void*)(intptr_t)group);
+void ui_checkableaction_set(UiInteger *value, int64_t i) {
+    UiAction *action = (UiAction*)value->obj;
+    value->value = i;
+    if(i != 0) {
+        action->setChecked((bool)i);
     }
-    va_end(ap);
-    
-    // create menuitem
-    UiStockItem *stockItem = ui_get_stock_item(stockid);
-    
-    QString str = QString::fromUtf8(stockItem->label);
-    UiAction *action = new UiAction(obj, str, f, userdata);
-    action->setIcon(QIcon::fromTheme(stockItem->icon_name));
-    action->setIconVisibleInMenu(true);
-    ct->menu->addAction(action);
-    QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger()));
 }
+
index 7bffb0804449f0812f30b1ebb3b6269f4a30c922..9903ae07396149c37c388c91eae8f48826ef3bb0 100644 (file)
 #define        MENU_H
 
 #include "../ui/menu.h"
-#include <ucx/list.h>
+#include "../common/menu.h"
+
+#include "toolkit.h"
 
 #include <QMainWindow>
 #include <QMenu>
 #include <QMenuBar>
 #include <QContextMenuEvent>
 
-class UiMenuItemI {
-public:
-    virtual void addTo(UiObject *obj, QMenuBar *menubar, QMenu *menu) = 0;
-};
-
-class UiMenu : public UiMenuItemI {
-public:
-    
-    UcxList *items;
-    char *label;
-    
-    UiMenu(char *label);
-    
-    void addMenuItem(UiMenuItemI *item);
-    
-    virtual void addTo(UiObject *obj, QMenuBar *menubar, QMenu *menu);
-};
-
-class UiMenuItem : public UiMenuItemI {
-    char *label;
-    ui_callback callback;
-    void *userdata;
-    UcxList *groups;
-    bool checkable = false;
-    
-public:
-    UiMenuItem(char *label, ui_callback f, void *userdata);
-    void addGroup(int group);
-    void setCheckable(bool c);
-    
-    virtual void addTo(UiObject *obj, QMenuBar *menubar, QMenu *menu);
-};
-
-class UiStMenuItem : public UiMenuItemI {
-    char *stockid;
-    ui_callback callback;
-    void *userdata;
-    UcxList *groups;
-    
-public:
-    UiStMenuItem(char *stockid, ui_callback f, void *userdata);
-    void addGroup(int group);
-    
-    virtual void addTo(UiObject *obj, QMenuBar *menubar, QMenu *menu);
-};
-
-class UiMenuSeparator : public UiMenuItemI {
-public:
-    virtual void addTo(UiObject *obj, QMenuBar *menubar, QMenu *menu);
-};
-
-class UiCheckItemNV : public UiMenuItemI {
-    char *label;
-    char *varname;
-    
-public:
-    UiCheckItemNV(char *label, char *varname);
-    virtual void addTo(UiObject *obj, QMenuBar *menubar, QMenu *menu);
-};
-
-
-class UiAction : public QAction {
-    Q_OBJECT
-    
-    UiObject *obj;
-    ui_callback callback;
-    void *userdata;
-    
-public:
-    UiAction(UiObject *obj, QString &label, ui_callback f, void *userdata);
+void ui_add_menus(UiObject *obj, QMainWindow *window);
 
-private slots:
-    void trigger();
-};
+typedef void(*ui_menu_add_f)(QMenu*, int, UiMenuItemI*, UiObject*);
 
-void ui_add_menus(UiObject *obj, QMainWindow *window);
+void add_menu_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj);
+void add_menuitem_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj);
+void add_menuseparator_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj);
+void add_checkitem_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj);
+void add_radioitem_widget(QMenu *parent, int index, UiMenuItemI *item, UiObject *obj);
+void add_checkitemnv_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj);
+void add_menuitem_list_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj);
 
-extern "C" int ui_checkitem_get(UiInteger *i);
-extern "C" void ui_checkitem_set(UiInteger *i, int value);
+void ui_checkableaction_prepare_event(UiEvent *event, UiAction *action);
+int64_t ui_checkableaction_get(UiInteger *value);
+void ui_checkableaction_set(UiInteger *value, int64_t i);
 
-class UiContextMenuHandler : public QObject {
-    Q_OBJECT
-    
-    QWidget *widget;
-    QMenu *menu;
-    
-public:
-    UiContextMenuHandler(QWidget *widget, QMenu *menu);
-    
-public slots:
-    void contextMenuEvent(const QPoint & pos);
-};
+void ui_actiongroup_prepare_event(UiEvent *event, UiAction *action);
+int64_t ui_actiongroup_get(UiInteger *value);
+void ui_actiongroup_set(UiInteger *value, int64_t i);
 
 #endif /* MENU_H */
 
index 7cdf63e41ac4821ba6d8fa4509d2e7f853a8eb18..d6ead680948420d752471852ee67d88766c39c1e 100644 (file)
 
 #include "model.h"
 
-UiListSelection* listSelection(QItemSelectionModel *s) {
-    UiListSelection *selection = new UiListSelection();
-    
-    QModelIndexList list = s->selectedRows();
-    selection->count = list.count();
-    if(selection->count > 0) {
-        selection->rows = new int[selection->count];
-    }
-    
-    QModelIndex index;
-    int i=0;
-    foreach(index, list) {
-        selection->rows[i] = index.row();
-        i++;
-    }
-    return selection;
-}
-
-ListModel::ListModel(UiObject* obj, QListView* view, UiListPtr* list, ui_model_getvalue_f getvalue, ui_callback f, void* userdata) {
-    this->obj = obj;
-    this->view = view;
-    this->list = list;
-    this->getvalue = getvalue;
-    this->callback = f;
-    this->userdata = userdata;
-}
-
-int ListModel::rowCount(const QModelIndex& parent) const {
-    return list->list->count(list->list);
-}
-
-QVariant ListModel::data(const QModelIndex &index, int role) const {
-    if(role == Qt::DisplayRole) {
-        UiList *ls = list->list;
-        void *rowData = ls->get(ls, index.row());
-        if(rowData && getvalue) {
-            void *value = getvalue(rowData, 0);
-            return QString::fromUtf8((char*)value); 
-        }
-    }
-    return QVariant();
-}
-
-void ListModel::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) {
-    UiListSelection *selection = listSelection(view->selectionModel());
-    
-    UiEvent e;
-    e.obj = obj;
-    e.window = obj->window;
-    e.document = obj->ctx->document;
-    e.eventdata = selection;
-    e.intval = selection->count > 0 ? selection->rows[0] : -1;
-    callback(&e, userdata);
-    
-    if(selection->count > 0) {
-        delete selection->rows;
-    }
-    delete selection;
-}
-
-TableModel::TableModel(UiObject *obj, QTreeView *view, UiListPtr *list, UiModelInfo *info) {
-    this->obj = obj;
-    this->list = list;
-    this->info = info;
-    this->view = view;
-}
-
-int TableModel::rowCount(const QModelIndex &parent) const {
-    return list->list->count(list->list);
-}
-
-int TableModel::columnCount(const QModelIndex &parent) const {
-    return info->columns;
-}
-
-QVariant TableModel::data(const QModelIndex &index, int role) const {
-    if(role == Qt::DisplayRole) {
-        UiList *ls = list->list;
-        void *rowData = ls->get(ls, index.row());
-        if(rowData && info->getvalue) {
-            void *value = info->getvalue(rowData, index.column());
-            switch(info->types[index.column()]) {
-                case UI_STRING: {
-                    return QString::fromUtf8((char*)value); 
-                }
-                case UI_INTEGER: {
-                    int *intptr = (int*)value;
-                    return QVariant(*intptr);
-                }
-            }
-        }
-    }
-    return QVariant();
-}
-
-QVariant TableModel::headerData(int section, Qt::Orientation orientation, int role) const {
-    if(role == Qt::DisplayRole) {
-        char *label = info->titles[section];
-        return QString::fromUtf8(label);
-    }
-    return QVariant();
-}
-
-void TableModel::update() {
-    emit dataChanged(QModelIndex(),QModelIndex());
-}
-
-void TableModel::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) {
-    UiListSelection *selection = listSelection(view->selectionModel());
-    
-    UiEvent e;
-    e.obj = obj;
-    e.window = obj->window;
-    e.document = obj->ctx->document;
-    e.eventdata = selection;
-    e.intval = selection->count > 0 ? selection->rows[0] : -1;
-    info->selection(&e, info->userdata);
-    
-    if(selection->count > 0) {
-        delete selection->rows;
-    }
-    delete selection;
-}
-
-void TableModel::activate(const QModelIndex &) {
-    UiListSelection *selection = listSelection(view->selectionModel());
-    
-    UiEvent e;
-    e.obj = obj;
-    e.window = obj->window;
-    e.document = obj->ctx->document;
-    e.eventdata = selection;
-    e.intval = selection->count > 0 ? selection->rows[0] : -1;
-    info->activate(&e, info->userdata);
-    
-    if(selection->count > 0) {
-        delete selection->rows;
-    }
-    delete selection;
-}
index b74b186e4e33fdf7a36b44135a4484e68ee08b43..d9a707d6932daeac5029688ca211f9c7e1c4853d 100644 (file)
 #include <QAbstractItemModel>
 #include <QItemSelectionModel>
 
-class ListModel : public QAbstractListModel {
-    Q_OBJECT
-    
-    UiObject    *obj;
-    UiListPtr   *list;
-    ui_model_getvalue_f getvalue;
-    ui_callback callback;
-    void        *userdata;
-    QListView   *view;
-    
-public:
-    ListModel(UiObject *obj, QListView *view, UiListPtr *list, ui_model_getvalue_f getvalue, ui_callback f, void *userdata);
-    
-    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 QAbstractTableModel {
-    Q_OBJECT
-    
-    UiObject    *obj;
-    UiListPtr   *list;
-    UiModelInfo *info;
-    QTreeView   *view;
-public:
-    TableModel(UiObject *obj, QTreeView *view, UiListPtr *list, UiModelInfo *info);
-    
-    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;
-    
-    void update();
-    
-public slots:
-    void selectionChanged(
-        const QItemSelection & selected,
-        const QItemSelection & deselected);
-    void activate(const QModelIndex &);
-};
-
-UiListSelection* listSelection(QItemSelectionModel *s);
 
 #endif /* MODEL_H */
 
diff --git a/ui/qt/qt5.pro b/ui/qt/qt5.pro
new file mode 100644 (file)
index 0000000..60cf702
--- /dev/null
@@ -0,0 +1,65 @@
+#
+# 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.
+#
+
+TARGET = uitk
+TEMPLATE = lib
+CONFIG += staticlib warn_off debug
+DESTDIR = ../build/lib
+MOC_DIR = ../build/ui/qt
+OBJECTS_DIR = ../build/ui/qt
+
+QT += core gui widgets
+
+DEFINES += UI_QT5
+
+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
+
index 43a3ea9e75991cc9dc27b56f06d39f396ae58108..1ead20bac6d7ef62584d104e8534f4e186f52b29 100644 (file)
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <ucx/map.h>
 
 #include "stock.h"
 #include "../ui/properties.h"
 
-static UcxMap *stock_items;
 
-void ui_stock_init() {
-    stock_items = ucx_map_new(64);
-    
-    ui_add_stock_item(UI_STOCK_NEW, "New", "document-new");
-    ui_add_stock_item(UI_STOCK_OPEN, "Open", "document-open");
-    ui_add_stock_item(UI_STOCK_SAVE, "Save", "document-save");
-    ui_add_stock_item(UI_STOCK_SAVE_AS, "Save as ...", "document-save-as");
-    ui_add_stock_item(UI_STOCK_REVERT_TO_SAVED, "Revert to saved", "document-revert");
-    ui_add_stock_item(UI_STOCK_CLOSE, "Close", "window-close");
-    ui_add_stock_item(UI_STOCK_UNDO, "Undo", "edit-undo");
-    ui_add_stock_item(UI_STOCK_REDO, "Redo", "edit-redo");
-    ui_add_stock_item(UI_STOCK_GO_BACK, "Back", "go-previous");
-    ui_add_stock_item(UI_STOCK_GO_FORWARD, "Forward", "go-next");
-    ui_add_stock_item(UI_STOCK_CUT, "Cut", "edit-cut");
-    ui_add_stock_item(UI_STOCK_COPY, "Copy", "edit-copy");
-    ui_add_stock_item(UI_STOCK_PASTE, "Paste", "edit-paste");
-    ui_add_stock_item(UI_STOCK_DELETE, "Delete", "edit-delete");
-}
-
-void ui_add_stock_item(char *id, char *label, char *icon) {
-    UiStockItem *item = new UiStockItem(label, icon);
-    ucx_map_cstr_put(stock_items, id, item);
-}
-
-UiStockItem* ui_get_stock_item(char *id) {
-    UiStockItem *item = (UiStockItem*)ucx_map_cstr_get(stock_items, id);
-    if(item) {
-        char *label = uistr_n(id);
-        if(label) {
-            item->label = label;
-        }
-    }
-    return item;
-}
-
-
-UiStockItem::UiStockItem(char* label, char* icon_name) {
-    this->label = label;
-    this->icon_name = icon_name;
-}
 
 
index f183f6e5383d3ac8260d2f1ea98c6b02e47d7e3e..f80f1a463afeae7f99a9aaee92e3d24a3ab19b66 100644 (file)
 
 #include "../ui/stock.h"
 
-class UiStockItem {
-public:
-        
-    char *label;
-    char *icon_name;
-    
-    UiStockItem(char *label, char *icon_name);
-};
 
 
-void ui_stock_init();
-void ui_add_stock_item(char *id, char *label, char *icon);
-UiStockItem* ui_get_stock_item(char *id);
-
 #endif /* STOCK_H */
 
index 3d7027ee391713c4ff0c37cc76336339dc66501d..f900ac0bbd0e2f105d2a42d637bfb9497e9bb891 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2014 Olaf Wintermann. All rights reserved.
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
 #include "../common/context.h"
 #include "../common/document.h"
 
-UIWIDGET ui_textarea(UiObject *obj, UiText *value) {
-    QTextDocument *txtdoc = value && value->obj ? (QTextDocument*)value->obj : new QTextDocument();
-    
-    if(value) {
-        if(value->value && value->obj) {
-            QString str = QString::fromUtf8(value->value);
-            txtdoc->setPlainText(str);
+/*
+ * Gets or creates a QTextDocument for the UiText value and initializes it
+ * with the UiText string value
+ */
+static QTextDocument* get_or_create_doc(UiText *value) {
+    QTextDocument *document = nullptr;
+    if(value->data1) {
+        document = (QTextDocument*)value->data1;
+    } else {
+        document = new QTextDocument();
+        if(value->value.ptr) {
+            QString str = QString::fromUtf8(value->value.ptr);
+            document->setPlainText(str);
         }
+    }
+    
+    if(value->value.free) {
+        value->value.free(value->value.ptr);
+    }
+    value->value.ptr = NULL;
+    value->value.free = NULL;
+    
+    return document;
+}
+
+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);
+    
+    QTextDocument *document = nullptr;
+    
+    UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_STRING);
+    if(var) {
+        UiText *value = (UiText*)var->value;
+        
+        document = get_or_create_doc(value);
         
+        value->save = ui_textarea_save;
+        value->restore = ui_textarea_restore;
+        value->destroy = ui_textarea_text_destroy;
         value->get = ui_textarea_get;
         value->set = ui_textarea_set;
         value->getsubstr = ui_textarea_getsubstr;
         value->insert = ui_textarea_insert;
         value->setposition = ui_textarea_setposition;
         value->position = ui_textarea_position;
+        value->setselection = ui_textarea_setselection;
         value->selection = ui_textarea_selection;
         value->length = ui_textarea_length;
         value->remove = ui_textarea_remove;
-        value->obj = txtdoc;
-        value->value = NULL;
+        value->obj = textarea;
+        value->data1 = document;
+    } else {
+        document = new QTextDocument();
     }
     
-    UiContainer *ct = uic_get_current_container(obj); 
-    QTextEdit *textedit = new QTextEdit();
-    textedit->setDocument(txtdoc);
-    ct->add(textedit, true);
+    textarea->setDocument(document);
     
-    return textedit;
+    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 = (UiText*)var->value;
-        return ui_textarea(obj, value);
-    } else {
-        // TODO: error
-    }
-    return NULL;
+void ui_textarea_save(UiText *text) {
+    // NOOP
+}
+
+void ui_textarea_restore(UiText *text) {
+    QTextEdit *textarea = (QTextEdit*)text->obj;
+    QTextDocument *document = get_or_create_doc(text);
+    textarea->setDocument(document);
 }
 
+void ui_textarea_text_destroy(UiText *text) {
+    QTextDocument *document = (QTextDocument*)text->data1;
+    if(document) {
+        delete document;
+    }
+}
 
 char* ui_textarea_get(UiText *text) {
-    if(text->value) {
-        free(text->value);
+    // clean previous value
+    if(text->value.free) {
+        text->value.free(text->value.ptr);
     }
     
-    QTextDocument *doc = (QTextDocument*)text->obj;
+    // get string
+    QTextDocument *doc = (QTextDocument*)text->data1;
     QString str = doc->toPlainText();
-    QByteArray array = str.toLocal8Bit();
+    QByteArray array = str.toUtf8();
     const char *cstr = array.constData();
     
-    if(text->value) {
-        free(text->value);
-    }
-    text->value = strdup(cstr);
-    return text->value;
+    // store a copy of the string in the UiText value
+    text->value.ptr = strdup(cstr);
+    text->value.free = free;
+    return text->value.ptr;
 }
 
-void ui_textarea_set(UiText *text, char *str) {
-    // set text
-    QTextDocument *doc = (QTextDocument*)text->obj;
+void ui_textarea_set(UiText *text, const char *str) {
+    if(text->value.free) {
+        text->value.free(text->value.ptr);
+    }
+    text->value.ptr = NULL;
+    text->value.free = NULL;
+    
+    QTextDocument *doc = (QTextDocument*)text->data1;
     QString qstr = QString::fromUtf8(str);
     doc->setPlainText(qstr);
-    // cleanup
-    if(text->value) {
-        free(text->value);
-    }
-    text->value = NULL;
 }
 
 char* ui_textarea_getsubstr(UiText *text, int begin, int end) {
-    QTextDocument *doc = (QTextDocument*)text->obj;
-    return NULL; // TODO
+    QTextDocument *doc = (QTextDocument*)text->data1;
+    QTextCursor cursor(doc);
+    cursor.setPosition(begin, QTextCursor::MoveAnchor);
+    cursor.setPosition(end, QTextCursor::KeepAnchor);
+    QString str = cursor.selectedText();
+    QByteArray bytes = str.toUtf8();
+    const char *cstr = bytes.constData();
+    return cstr ? strdup(cstr) : NULL;
 }
 
 void ui_textarea_insert(UiText *text, int pos, char *str) {
-    QTextDocument *doc = (QTextDocument*)text->obj;
+    QTextDocument *doc = (QTextDocument*)text->data1;
+    QTextCursor cursor(doc);
+    cursor.setPosition(pos);
+    cursor.insertText(str);
 }
 
 void ui_textarea_setposition(UiText *text, int pos) {
-    // TODO
+    QTextEdit *textview = (QTextEdit*)text->obj;
+    QTextCursor cursor = textview->textCursor();
+    cursor.setPosition(pos);
+    textview->setTextCursor(cursor); 
 }
 
 int ui_textarea_position(UiText *text) {
-    QTextDocument *doc = (QTextDocument*)text->obj;
-    return 0; // TODO
+    QTextEdit *textview = (QTextEdit*)text->obj;
+    QTextCursor cursor = textview->textCursor();
+    return cursor.position();
 }
 
 void ui_textarea_selection(UiText *text, int *begin, int *end) {
-    QTextDocument *doc = (QTextDocument*)text->obj;
+    QTextEdit *textview = (QTextEdit*)text->obj;
+    QTextCursor cursor = textview->textCursor();
+    if(cursor.hasSelection()) {
+        if(begin) {
+            *begin = cursor.selectionStart();
+        }
+        if(end) {
+            *end = cursor.selectionEnd();
+        }
+    }
+}
+
+void ui_textarea_setselection(UiText *text, int begin, int end) {
+    QTextEdit *textview = (QTextEdit*)text->obj;
+    QTextCursor cursor = textview->textCursor();
+    cursor.setPosition(begin, QTextCursor::MoveAnchor);
+    cursor.setPosition(end, QTextCursor::KeepAnchor);
+    textview->setTextCursor(cursor); 
 }
 
 int ui_textarea_length(UiText *text) {
-    QTextDocument *doc = (QTextDocument*)text->obj;
-    return 0; // TODO
+    QTextDocument *doc = (QTextDocument*)text->data1;
+    return doc->characterCount();
 }
 
 void ui_textarea_remove(UiText *text, int begin, int end) {
-    QTextDocument *doc = (QTextDocument*)text->obj;
+    // TODO
 }
 
+/* ------------------------------ TextField ------------------------------ */
 
-/* ------------------- TextField ------------------- */
-
-UIWIDGET ui_textfield(UiObject *obj, UiString *value) {
+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);
     
-    UiContainer *ct = uic_get_current_container(obj);
-    ct->add(textfield, false);
+    if(password) {
+        textfield->setEchoMode(QLineEdit::Password);
+    }
     
-    if(value) {
-        if(value->value) {
-            QString str = QString::fromUtf8(value->value);
+    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) {
+            QString str = QString::fromUtf8(value->value.ptr);
             textfield->setText(str);
-            free(value->value);
-            value->value = NULL;
+            if(value->value.free) {
+                value->value.free(value->value.ptr);
+            }
+            value->value.ptr = NULL;
         }
+        
         value->set = ui_textfield_set;
         value->get = ui_textfield_get;
         value->obj = textfield;
@@ -158,38 +237,40 @@ UIWIDGET ui_textfield(UiObject *obj, UiString *value) {
     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 = (UiString*)var->value;
-        return ui_textfield(obj, value);
-    } else {
-        // TODO: error
-    }
-    return NULL;
+UIWIDGET ui_textfield_create(UiObject *obj, UiTextFieldArgs args) {
+    return create_textfield(obj, args, false, false);
+}
+
+UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs args) {
+    return create_textfield(obj, args, false, true);
+}
+
+UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs args) {
+    return create_textfield(obj, args, true, false);
 }
 
 char* ui_textfield_get(UiString *str) {
     QLineEdit *textfield = (QLineEdit*)str->obj;
     QString qstr = textfield->text();
     
-    if(str->value) {
-        free(str->value);
+    if(str->value.free) {
+        str->value.free(str->value.ptr);
     }
-    QByteArray array = qstr.toLocal8Bit();
+    QByteArray array = qstr.toUtf8();
     const char *cstr = array.constData();
-    str->value = strdup(cstr);
+    str->value.ptr = strdup(cstr);
+    str->value.free = free;
     
-    return str->value;
+    return str->value.ptr;
 }
 
-void ui_textfield_set(UiString *str, char *value) {
+void ui_textfield_set(UiString *str, const char *value) {
     QLineEdit *textfield = (QLineEdit*)str->obj;
     QString qstr = QString::fromUtf8(value);
     textfield->setText(qstr);
     
-    if(str->value) {
-        free(str->value);
+    if(str->value.free) {
+        str->value.free(str->value.ptr);
     }
-    str->value = NULL;
+    str->value.ptr = NULL;
 }
index 3ca8fd243df6c5e767a6d59a60a67f046f06d294..fcfe6129ef58ddf8f810ddc353f6c3dcd4f24a96 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
  *
- * Copyright 2014 Olaf Wintermann. All rights reserved.
+ * Copyright 2025 Olaf Wintermann. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions are met:
 
 // value implementations
 extern "C" {    
-    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);
-    void ui_textarea_setposition(UiText *text, int pos);
-    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);
     
-    char* ui_textfield_get(UiString *str);
-    void ui_textfield_set(UiString *str, char *value);
+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);
+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 *str) ;
+void ui_textfield_set(UiString *str, const char *value);
+
 }
 
 
index c810e8cb7d7bb18b476c331461ce15957a82a7bf..11285856d525bc8536698a5ec7221d20c1f0e656 100644 (file)
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <ucx/map.h>
 #include <inttypes.h>
 
 #include "toolbar.h"
 #include "menu.h"
 #include "stock.h"
 
-static UcxMap *toolbar_items = ucx_map_new(16);
-static UcxList *defaults;
-
-/* ------------------------- UiToolItem ------------------------- */
-
-UiToolItem::UiToolItem(char *label, ui_callback f, void *userdata) {
-    this->label = label;
-    this->image = NULL;
-    this->callback = f;
-    this->userdata = userdata;
-    this->isimportant = false;
-    this->groups = NULL;
-}
-
-void UiToolItem::addGroup(int group) {
-    groups = ucx_list_append(groups, (void*)(intptr_t)group);
-}
-
-void UiToolItem::addTo(UiObject *obj, QToolBar *toolbar) {
-    QString str = QString::fromUtf8(label);
-    UiAction *action = new UiAction(obj, str, callback, userdata);
-    action->setIcon(QIcon::fromTheme(image));
-    toolbar->addAction(action);
-    QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger()));
-}
-
-
-/* ------------------------- UiStockToolItem ------------------------- */
-
-UiStockToolItem::UiStockToolItem(char *stockid, ui_callback f, void *userdata) {
-    this->stockid = stockid;
-    this->callback = f;
-    this->userdata = userdata;
-    this->isimportant = false;
-    this->groups = NULL;
-}
-
-void UiStockToolItem::addGroup(int group) {
-    groups = ucx_list_append(groups, (void*)(intptr_t)group);
-}
-
-void UiStockToolItem::addTo(UiObject *obj, QToolBar *toolbar) {
-    UiStockItem *stockItem = ui_get_stock_item(stockid);
-    QString str = QString::fromUtf8(stockItem->label);
-    
-    UiAction *action = new UiAction(obj, str, callback, userdata);
-    action->setIcon(QIcon::fromTheme(stockItem->icon_name));
-    toolbar->addAction(action);
-    QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger()));
-}
-
-
-
-void ui_toolitem_vstgr(
-        char *name,
-        char *stockid,
-        int isimportant,
-        ui_callback f,
-        void *userdata,
-        va_list ap)
-{
-    UiStockToolItem *item = new UiStockToolItem(stockid, f, userdata);
-    item->isimportant = isimportant;
-    
-    // add groups
-    int group;
-    while((group = va_arg(ap, int)) != -1) {
-        item->addGroup(group);
-    }
-    
-    ucx_map_cstr_put(toolbar_items, name, item);
-}
-
-void ui_toolitem_img(char *name, char *label, char *img, ui_callback f, void *udata) {
-    UiToolItem *item = new UiToolItem(label, f, udata);
-    item->image = img;
-    item->isimportant = false;
-    
-    ucx_map_cstr_put(toolbar_items, name, item);
-}
-
-void ui_toolitem(char *name, char *label, ui_callback f, void *udata) {
-    ui_toolitem_img(name, label, NULL, f, udata);
-}
-
-void ui_toolitem_st(char *name, char *stockid, ui_callback f, void *userdata) {
-    ui_toolitem_stgr(name, stockid, f, userdata, -1);
-}
-
-void ui_toolitem_sti(char *name, char *stockid, ui_callback f, void *userdata) {
-    ui_toolitem_stgri(name, stockid, f, userdata, -1);
-}
-
-void ui_toolitem_stgr(char *name, char *stockid, ui_callback f, void *userdata, ...) {
-    va_list ap;
-    va_start(ap, userdata);
-    ui_toolitem_vstgr(name, stockid, 0, f, userdata, ap);
-    va_end(ap);
-}
-
-void ui_toolitem_stgri(char *name, char *stockid, ui_callback f, void *userdata, ...) {
-    va_list ap;
-    va_start(ap, userdata);
-    ui_toolitem_vstgr(name, stockid, 1, f, userdata, ap);
-    va_end(ap);
-}
-
-
-void ui_toolbar_add_default(char *name) {
-    char *s = strdup(name);
-    defaults = ucx_list_append(defaults, s);
-}
-
-
-QToolBar* ui_create_toolbar(UiObject *obj) {
-    QToolBar *toolbar = new QToolBar();
-    
-    UCX_FOREACH(elm, defaults) {
-        UiToolItemI *item = (UiToolItemI*)ucx_map_cstr_get(toolbar_items, (char*)elm->data);
-        if(item) {
-            item->addTo(obj, toolbar);
-        } else if(!strcmp((char*)elm->data, "@separator")) {
-            
-        } else {
-            fprintf(stderr, "UI Error: Unknown toolbar item: %s\n", elm->data);
-        }
-    }
-    
-    return toolbar;
-}
index 77f059e99d92dac0bc2347ecc0f0fbddedd2ec1f..7a4dc2a14c86ed44175de93e3ca27aa5deb68cf4 100644 (file)
 
 #include "toolkit.h"
 #include "../ui/toolbar.h"
-#include <ucx/list.h>
 #include <QToolBar>
 
-class UiToolItemI {
-public:
-    virtual void addTo(UiObject *obj, QToolBar *toolbar) = 0;
-};
 
-class UiToolItem : public UiToolItemI {
-public:
-    char *label;
-    char *image;
-    ui_callback callback;
-    void *userdata;
-    UcxList *groups;
-    bool isimportant;
-    
-    UiToolItem(char *label, ui_callback f, void *userdata);
-    void addGroup(int group);
-    virtual void addTo(UiObject *obj, QToolBar *toolbar);
-};
-
-class UiStockToolItem : public UiToolItemI {
-public:
-    char *stockid;
-    ui_callback callback;
-    void *userdata;
-    UcxList *groups;
-    bool isimportant;
-    
-    UiStockToolItem(char *stockid, ui_callback f, void *userdata);
-    void addGroup(int group);
-    virtual void addTo(UiObject *obj, QToolBar *toolbar);
-};
-
-
-void ui_toolitem_vstgr(
-        char *name,
-        char *stockid,
-        int isimportant,
-        ui_callback f,
-        void *userdata,
-        va_list ap);
-
-
-QToolBar* ui_create_toolbar(UiObject *obj);
 
 
 #endif /* TOOLBAR_H */
index 13c8f2993504eae8c6fe54864a8f9827914f5ea9..3db92034b7cd0095bbaf5e31b37a5933aa6f910b 100644 (file)
 
 #include "../common/document.h"
 #include "../common/properties.h"
+#include "../common/menu.h"
+#include "../common/toolbar.h"
 
-static char *application_name;
+static const char *application_name;
 
-static ui_callback appclose_fnc;
-static void *appclose_udata;
+static ui_callback   startup_func;
+static void          *startup_data;
+static ui_callback   open_func;
+void                 *open_data;
+static ui_callback   exit_func;
+void                 *exit_data;
+
+static int is_toplevel_realized = 0;
 
-//static QApplication app(qargc, qargv);
 int app_argc;
 char **app_argv;
 QApplication *application = NULL;
 
-void ui_init(char *appname, int argc, char **argv) {
+void ui_init(const char *appname, int argc, char **argv) {
     application_name = appname;
     
     app_argc = argc;
@@ -54,30 +61,39 @@ void ui_init(char *appname, int argc, char **argv) {
     application = new QApplication(app_argc, app_argv);
     
     uic_docmgr_init();
+    uic_menu_init();
+    uic_toolbar_init();
     
     uic_load_app_properties();
-    
-    ui_stock_init();
+     
 }
 
-char* ui_appname() {
+const char* ui_appname() {
     return application_name;
 }
 
-void ui_exitfunc(ui_callback f, void *udata) {
-    appclose_fnc = f;
-    appclose_udata = udata;
+void ui_onstartup(ui_callback f, void *userdata) {
+    startup_func = f;
+    startup_data = userdata;
 }
 
-void ui_openfilefunc(ui_callback f, void *userdata) {
-    // OS X only
+void ui_onopen(ui_callback f, void *userdata) {
+    open_func = f;
+    open_data = userdata;
+}
+
+void ui_onexit(ui_callback f, void *userdata) {
+    exit_func = f;
+    exit_data = userdata;
 }
 
 void ui_main() {
+    if(startup_func) {
+        startup_func(NULL, startup_data);
+    }
     application->exec();
-    
-    if(appclose_fnc) {
-        appclose_fnc(NULL, appclose_udata);
+    if(exit_func) {
+        exit_func(NULL, exit_data);
     }
     uic_store_app_properties();
     
@@ -103,6 +119,7 @@ void ui_set_visible(UIWIDGET widget, int visible) {
 
 
 
+/* --------------------- Implemtation UiEventWrapper --------------------- */
 
 UiEventWrapper::UiEventWrapper(UiObject *obj, ui_callback f, void* userdata) {
     this->obj = obj;
@@ -111,11 +128,64 @@ UiEventWrapper::UiEventWrapper(UiObject *obj, ui_callback f, void* userdata) {
 }
 
 void UiEventWrapper::slot() {
+    if(!callback) {
+        return;
+    }
+    
+    UiEvent e;
+    e.obj = obj;
+    e.window = obj->window;
+    e.document = obj->ctx->document;
+    e.eventdata = NULL;
+    e.intval = 0;
+    e.set = ui_get_setop();
+    if(prepare_event) {
+        prepare_event(&e, this);
+    }
+    callback(&e, userdata);
+    
+    // TODO: notify var observers
+}
+
+void UiEventWrapper::destroy() {
+    delete this;
+}
+
+
+/* --------------------- Implemtation UiAction --------------------- */
+
+UiAction::UiAction(UiObject *obj, QString &label, ui_callback f, void *userdata) : QAction(label, NULL) {
+    this->obj = obj;
+    this->callback = f;
+    this->userdata = userdata;
+}
+
+UiAction::~UiAction() {
+    
+}
+
+void UiAction::trigger() {
+    if(!callback) {
+        return;
+    }
+    
     UiEvent e;
     e.obj = obj;
     e.window = obj->window;
     e.document = obj->ctx->document;
     e.eventdata = NULL;
     e.intval = 0;
+    e.set = ui_get_setop();
+    if(prepare_event) {
+        prepare_event(&e, this);
+    }
     callback(&e, userdata);
+    
+    // TODO: notify var observers
+}
+
+// ui_enablefunc for UiAction
+void ui_action_enable(UiAction *action, int enable) {
+    action->setEnabled((bool)enable);
 }
+
index f767ef66ffed0ac19b864c952d9a3429542d72a5..1db8df722231c78cc8912961b4bbd57813c07da4 100644 (file)
 
 #include <QApplication>
 
+class UiEventWrapper;
+
+typedef void (*ui_prepare_event_func)(UiEvent *event, UiEventWrapper *wrapper);
+
 class UiEventWrapper : public QObject {
     Q_OBJECT
     
     UiObject *obj;
     ui_callback callback;
     void *userdata;
-
+    
 public:
+    UiVar *var;
+    
+    void *customdata1 = nullptr;
+    void *customdata2 = nullptr;
+    int customvalue1 = 0;
+    int customvalue2 = 0;
+    
+    ui_prepare_event_func prepare_event = nullptr;
+    
     UiEventWrapper(UiObject *obj, ui_callback f, void *userdata);
     
 public slots:
     void slot();
+    void destroy();
+};
+
+class UiAction;
+
+typedef void (*ui_prepare_action_event_func)(UiEvent *event, UiAction *action);
+
+class UiAction : public QAction {
+    Q_OBJECT
+            
+    UiObject *obj;
+    ui_callback callback;
+    void *userdata;
+    
+public:
+    UiVar *var;
+    
+    ui_prepare_action_event_func prepare_event = nullptr;
+    void *customdata1 = nullptr;
+    void *customdata2 = nullptr;
+    int customvalue1 = 0;
+    int customvalue2 = 0;
+    
+    UiAction(UiObject *obj, QString &label, ui_callback f, void *userdata);
+    ~UiAction();
+    
+private slots:
+    void trigger();
 };
 
+void ui_action_enable(UiAction *action, int enable);
 
 #endif /* TOOLKIT_H */
 
index d62b20ccfbd7759b1b4d2fe3490aa3e0ec617b19..336041adc5cc8e148690213c844b0710d3e262df 100644 (file)
 #include <QListView>
 
 
-extern "C" void* ui_strmodel_getvalue(void *elm, int column) {
-    return column == 0 ? elm : NULL;
-}
-
-UIWIDGET ui_listview_str(UiObject *obj, UiList *list, ui_callback f, void *udata) {
-    return ui_listview(obj, list, ui_strmodel_getvalue, f, udata);
-}
-UIWIDGET ui_listview_var(UiObject *obj, UiListPtr *list, ui_model_getvalue_f getvalue, ui_callback f, void *udata) {
-    QListView *view = new QListView();
-    ListModel *model = new ListModel(obj, view, list, getvalue, f, udata);
-    view->setModel(model);
-    
-    // TODO: observer update
-    
-    QItemSelectionModel *s = view->selectionModel();
-    QObject::connect(
-            s,
-            SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
-            model,
-            SLOT(selectionChanged(const QItemSelection &, const QItemSelection &)));
-    
-    UiContainer *ct = uic_get_current_container(obj); 
-    ct->add(view, true);
-    return view;
-}
-
-UIWIDGET ui_listview(UiObject *obj, UiList *list, ui_model_getvalue_f getvalue, ui_callback f, void *udata) {
-    UiListPtr *listptr = (UiListPtr*)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 = (UiListVar*)var->value;
-        return ui_listview_var(obj, value->listptr, getvalue, f, udata);
-    } else {
-        // TODO: error
-    }
-    return NULL;
-}
-
-
-UIWIDGET ui_table_var(UiObject *obj, UiListPtr *list, UiModelInfo *modelinfo) {
-    QTreeView *view = new QTreeView();
-    TableModel *model = new TableModel(obj, view, list, modelinfo);
-    view->setModel(model);
-    
-    view->setItemsExpandable(false);
-    view->setRootIsDecorated(false);   
-    
-    // TODO: observer update
-    UiTableView *u = new UiTableView();
-    u->widget = view;
-    u->model = model;
-    list->list->observers = ui_add_observer(
-            list->list->observers,
-            (ui_callback)ui_table_update,
-            u);
-    
-    view->setSelectionMode(QAbstractItemView::ExtendedSelection);
-    QItemSelectionModel *s = view->selectionModel();
-    QObject::connect(
-            s,
-            SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
-            model,
-            SLOT(selectionChanged(const QItemSelection &, const QItemSelection &)));
-    QObject::connect(
-            view,
-            SIGNAL(doubleClicked(const QModelIndex &)),
-            model,
-            SLOT(activate(const QModelIndex &)));
-    
-    
-    UiContainer *ct = uic_get_current_container(obj); 
-    ct->add(view, true);
-    return view;
-}
-
-void ui_table_update(UiEvent *event, UiTableView *view) {
-    // TODO
-    printf("update\n");
-    
-    //view->model->update();
-    view->widget->setModel(NULL);
-    view->widget->setModel(view->model);
-}
-
-UIWIDGET ui_table(UiObject *obj, UiList *list, UiModelInfo *modelinfo) {
-    UiListPtr *listptr = (UiListPtr*)ucx_mempool_malloc(obj->ctx->mempool, sizeof(UiListPtr));
-    listptr->list = list;
-    return ui_table_var(obj, listptr, modelinfo);
-}
-
-UIWIDGET ui_table_nv(UiObject *obj, char *varname, UiModelInfo *modelinfo) {
-    UiVar *var = uic_connect_var(obj->ctx, varname, UI_VAR_LIST);
-    if(var) {
-        UiListVar *value = (UiListVar*)var->value;
-        return ui_table_var(obj, value->listptr, modelinfo);
-    } else {
-        // TODO: error
-    }
-    return NULL;
-}
-
index 54dd0cd2ca6a8ecd8718699d2cf8dd30885cddb3..664b32b5f40bd1aea4bf7c193ba82d5d0b062100 100644 (file)
 
 #include <QTableView>
 
-class UiTableView {
-public:
-    QTreeView *widget;
-    TableModel *model;
-};
 
-extern "C" void ui_table_update(UiEvent *event, UiTableView *view);
 
 #endif /* TREE_H */
 
index 119ea3e5b6f808adaa4d08892fd6ae004fbde77d..a30dc6bf31aa37074fb790be8be74225d0fd56b6 100644 (file)
@@ -26,7 +26,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#include <ucx/mempool.h>
+#include <cx/mempool.h>
 #include "../common/context.h"
 
 #include "window.h"
 
 #include <QVBoxLayout>
 #include <QFileDialog>
+#include <QPushButton>
 
-static UiObject* create_window(char *title, void *window_data, bool simple) {
-    UcxMempool *mp = ucx_mempool_new(256);
-    UiObject *obj = (UiObject*)ucx_mempool_calloc(mp, 1, sizeof(UiObject));
+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);
     obj->window = window_data;
     obj->next = NULL;
     
     QMainWindow *window = new QMainWindow();
+    window->setWindowTitle(title);
     obj->widget = window;
     
     if(!simple) {
         ui_add_menus(obj, window);
-        QToolBar *toolbar = ui_create_toolbar(obj);
-        window->addToolBar(Qt::TopToolBarArea, toolbar);
+        //QToolBar *toolbar = ui_create_toolbar(obj);
+        //window->addToolBar(Qt::TopToolBarArea, toolbar);
     }
     
     QBoxLayout *box = new QVBoxLayout();
     QWidget *boxWidget = new QWidget();
     boxWidget->setLayout(box);
     window->setCentralWidget(boxWidget);
-    obj->container = new UiBoxContainer(box);
+    ui_container_add(obj, new UiBoxContainer(box));
     
     obj->widget = window;
     return obj;
 }
 
-UiObject* ui_window(char *title, void *window_data) {
+UiObject* ui_window(const char *title, void *window_data) {
     return create_window(title, window_data, FALSE);
 }
 
index faa91e76873e8d5fd3d34c6a703ea98a04427c89..3f828ea6b219c9b598917fda72da67254a5b6198 100644 (file)
@@ -259,6 +259,7 @@ struct UiContainerX {
 #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))
index 94ab8a6961db9e412acebf8cd04afbf70e4de739..d54c9e9704e4b01a082b52d0fe010e8635682645 100644 (file)
@@ -51,6 +51,13 @@ typedef struct UiImageViewerArgs {
 
     UiBool scrollarea;
     UiBool autoscale;
+    UiBool adjustwidgetsize;
+    UiBool useradjustable;
+    int image_padding;
+    int image_padding_left;
+    int image_padding_right;
+    int image_padding_top;
+    int image_padding_bottom;
     UiGeneric *value;
     const char *varname;
     UiMenuBuilder *contextmenu;
@@ -60,6 +67,11 @@ typedef struct UiImageViewerArgs {
     
 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);
+UIEXPORT UIWIDGET ui_imageviewer_set_adjustwidgetsize(UIWIDGET w, UiBool set);
+UIEXPORT UIWIDGET ui_imageviewer_set_useradjustable(UIWIDGET w, UiBool set);
+
 UIEXPORT int ui_image_load_file(UiGeneric *obj, const char *path);
 
 #ifdef __cplusplus
index 732473ca8dbb8d900e8fd5e22dca515d10a97ba3..2af07c5406e381b78976b793aae3dea8ece61a8c 100644 (file)
@@ -30,6 +30,7 @@
 #define        UI_TOOLKIT_H
 
 #include <inttypes.h>
+#include <stdlib.h>
 
 #ifdef UI_COCOA
 
@@ -60,24 +61,41 @@ typedef void* UIMENU;   // NSMenu*
 #include <adwaita.h>
 #endif
 
-#elif UI_MOTIF
-
-#include <Xm/XmAll.h> 
-#define UIWIDGET Widget
-#define UIMENU   Widget
-
 #elif defined(UI_QT4) || defined(UI_QT5)
+#define UI_QT
+
 #ifdef __cplusplus
+
 #include <QApplication>
 #include <QWidget>
 #include <QMenu>
+
 #define UIWIDGET QWidget*
+#define UIWINDOW QWidget*
 #define UIMENU   QMenu*
 #else /* __cplusplus */
 #define UIWIDGET void*
+#define UIWINDOW void*
 #define UIMENU   void*
 #endif
 
+#elif UI_MOTIF
+
+#include <Xm/XmAll.h> 
+#define UIWIDGET Widget
+#define UIMENU   Widget
+
+
+#elif UI_WIN32
+
+#include <Windows.h>
+
+#define UIEXPORT __declspec(dllexport)
+
+#define UIWIDGET void*
+#define UIWINDOW void*
+#define UIMENU   void*
+
 #elif UI_WINUI
 
 #define UIEXPORT __declspec(dllexport) 
@@ -193,16 +211,29 @@ typedef struct UiThreadpool  UiThreadpool;
 
 typedef struct UiTabbedPane UiTabbedPane;
 
-typedef enum UiTri UiTri;
-typedef enum UiLabelType UiLabelType;
+typedef enum UiTri {
+    UI_DEFAULT = 0,
+    UI_ON,
+    UI_OFF
+} UiTri;
 
-typedef enum UiDnDAction UiDnDAction;
 
 enum UiMouseEventType { UI_PRESS = 0, UI_PRESS2 };
 
-enum UiLabelType { UI_LABEL_DEFAULT, UI_LABEL_TEXT, UI_LABEL_ICON, UI_LABEL_TEXT_ICON };
-
-enum UiDnDAction { UI_DND_ACTION_NONE, UI_DND_ACTION_COPY, UI_DND_ACTION_MOVE, UI_DND_ACTION_LINK, UI_DND_ACTION_CUSTOM };
+typedef enum UiLabelType {
+    UI_LABEL_DEFAULT,
+    UI_LABEL_TEXT,
+    UI_LABEL_ICON,
+    UI_LABEL_TEXT_ICON
+} UiLabelType;
+
+typedef enum UiDnDAction {
+    UI_DND_ACTION_NONE,
+    UI_DND_ACTION_COPY,
+    UI_DND_ACTION_MOVE,
+    UI_DND_ACTION_LINK,
+    UI_DND_ACTION_CUSTOM
+} UiDnDAction;
   
 typedef void(*ui_callback)(UiEvent*, void*); /* event, user data */
 
@@ -346,6 +377,7 @@ struct UiText {
     void  (*insert)(UiText*, int, char*);
     void  (*setposition)(UiText*,int);
     int   (*position)(UiText*);
+    void  (*setselection)(UiText*, int, int); /* text, begin, end */
     void  (*selection)(UiText*, int*, int*); /* text, begin, end */
     int   (*length)(UiText*);
     void  (*remove)(UiText*, int, int); /* text, begin, end */
@@ -428,12 +460,6 @@ struct UiRange {
     UiObserver *observers;
 };
 
-enum UiTri {
-    UI_DEFAULT = 0,
-    UI_ON,
-    UI_OFF
-};
-
 struct UiFileList {
     char **files;
     size_t nfiles;
index 3ac2e15aee4199f3b76b35d14beb275510a0a5f5..e08233dfef0c289c56e2a7598f0a05df5ac9a0f1 100644 (file)
@@ -49,12 +49,16 @@ typedef struct UiWidgetArgs {
 
 #ifdef UI_GTK
 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);
 #elif defined(UI_MOTIF)
 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);
 #elif defined(UI_WINUI)
 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);
 #endif
 UIEXPORT UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func create_widget, void *userdata, UiWidgetArgs args);
 
@@ -65,6 +69,9 @@ UIEXPORT UIWIDGET ui_separator_create(UiObject *obj, UiWidgetArgs *args);
 
 #define ui_separator(obj, ...) ui_separator_create(obj, &(UiWidgetArgs){ __VA_ARGS__ } )
 
+UIEXPORT void ui_widget_set_size(UIWIDGET w, int width, int height);
+UIEXPORT void ui_widget_redraw(UIWIDGET w);
+
 
 #ifdef __cplusplus
 }
diff --git a/ui/win32/Makefile b/ui/win32/Makefile
new file mode 100644 (file)
index 0000000..97b3d25
--- /dev/null
@@ -0,0 +1,33 @@
+#
+# 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.
+#
+
+$(WIN32_OBJPRE)%.obj: win32/%.c
+       $(CC) -o $@ -c -I../ucx $(CFLAGS) $(TK_CFLAGS) $<
+
+$(UI_LIB): $(OBJ)
+       $(AR) $(ARFLAGS) $(UI_LIB) $(OBJ)       
diff --git a/ui/win32/objs.mk b/ui/win32/objs.mk
new file mode 100644 (file)
index 0000000..e74d9c6
--- /dev/null
@@ -0,0 +1,35 @@
+#
+# 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.
+#
+
+WIN32_SRC_DIR = ui/win32/
+WIN32_OBJPRE = $(OBJ_DIR)$(WIN32_SRC_DIR)
+
+WIN32OBJ = toolkit.obj
+
+TOOLKITOBJS += $(WIN32OBJ:%=$(WIN32_OBJPRE)%)
+TOOLKITSOURCE += $(WIN32OBJ:%.obj=win32/%.c)
diff --git a/ui/win32/toolkit.c b/ui/win32/toolkit.c
new file mode 100644 (file)
index 0000000..4afbc73
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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 "toolkit.h"
+#include "Windows.h"
+
+#include "../common/properties.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+static const char *application_name;
+
+static ui_callback   startup_func;
+static void          *startup_data;
+static ui_callback   open_func;
+void                 *open_data;
+static ui_callback   exit_func;
+void                 *exit_data;
+
+void ui_init(const char *appname, int argc, char **argv) {
+      application_name = appname;
+}
+
+const char* ui_appname() {
+    return application_name;
+}
+
+void ui_onstartup(ui_callback f, void *userdata) {
+    startup_func = f;
+    startup_data = userdata;
+}
+
+void ui_onopen(ui_callback f, void *userdata) {
+    open_func = f;
+    open_data = userdata;
+}
+
+void ui_onexit(ui_callback f, void *userdata) {
+    exit_func = f;
+    exit_data = userdata;
+}
+
+void ui_main() {
+    if(startup_func) {
+        startup_func(NULL, startup_data);
+    }
+
+    // event loop
+    MSG msg;
+    while (GetMessage(&msg, NULL, 0, 0)) {
+        TranslateMessage(&msg);
+        DispatchMessage(&msg);
+    }
+
+    if(exit_func) {
+        exit_func(NULL, exit_data);
+    }
+    uic_store_app_properties();
+}
diff --git a/ui/win32/toolkit.h b/ui/win32/toolkit.h
new file mode 100644 (file)
index 0000000..3b5071c
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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 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
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TOOLKIT_H */
+