]> uap-core.de Git - uwplayer.git/commitdiff
update toolkit default
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Sat, 11 Jul 2026 18:17:58 +0000 (20:17 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Sat, 11 Jul 2026 18:17:58 +0000 (20:17 +0200)
126 files changed:
ui/Makefile
ui/cocoa/AppDelegate.h [new file with mode: 0644]
ui/cocoa/AppDelegate.m [new file with mode: 0644]
ui/cocoa/BoxContainer.h
ui/cocoa/EventData.h
ui/cocoa/EventData.m
ui/cocoa/GridLayout.h
ui/cocoa/ListDelegate.h
ui/cocoa/ListDelegate.m
ui/cocoa/MainWindow.h
ui/cocoa/MainWindow.m
ui/cocoa/TabView.h
ui/cocoa/TabView.m
ui/cocoa/Toolbar.h
ui/cocoa/Toolbar.m
ui/cocoa/WindowManager.h
ui/cocoa/WindowManager.m
ui/cocoa/action.h [new file with mode: 0644]
ui/cocoa/action.m [new file with mode: 0644]
ui/cocoa/button.m
ui/cocoa/container.h
ui/cocoa/container.m
ui/cocoa/entry.h
ui/cocoa/image.h
ui/cocoa/image.m
ui/cocoa/label.m
ui/cocoa/list.h
ui/cocoa/list.m
ui/cocoa/menu.m
ui/cocoa/objs.mk
ui/cocoa/text.h
ui/cocoa/text.m
ui/cocoa/toolkit.h
ui/cocoa/toolkit.m
ui/cocoa/webview.m
ui/cocoa/widget.h
ui/cocoa/widget.m
ui/cocoa/window.m
ui/common/Makefile [new file with mode: 0644]
ui/common/action.c [new file with mode: 0644]
ui/common/action.h [new file with mode: 0644]
ui/common/app.c
ui/common/app.h
ui/common/args.c
ui/common/args.h
ui/common/container.c
ui/common/context.c
ui/common/context.h
ui/common/document.c
ui/common/icons.c [new file with mode: 0644]
ui/common/icons.h [new file with mode: 0644]
ui/common/menu.c
ui/common/menu.h
ui/common/object.c
ui/common/object.h
ui/common/objs.mk
ui/common/properties.c
ui/common/threadpool.c
ui/common/threadpool.h
ui/common/toolbar.c
ui/common/toolbar.h
ui/common/types.c
ui/common/types.h
ui/common/wrapper.c
ui/common/wrapper.h
ui/gtk/Makefile
ui/gtk/action.c [new file with mode: 0644]
ui/gtk/action.h [new file with mode: 0644]
ui/gtk/button.c
ui/gtk/button.h
ui/gtk/container.c
ui/gtk/container.h
ui/gtk/display.c
ui/gtk/headerbar.c
ui/gtk/headerbar.h
ui/gtk/icon.c
ui/gtk/list.c
ui/gtk/list.h
ui/gtk/menu.c
ui/gtk/menu.h
ui/gtk/objs.mk
ui/gtk/text.c
ui/gtk/text.h
ui/gtk/toolbar.c
ui/gtk/toolbar.h
ui/gtk/toolkit.c
ui/gtk/toolkit.h
ui/gtk/window.c
ui/gtk/window.h [new file with mode: 0644]
ui/motif/Grid.c
ui/motif/Makefile
ui/motif/button.c
ui/motif/button.h
ui/motif/container.c
ui/motif/container.h
ui/motif/label.c
ui/motif/menu.c
ui/motif/menu.h
ui/motif/text.c
ui/motif/text.h
ui/motif/toolkit.c
ui/motif/toolkit.h
ui/motif/window.c
ui/qt/container.cpp
ui/qt/container.h
ui/qt/list.cpp
ui/qt/menu.cpp
ui/qt/menu.h
ui/qt/model.cpp
ui/qt/text.cpp
ui/qt/text.h
ui/qt/toolkit.cpp
ui/qt/toolkit.h
ui/qt/window.cpp
ui/ui/button.h
ui/ui/container.h
ui/ui/display.h
ui/ui/entry.h
ui/ui/icons.h
ui/ui/list.h
ui/ui/menu.h
ui/ui/text.h
ui/ui/toolbar.h
ui/ui/toolkit.h
ui/ui/webview.h
ui/ui/widget.h

index ad5aad0f563cbf93f8b7de3d6e7ed169a9abf4a8..b03b6d3d1ad64d8e2c1b7d0cf948b077aeecdb34 100644 (file)
@@ -41,8 +41,5 @@ OBJ = $(TOOLKITOBJS) $(COMMONOBJS)
 
 all: $(UI_LIB) $(UI_SHLIB)
 
+include common/Makefile
 include $(TOOLKIT)/Makefile
-
-$(COMMON_OBJPRE)uic_%$(OBJ_EXT): common/%.c
-       $(CC) -o $@ -c -I../ucx/ $(CFLAGS) $(SHLIB_CFLAGS) $(TK_CFLAGS) $<
-
diff --git a/ui/cocoa/AppDelegate.h b/ui/cocoa/AppDelegate.h
new file mode 100644 (file)
index 0000000..7c2ce1e
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2024 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "../ui/toolkit.h"
+#include "../common/context.h"
+#include "../common/object.h"
+
+@interface AppDelegate : NSObject <NSApplicationDelegate>
+
+
+@end
diff --git a/ui/cocoa/AppDelegate.m b/ui/cocoa/AppDelegate.m
new file mode 100644 (file)
index 0000000..b28df42
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+#import "AppDelegate.h"
+#import "WindowManager.h"
+
+#import "toolkit.h"
+#import "menu.h"
+
+#import "../common/app.h"
+
+@implementation AppDelegate
+
+- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
+    NSLog(@"toolkit applicationDidFinishLaunching");
+    uic_application_startup(NULL);
+    // The menu init func can be called multiple times and is also called
+    // when a new window is created
+    // The only usecase for calling init here is, that an application might not
+    // open a window on startup, but wants a working menubar
+    ui_menu_init();
+}
+
+- (void)applicationWillTerminate:(NSNotification *)aNotification {
+    NSLog(@"toolkit applicationWillTerminate");
+    uic_application_exit(NULL);
+    [[WindowManager sharedWindowManager] shutdown];
+    ui_app_save_settings();
+}
+
+
+- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app {
+    return YES;
+}
+
+
+@end
index a80ae7dc8c7d2219d4b6b7843f247a10ec190ef9..065c78ff2e9b801c7b333a5dd76f69fc4fc2ec86 100644 (file)
@@ -26,7 +26,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import "Container.h"
+#import "container.h"
 #import "GridLayout.h"
 
 @interface BoxContainer : GridLayout
index 4ee89f3e11e512b842e669f2acb6cc403c5c5e3f..f0c8eacfc62c4597e4065fed6757f1a52c914a6f 100644 (file)
@@ -29,7 +29,7 @@
 #import "../ui/toolkit.h"
 #import "../common/context.h"
 
-typedef void(*get_eventdata_func)(id sender, UiVar *var, void **eventdata, int *value);
+typedef void(*get_eventdata_func)(id sender, UiVar *var, void **eventdata, UiEventType *eventdatatype, int *value);
 
 @interface EventData : NSObject
 @property UiObject           *obj;
@@ -37,11 +37,12 @@ typedef void(*get_eventdata_func)(id sender, UiVar *var, void **eventdata, int *
 @property int                vartype;
 @property ui_callback        callback;
 @property void               *userdata;
+@property NSString           *action;
 @property void               *data;
 @property int                value;
 @property get_eventdata_func get_eventdata;
 
-- (EventData*)init:(ui_callback)cb userdata:(void*)userdata;
+- (EventData*)init:(ui_callback)cb userdata:(void*)userdata action:(const char*)action;
 
 - (void)handleEvent:(id)sender;
 
index 1df6d9b4f5123c414ae1e129e96daf7c1d0908d3..aa8c74b6e11a463eef16fcc1376ef235c0c013b8 100644 (file)
  */
 
 #import "EventData.h"
+#import "action.h"
 
 #import <objc/runtime.h>
 
 
 @implementation EventData
 
-- (EventData*)init:(ui_callback)cb userdata:(void*)userdata {
+- (EventData*)init:(ui_callback)cb userdata:(void*)userdata action:(const char*)action {
     _callback = cb;
     _userdata = userdata;
+    if(action != nil) {
+        _action = [[NSString alloc]initWithUTF8String:action];
+    }
     return self;
 }
 
 - (void)handleEvent:(id)sender {
-    if(_callback) {
-        UiEvent event;
-        event.obj = self.obj;
-        event.window = event.obj->window;
-        event.document = event.obj->ctx->document;
-        event.eventdata = self.data;
-        event.intval = self.value;
-        event.set = ui_get_setop();
+    UiEvent event;
+    event.obj = self.obj;
+    event.window = event.obj->window;
+    event.document = event.obj->ctx->document;
+    event.eventdata = self.data;
+    event.intval = self.value;
+    event.set = ui_get_setop();
+    
+    if(_callback != nil) {
         self.callback(&event, self.userdata);
     }
+    
+    if(_action != nil) {
+        uic_action_callback(&event, self.action.UTF8String);
+    }
 }
 
 - (void)handleEventWithEventData:(id)sender {
@@ -61,7 +70,7 @@
     event.intval = 0;
     event.set = ui_get_setop();
     if(_get_eventdata) {
-        _get_eventdata(sender, _var, &event.eventdata, &event.intval);
+        _get_eventdata(sender, _var, &event.eventdata, &event.eventdatatype, &event.intval);
     }
     if(self.callback) {
         self.callback(&event, self.userdata);
index 362c9b281551a4299ed98696e1836080f1bf3b28..ccb652819e6dfb7b1f262bcd816fdc170830462c 100644 (file)
@@ -28,7 +28,7 @@
 
 #import "toolkit.h"
 
-#import "Container.h"
+#import "container.h"
 
 #import <cx/array_list.h>
 
@@ -56,7 +56,7 @@ typedef struct GridDef {
 
 @interface GridLayout : NSView<Container>
 
-@property UiContainerX *container;
+@property UiContainer *container;
 
 @property int columnspacing;
 @property int rowspacing;
index 27762f79ad8dd926eef5a23b9a5986b3877621a6..6603b82c0bdd01b7d32243cac9a4773f3a9b9380 100644 (file)
 @property UiObject    *obj;
 @property ui_callback onselection;
 @property void        *onselectiondata;
+@property NSString    *onselection_action;
 @property ui_callback onactivate;
 @property void        *onactivatedata;
+@property NSString    *onactivate_action;
 
 - (id)init:(NSTableView*) tableview obj:(UiObject*)obj;
 
index 7e15f3d7a768bcced3dfdd52645d57ed7208cbda..d4642315a12ed499425ebb9f830fa9afa9e7c615 100644 (file)
 
 - (void)activateEvent:(id)sender {
     NSTableView *table = sender;
+    
+    int row = (int)table.clickedRow;
+    
+    UiListSelection sel;
+    sel.count = 1;
+    sel.rows = &row;
+    
+    UiEvent  event;
+    event.obj = _obj;
+    event.window = event.obj->window;
+    event.document = event.obj->ctx->document;
+    event.eventdata = &sel;
+    event.eventdatatype = UI_EVENT_DATA_LIST_SELECTION;
+    event.intval = row;
+    event.set = ui_get_setop();
+    
     if(_onactivate) {
-        int row = (int)table.clickedRow;
-        
-        UiListSelection sel;
-        sel.count = 1;
-        sel.rows = &row;
-        
-        UiEvent  event;
-        event.obj = _obj;
-        event.window = event.obj->window;
-        event.document = event.obj->ctx->document;
-        event.eventdata = &sel;
-        event.eventdatatype = UI_EVENT_DATA_LIST_SELECTION;
-        event.intval = row;
-        event.set = ui_get_setop();
-        
         _onactivate(&event, _onactivatedata);
     }
+    
+    if(_onselection_action) {
+        uic_action_callback(&event, _onselection_action.UTF8String);
+    }
 }
 
 - (void) tableViewSelectionDidChange:(NSNotification *) notification {
-    if(_onselection) {
+    if(ui_selection_events_is_enabled()) {
         UiListSelection sel = ui_tableview_selection(_tableview);
         
-        UiEvent  event;
+        UiEvent event;
         event.obj = _obj;
         event.window = event.obj->window;
         event.document = event.obj->ctx->document;
         event.intval = 0;
         event.set = ui_get_setop();
         
-        _onselection(&event, _onselectiondata);
+        if(_onselection) {
+            _onselection(&event, _onselectiondata);
+        }
+        
+        if(_onselection_action) {
+            uic_action_callback(&event, _onselection_action.UTF8String);
+        }
     }
 }
 
index 7c8cbf63d9688d0925b2c2a55105330f5f1758ac..52ad47fa9dc0151d86d46a9749eb30e732999027 100644 (file)
@@ -29,7 +29,7 @@
 #import "toolkit.h"
 #import "../ui/window.h"
 
-@interface MainWindow : NSWindow<UiToplevelObject>
+@interface MainWindow : NSWindow<UiToplevelObject, NSWindowDelegate>
 
 @property UiObject *obj;
 @property (strong) NSSplitView *splitview;
@@ -38,7 +38,8 @@
 @property (strong) NSView *rightPanel;
 @property int topOffset;
 
-- (MainWindow*)init:(UiObject*)obj withSidebar:(BOOL)hasSidebar withSplitview:(BOOL)hasSplitview;
+- (MainWindow*)init:(UiObject*)obj withSidebar:(BOOL)hasSidebar withSplitview:(BOOL)hasSplitview width:(int)width height:(int)height;
+- (void) saveWindowSize;
 
 @end
 
index c62079f03b64a79264976d96e896f97f89f4a0a3..944c9aa3206a736f5302a42828a59a4c38727b71 100644 (file)
@@ -27,7 +27,8 @@
  */
 
 #import "MainWindow.h"
-#import "Container.h"
+#import "WindowManager.h"
+#import "container.h"
 #import "GridLayout.h"
 #import "BoxContainer.h"
 #import "../common/object.h"
 #import "menu.h"
 #import "Toolbar.h"
 
+
+
 @implementation MainWindow
 
-- (MainWindow*)init:(UiObject*)obj withSidebar:(BOOL)hasSidebar withSplitview:(BOOL)hasSplitview{
-    NSRect frame = NSMakeRect(300, 200, 600, 500);
+- (MainWindow*)init:(UiObject*)obj withSidebar:(BOOL)hasSidebar withSplitview:(BOOL)hasSplitview width:(int)width height:(int)height {
+    NSRect frame = NSMakeRect(300, 200, width, height);
     
     self = [self initWithContentRect:frame
                            styleMask:NSWindowStyleMaskTitled |
@@ -51,7 +54,7 @@
                              backing:NSBackingStoreBuffered
                                defer:false];
     _obj = obj;
-    
+    self.delegate = self;
     
     int top = 4;
     NSView *content = self.contentView;
             [vbox.trailingAnchor constraintEqualToAnchor:content.trailingAnchor],
             [vbox.bottomAnchor constraintEqualToAnchor:content.bottomAnchor],
         ]];
-        UiContainerX *container = ui_create_container(obj, vbox);
+        UiContainer *container = ui_create_container(obj, vbox);
         vbox.container = container;
         uic_object_push_container(obj, container);
     }
         [self setToolbar:toolbar];
     }
     
-    
     return self;
 }
 
+- (void) saveWindowSize {
+    CGSize size = self.frame.size;
+    if(size.width > 0 && size.height > 0) {
+        char width_str[32];
+        char height_str[32];
+        snprintf(width_str, 32, "%d", (int)size.width);
+        snprintf(height_str, 32, "%d", (int)size.height);
+        ui_set_property("ui.window.width", width_str);
+        ui_set_property("ui.window.height", height_str);
+    }
+}
+
 - (BOOL) getIsVisible {
     return [self isVisible];
 }
     }
 }
 
+- (void) windowWillClose:(NSNotification *) notification {
+    UiObject *obj = _obj;
+    
+    if(obj->onclose) {
+        UiEvent event;
+        memset(&event, 0, sizeof(UiEvent));
+        event.obj = obj;
+        event.window = obj->window;
+        event.document = obj->ctx->document;
+        obj->onclose(&event, obj->onclosedata);
+    }
+    
+    if(obj->ref > 0) {
+        obj->ref--;
+    } else {
+        // warn about invalid reference counting
+        NSLog(@"Error: UiObject %p ref == 0\n", obj);
+    }
+    
+    if(obj->ref == 0) {
+        [self saveWindowSize];
+        // this cleans up any widget references from the context
+        uic_context_prepare_close(obj->ctx);
+        [[WindowManager sharedWindowManager] closeWindow:self];
+    }
+}
 
+- (void) dealloc {
+    uic_object_destroy(_obj);
+    NSLog(@"MainWindow dealloc");
+}
 @end
 
 
index d6e4b0dfb4d1825dd29480ddd970faae0707c292..506c1e61864151191a02e0327faa2b244906af9b 100644 (file)
@@ -26,7 +26,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import "Container.h"
+#import "container.h"
 
 @protocol TabView
 
index 5b50048168e36009e101162498499983d3c63b1f..5cfc1bf945f82dc0ec69a4d7933141b802100f6f 100644 (file)
     UiObject *newobj = uic_object_new_toplevel();
     newobj->widget = (__bridge void*)sub;
     
-    UiContainerX *container = ui_create_container(newobj, sub);
+    UiContainer *container = ui_create_container(newobj, sub);
     uic_object_push_container(newobj, container);
     
     return newobj;
index 7ec7bbd5d4d11fcc6287a0f6bda5e36f26140c44..042fa240462d2fe723f8924581d510044b6b9446 100644 (file)
@@ -50,7 +50,7 @@
     NSMutableArray<NSString*> *defaultItems;
 }
 
-@property MainWindow *window;
+@property (weak) MainWindow *window;
 @property UiObject *obj;
 
 - (UiToolbar*) initWithWindow:(MainWindow*)window;
index 8ab2ad83afa97042c7dfdd6ee0c1c067aaf007ca..e9a09679fac5bc9c8af3a42b78e696efad28700d 100644 (file)
@@ -39,7 +39,21 @@ void ui_toolbar_init(void) {
     
 }
 
+static void toolitem_set_enabled(void *item, int enabled) {
+    NSToolbarItem *i = (__bridge NSToolbarItem*)item;
+    i.enabled = enabled;
+}
 
+static void toolitem_bind_action(UiContext *ctx, NSToolbarItem *item, const char *action) {
+    if(action) {
+        void *widget = (__bridge void*)item;
+        uic_bind_action(ctx, action, widget, (ui_enablefunc)toolitem_set_enabled);
+        UiAction *ui_action = uic_resolve_action(ctx, action);
+        if(!ui_action) {
+            toolitem_set_enabled(widget, FALSE);
+        }
+    }
+}
 
 /* ---------------------      UiToolbar      --------------------- */
 
@@ -219,12 +233,14 @@ NSToolbarItem* ui_nstoolbaritem_create_item(UiObject *obj, UiToolbarItem *item,
         button.image = ui_cocoa_named_icon(item->args.icon);
     }
     
-    if(item->args.onclick) {
-        EventData *event = [[EventData alloc] init:item->args.onclick userdata:item->args.onclickdata];
+    if(item->args.onclick || item->args.action) {
+        EventData *event = [[EventData alloc] init:item->args.onclick userdata:item->args.onclickdata action:item->args.action];
         event.obj = obj;
         button.target = event;
         button.action = @selector(handleEvent:);
         objc_setAssociatedObject(button, "eventdata", event, OBJC_ASSOCIATION_RETAIN);
+        
+        toolitem_bind_action(obj->ctx, button, item->args.action);
     }
     return button;
 }
@@ -243,14 +259,23 @@ NSToolbarItem* ui_nstoolbaritem_create_toggle(UiObject *obj, UiToolbarToggleItem
     }
     objc_setAssociatedObject(button, "eventdata", event, OBJC_ASSOCIATION_RETAIN);
     
-    NSSegmentedControl *seg;
+    NSSegmentedControl *seg = nil;
     if(!item->args.icon) {
-        NSArray *labels = @[[[NSString alloc] initWithUTF8String:item->args.label]];
-        seg = [NSSegmentedControl segmentedControlWithLabels:labels trackingMode:NSSegmentSwitchTrackingSelectAny target:event action:@selector(handleEvent:)];
-        button.view = seg;
+        if(item->args.label) {
+            NSArray *labels = @[[[NSString alloc] initWithUTF8String:item->args.label]];
+            seg = [NSSegmentedControl segmentedControlWithLabels:labels trackingMode:NSSegmentSwitchTrackingSelectAny target:event action:@selector(handleEvent:)];
+            button.view = seg;
+        } else {
+            NSLog(@"UI Error: toggle button has no icon or label");
+        }
     } else {
-        NSArray *images = @[ui_cocoa_named_icon(item->args.icon)];
-        seg = [NSSegmentedControl segmentedControlWithImages:images trackingMode:NSSegmentSwitchTrackingSelectAny target:event action:@selector(handleEvent:)];
+        NSImage *image = ui_cocoa_named_icon(item->args.icon);
+        if(image != nil) {
+            NSArray *images = @[image];
+            seg = [NSSegmentedControl segmentedControlWithImages:images trackingMode:NSSegmentSwitchTrackingSelectAny target:event action:@selector(handleEvent:)];
+        } else {
+            NSLog(@"UI Error: icon %s not found", item->args.icon);
+        }
     }
     button.view = seg;
     
@@ -265,7 +290,6 @@ NSToolbarItem* ui_nstoolbaritem_create_toggle(UiObject *obj, UiToolbarToggleItem
             
         }
         i->obj = (__bridge void*)seg;
-        printf("seg: %p\n", seg);
         i->get = ui_toolbar_seg_toggleitem_get;
         i->set = ui_toolbar_seg_toggleitem_set;
     }
index 7f1b225af6c36332b4f5e3b6865475eadb70513b..76e3c655c83004c58a3871a1790468d21575cba0 100644 (file)
 
 #import "toolkit.h"
 
-@interface WindowManager : NSObject<NSWindowDelegate>
+@interface WindowManager : NSObject
 
-@property NSMutableArray<NSWindow*> *windows;
+@property NSMutableArray<NSWindowController*> *windows;
 
 + (WindowManager*) sharedWindowManager;
 
 - (WindowManager*)init;
 
-- (void)addWindow:(NSWindow*)win;
+- (void)addWindow:(NSWindowController*)win;
+
+- (void)closeWindow:(NSWindow*)win;
+
+- (void)shutdown;
 
 @end
index ca0318211603b3faee8aa7a65622257161ab194a..9b5d04a26561b11354c7e90984d4cfc87424bbe9 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #import "WindowManager.h"
+#import "MainWindow.h"
 
 @implementation WindowManager
 
@@ -44,14 +45,21 @@ static WindowManager *instance = nil;
     return self;
 }
 
-- (void)addWindow:(NSWindow*)win {
+- (void)addWindow:(NSWindowController*)win {
     [_windows addObject:win];
-    [win setDelegate:self];
 }
 
-- (void) windowWillClose:(NSNotification *) notification {
-    NSWindow *window = notification.object;
-    [_windows removeObject:window];
+- (void)closeWindow:(NSWindow*)win {
+    [_windows removeObject:win.windowController];
+}
+
+- (void)shutdown {
+    if(_windows.count > 0) {
+        NSWindowController *controller = _windows.firstObject;
+        MainWindow *win = (MainWindow*)controller.window;
+        [win saveWindowSize];
+    }
+    [_windows removeAllObjects];
 }
 
 @end
diff --git a/ui/cocoa/action.h b/ui/cocoa/action.h
new file mode 100644 (file)
index 0000000..4d9d19f
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2026 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "../ui/toolkit.h"
+#include "../common/action.h"
+
+#import "widget.h"
+
+void ui_cocoa_view_bind_action(UiContext *ctx, NSView *view, const char *action);
diff --git a/ui/cocoa/action.m b/ui/cocoa/action.m
new file mode 100644 (file)
index 0000000..943341a
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2026 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "action.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+
+/* ------------------------------ public API ------------------------------ */
+
+void ui_add_action(UiContext *ctx, const char *name, ui_callback callback, void *userdata) {
+    uic_add_action(ctx, name, callback, userdata, NULL, NULL);
+}
+
+void ui_add_action_with_accelerator(
+        UiContext *ctx,
+        const char *name,
+        ui_callback callback,
+        void *userdata,
+        const char *accelerator,
+        const char *accelerator_text)
+{
+    uic_add_action(ctx, name, callback, userdata, accelerator, accelerator_text);
+    
+    // TODO: accelerator
+}
+
+
+void ui_cocoa_view_bind_action(UiContext *ctx, NSView *view, const char *action) {
+    if(action) {
+        void *widget = (__bridge void*)view;
+        uic_bind_action(ctx, action, widget, (ui_enablefunc)ui_set_enabled);
+        UiAction *ui_action = uic_resolve_action(ctx, action);
+        if(!ui_action) {
+            ui_set_enabled(widget, FALSE);
+        }
+    }
+}
index 54295dab1501b97bad2083565a7afe47beb9c429..dd1c55945945c0756f0caa7cf0eeef9f09a5a63d 100644 (file)
@@ -28,8 +28,9 @@
 
 #import "button.h"
 #import "EventData.h"
-#import "Container.h"
+#import "container.h"
 #import "image.h"
+#import "action.h"
 #import <objc/runtime.h>
 
 #import <cx/buffer.h>
@@ -46,12 +47,14 @@ UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs *args) {
         button.image = ui_cocoa_named_icon(args->icon);;
     }
     
-    if(args->onclick) {
-        EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata];
+    if(args->onclick || args->action) {
+        EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata action:args->action];
         event.obj = obj;
         button.target = event;
         button.action = @selector(handleEvent:);
         objc_setAssociatedObject(button, "eventdata", event, OBJC_ASSOCIATION_RETAIN);
+        
+        ui_cocoa_view_bind_action(obj->ctx, button, args->action);
     }
     
     UiLayout layout = UI_INIT_LAYOUT(args);
@@ -61,7 +64,7 @@ UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs *args) {
 }
 
 
-static void togglebutton_eventdata(id button, UiVar *var, void **eventdata, int *value) {
+static void togglebutton_eventdata(id button, UiVar *var, void **eventdata, UiEventType *eventdatatype, int *value) {
     NSButton *btn = (NSButton*)button;
     NSControlStateValue state = btn.state;
     *value = (int)state;
@@ -88,8 +91,8 @@ UIWIDGET togglebutton_create(UiObject* obj, UiToggleArgs *args, enum NSButtonTyp
         i->set = ui_togglebutton_set;
     }
     
-    if(args->onchange) {
-        EventData *event = [[EventData alloc] init:args->onchange userdata:args->onchangedata];
+    if(args->onchange || args->action) {
+        EventData *event = [[EventData alloc] init:args->onchange userdata:args->onchangedata action:args->action];
         event.get_eventdata = togglebutton_eventdata;
         event.obj = obj;
         event.var = var;
@@ -97,6 +100,8 @@ UIWIDGET togglebutton_create(UiObject* obj, UiToggleArgs *args, enum NSButtonTyp
         button.target = event;
         button.action = @selector(handleEventWithEventData:);
         objc_setAssociatedObject(button, "eventdata", event, OBJC_ASSOCIATION_RETAIN);
+        
+        ui_cocoa_view_bind_action(obj->ctx, button, args->action);
     }
     
     UiLayout layout = UI_INIT_LAYOUT(args);
@@ -132,7 +137,7 @@ UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs *args) {
     return togglebutton_create(obj, args, NSButtonTypeSwitch);
 }
 
-static void switch_eventdata(id button, UiVar *var, void **eventdata, int *value) {
+static void switch_eventdata(id button, UiVar *var, void **eventdata, UiEventType *eventdatatype, int *value) {
     NSSwitch *btn = (NSSwitch*)button;
     NSControlStateValue state = btn.state;
     *value = (int)state;
@@ -149,8 +154,8 @@ UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs *args) {
         i->set = ui_switch_set;
     }
     
-    if(args->onchange) {
-        EventData *event = [[EventData alloc] init:args->onchange userdata:args->onchangedata];
+    if(args->onchange || args->action) {
+        EventData *event = [[EventData alloc] init:args->onchange userdata:args->onchangedata action:args->action];
         event.get_eventdata = switch_eventdata;
         event.obj = obj;
         event.var = var;
@@ -158,6 +163,7 @@ UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs *args) {
         button.target = event;
         button.action = @selector(handleEventWithEventData:);
         objc_setAssociatedObject(button, "eventdata", event, OBJC_ASSOCIATION_RETAIN);
+        ui_cocoa_view_bind_action(obj->ctx, button, args->action);
     }
     
     UiLayout layout = UI_INIT_LAYOUT(args);
@@ -201,10 +207,10 @@ void ui_switch_set(UiInteger *i, int64_t value) {
 
 @end
 
-static void radiobutton_eventdata(id button, UiVar *var, void **eventdata, int *value) {
+static void radiobutton_eventdata(id button, UiVar *var, void **eventdata, UiEventType *eventdatatype, int *value) {
     if(var) {
-        UiInteger *value = var->value;
-        NSMutableArray *buttons = (__bridge NSMutableArray*)value->obj;
+        UiInteger *i = var->value;
+        NSMutableArray *buttons = (__bridge NSMutableArray*)i->obj;
         for(UiRadioButton *b in buttons) {
             if(b != button) {
                 b.direct_state = YES;
@@ -238,18 +244,19 @@ UIWIDGET ui_radiobutton_create(UiObject* obj, UiToggleArgs *args) {
         objc_setAssociatedObject(button, "radiogroup", buttons, OBJC_ASSOCIATION_RETAIN);
     }
     
-    if(args->onchange || var) {
-        EventData *event = [[EventData alloc] init:args->onchange userdata:args->onchangedata];
+    if(args->onchange || args->action || var) {
+        EventData *event = [[EventData alloc] init:args->onchange userdata:args->onchangedata action:args->action];
         event.get_eventdata = radiobutton_eventdata;
         event.obj = obj;
         event.var = var;
         event.vartype = UI_VAR_INTEGER;
         button.target = event;
         
-        
         button.action = @selector(handleEventWithEventData:);
         
         objc_setAssociatedObject(button, "eventdata", event, OBJC_ASSOCIATION_RETAIN);
+        
+        ui_cocoa_view_bind_action(obj->ctx, button, args->action);
     }
     
     UiLayout layout = UI_INIT_LAYOUT(args);
@@ -370,7 +377,7 @@ static char* create_linkbutton_jsonvalue(const char *label, const char *uri, UiB
     
     CxJsonWriter writer = cxJsonWriterCompact();
     CxBuffer buf;
-    cxBufferInit(&buf, NULL, 128, NULL, CX_BUFFER_AUTO_EXTEND);
+    cxBufferInit(&buf, NULL, NULL, 128, CX_BUFFER_AUTO_EXTEND);
     cxJsonWrite(&buf, obj, (cx_write_func)cxBufferWrite, &writer);
     cxJsonValueFree(obj);
     cxBufferTerminate(&buf);
index ed2dc67b92f2126271d09b9141c9267a43a09efd..89512acbfb921abd9d5cbe881248fd2b1705b45b 100644 (file)
@@ -51,7 +51,7 @@ typedef struct UiLayout UiLayout;
 
 @protocol Container
 
-@property UiContainerX *container;
+@property UiContainer *container;
 
 - (void) addView:(NSView*)view layout:(UiLayout*)layout;
 
@@ -73,6 +73,6 @@ typedef struct UiLayout UiLayout;
 @end
 
 
-UiContainerX* ui_create_container(UiObject *obj, id<Container> container);
+UiContainer* ui_create_container(UiObject *obj, id<Container> container);
 
 void ui_container_add(UiObject *obj, NSView *view, UiLayout *layout);
index d9b2e2d8cfd4d2c35312669161a2b13793da912b..2bd54a203bafa7edf31efed710f3a3665eb76e50 100644 (file)
@@ -26,7 +26,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
-#import "Container.h"
+#import "container.h"
 #import "GridLayout.h"
 #import "BoxContainer.h"
 #import "TabView.h"
@@ -36,7 +36,7 @@
 static UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs *args, NSUserInterfaceLayoutOrientation orientation) {
     BoxContainer *box = [[BoxContainer alloc] init:orientation spacing:args->spacing];
     box.translatesAutoresizingMaskIntoConstraints = false;
-    UiContainerX *container = ui_create_container(obj, box);
+    UiContainer *container = ui_create_container(obj, box);
     
     // add box to the parent
     UiLayout layout = UI_INIT_LAYOUT(args);
@@ -61,7 +61,7 @@ UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) {
     grid.translatesAutoresizingMaskIntoConstraints = false;
     grid.columnspacing = args->columnspacing;
     grid.rowspacing = args->rowspacing;
-    UiContainerX *container = ui_create_container(obj, grid);
+    UiContainer *container = ui_create_container(obj, grid);
     grid.container = container;
     
     // add box to the parent
@@ -81,7 +81,7 @@ UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args) {
     ui_container_add(obj, frame, &layout);
     
     // add container to the chain
-    UiContainerX *container;
+    UiContainer *container;
     UiLayout subLayout = {0};
     switch(args->subcontainer) {
         default: {
@@ -137,12 +137,22 @@ UIWIDGET ui_scrolledwindow_create(UiObject *obj, UiFrameArgs *args) {
     UiLayout layout = UI_ARGS2LAYOUT(args);
     ui_container_add(obj, scrollview, &layout);
     
-    UiContainerX *container = ui_create_container(obj, scrollview);
+    UiContainer *container = ui_create_container(obj, scrollview);
     uic_object_push_container(obj, container);
     
     return (__bridge void*)scrollview;
 }
 
+static int64_t tabview_get(UiInteger *i) {
+    NSView<TabView, Container> *tabview = (__bridge id)i->obj;
+    return 0;
+}
+
+static void tabview_set(UiInteger *i, int64_t value) {
+    NSView<TabView, Container> *tabview = (__bridge id)i->obj;
+    
+}
+
 UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs *args) {
     NSView<TabView, Container> *tabview;
     switch(args->tabview) {
@@ -152,19 +162,19 @@ UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs *args) {
     UiLayout layout = UI_ARGS2LAYOUT(args);
     ui_container_add(obj, tabview, &layout);
     
-    UiContainerX *container = ui_create_container(obj, tabview);
+    UiContainer *container = ui_create_container(obj, tabview);
     uic_object_push_container(obj, container);
     
     return (__bridge void*)tabview;
 }
 
 void ui_tab_create(UiObject *obj, const char* title) {
-    UiContainerX *ctn = obj->container_end;
+    UiContainer *ctn = obj->container_end;
     id<TabView> tabview = (__bridge id<TabView>)ctn->container;
     NSString *s = title ? [[NSString alloc]initWithUTF8String:title] : @"";
     NSView<Container> *sub = [tabview createTab:-1 title:s];
     
-    UiContainerX *container = ui_create_container(obj, sub);
+    UiContainer *container = ui_create_container(obj, sub);
     uic_object_push_container(obj, container);
 }
 
@@ -204,12 +214,12 @@ UIWIDGET ui_vsplitpane_create(UiObject *obj, UiSplitPaneArgs *args) {
 
 
 void ui_container_begin_close(UiObject *obj) {
-    UiContainerX *ct = obj->container_end;
+    UiContainer *ct = obj->container_end;
     ct->close = 1;
 }
 
 int ui_container_finish(UiObject *obj) {
-    UiContainerX *ct = obj->container_end;
+    UiContainer *ct = obj->container_end;
     if(ct->close) {
         ui_end_new(obj);
         return 0;
@@ -307,8 +317,8 @@ int ui_container_finish(UiObject *obj) {
 
 /* ------------------------- private functions ------------------------- */
 
-UiContainerX* ui_create_container(UiObject *obj, id<Container> container) {
-    UiContainerX *ctn = ui_malloc(obj->ctx, sizeof(UiContainerX));
+UiContainer* ui_create_container(UiObject *obj, id<Container> container) {
+    UiContainer *ctn = ui_malloc(obj->ctx, sizeof(UiContainer));
     ctn->container = (__bridge void*)container;
     ctn->close = 0;
     ctn->prev = NULL;
@@ -318,7 +328,7 @@ UiContainerX* ui_create_container(UiObject *obj, id<Container> container) {
 }
 
 void ui_container_add(UiObject *obj, NSView *view, UiLayout *layout) {
-    UiContainerX *ctn = obj->container_end;
+    UiContainer *ctn = obj->container_end;
     id<Container> container = (__bridge id<Container>)ctn->container;
     UiLayout adjustedLayout = *layout;
     if(adjustedLayout.margin > 0) {
index b0cb2fdaa5a6f9bcf5aad53b67881d7dac6a2800..227d984607238f9b7485122634b6534b487be0bf 100644 (file)
@@ -27,7 +27,7 @@
  */
 
 #import "toolkit.h"
-#import "Container.h"
+#import "container.h"
 
 #import "../ui/entry.h"
 
index 8b80a70f50fe9c14dba3457623b420da43b6c260..70f1d8de0d66b3e7ed8f3887f81f0ebef8c57394 100644 (file)
@@ -28,7 +28,7 @@
 
 #include "../ui/image.h"
 
-#include "Container.h"
+#include "container.h"
 
 typedef struct UiImage {
     void *nsimage;
index a6794c08b3b321275f479b7581efec9949c7f711..80ae7d2267e26243d7e05824b9a3e043cfe3cdfd 100644 (file)
@@ -100,11 +100,12 @@ void ui_icon_init(void) {
 
 NSImage* ui_cocoa_named_icon(const char *name) {
     NSString *imageName = [[NSString alloc] initWithUTF8String:name];
-    NSString *imgName = [standardIconNames objectForKey:imageName];
-    if(imgName) {
-        imageName = imgName;
-    }
-    return [NSImage imageNamed:imageName];
+    //NSString *imgName = [standardIconNames objectForKey:imageName];
+    //if(imgName) {
+    //    imageName = imgName;
+    //}
+    //return [NSImage imageNamed:imageName];
+    return [NSImage imageWithSystemSymbolName:imageName accessibilityDescription:nil];
 }
 
 static UIIMAGE create_image(NSImage *image) {
index 4e75e01d57bbdf6e49e87b862a413666e2d5d553..44e90451f7437c5b53c797a8e9e7e88765a84acb 100644 (file)
@@ -27,7 +27,7 @@
  */
 
 #import "label.h"
-#import "Container.h"
+#import "container.h"
 
 #import <string.h>
 
index 6a3b174dec9a35da1dc96d71fb443688d005bbea..173afc604373eb976086d93a210ad0afb4f1ab19 100644 (file)
@@ -27,7 +27,7 @@
  */
 
 #import "toolkit.h"
-#import "Container.h"
+#import "container.h"
 #import "../ui/list.h"
 
 #import "ListDataSource.h"
index 5e72e9243a868c276d5d34e021eec0209f4bbf3b..132d84aa0244fce6f0e22baea0a6caa1ab2168a2 100644 (file)
@@ -54,8 +54,14 @@ static void add_listdelegate(UiObject *obj, NSTableView *tableview, UiListArgs *
     ListDelegate *delegate = [[ListDelegate alloc] init:tableview obj:obj];
     delegate.onactivate = args->onactivate;
     delegate.onactivatedata = args->onactivatedata;
+    if(args->onactivate_action) {
+        delegate.onactivate_action = [[NSString alloc]initWithUTF8String:args->onactivate_action];
+    }
     delegate.onselection = args->onselection;
     delegate.onselectiondata = args->onselectiondata;
+    if(args->onselection_action) {
+        delegate.onselection_action = [[NSString alloc]initWithUTF8String:args->onselection_action];
+    }
     tableview.delegate = delegate;
     objc_setAssociatedObject(tableview, "ui_listdelegate", delegate, OBJC_ASSOCIATION_RETAIN);
     tableview.doubleAction = @selector(activateEvent:);
@@ -209,6 +215,7 @@ UIWIDGET ui_table_create(UiObject* obj, UiListArgs *args) {
 void ui_tableview_update(UiList *list, int i) {
     NSTableView *tableview = (__bridge NSTableView*)list->obj;
     if(i < 0) {
+        [tableview deselectAll: tableview];
         [tableview reloadData];
     } else {
         [tableview reloadData]; // TODO: optimize
@@ -263,7 +270,7 @@ void ui_tableview_setselection(UiList *list, UiListSelection selection) {
     event.eventdatatype = UI_EVENT_DATA_LIST_ELM;
     event.intval = index;
     
-    if(_onselection) {
+    if(_onselection && ui_selection_events_is_enabled()) {
         _onselection(&event, _onselectiondata);
     }
     
@@ -468,7 +475,7 @@ UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs *args) {
     data.onactivate = args->onactivate;
     data.onactivatedata = args->onactivatedata;
     data.onbuttonclick = args->onbuttonclick;
-    data.onactivatedata = args->onbuttonclickdata;
+    data.onbuttonclickdata = args->onbuttonclickdata;
     [data update:-1];
  
     outline.dataSource = data;
@@ -508,18 +515,37 @@ void ui_sourcelist_update(UiList *list, int row) {
     
     [_sections removeAllObjects];
     
-    CxIterator i = cxListIterator(_sublists);
-    int index = 0;
-    int rownum = 0;
-    cx_foreach(UiSubList *, sl, i) {
-        UiSourceListItem *section = [[UiSourceListItem alloc] init:self sublist:sl];
-        section.sublistIndex = index;
-        section.rownum = rownum;
-        section.sublistStartRow = rownum;
-        [section update:-1];
-        [_sections addObject:section];
-        index++;
-        rownum += 1 + section.items.count;
+    if(_sublists) {
+        CxIterator i = cxListIterator(_sublists);
+        int index = 0;
+        int rownum = 0;
+        cx_foreach(UiSubList *, sl, i) {
+            UiSourceListItem *section = [[UiSourceListItem alloc] init:self sublist:sl];
+            section.sublistIndex = index;
+            section.rownum = rownum;
+            section.sublistStartRow = rownum;
+            [section update:-1];
+            [_sections addObject:section];
+            index++;
+            rownum += 1 + section.items.count;
+        }
+    } else if (_dynamic_sublists) {
+        UiList *sublists = _dynamic_sublists->value;
+        UiSubList *sl = sublists->first(sublists);
+        int index = 0;
+        int rownum = 0;
+        while(sl) {
+            UiSourceListItem *section = [[UiSourceListItem alloc] init:self sublist:sl];
+            section.sublistIndex = index;
+            section.rownum = rownum;
+            section.sublistStartRow = rownum;
+            [section update:-1];
+            [_sections addObject:section];
+            index++;
+            rownum += 1 + section.items.count;
+            
+            sl = sublists->next(sublists);
+        }
     }
     
     [_outlineView reloadData];
index eae8a50960689564dd88e24415cbffdf9c415166..9e7a39db562932574931494206e691f115f106c9 100644 (file)
@@ -109,10 +109,10 @@ void add_menuitem_widget(UiObject *obj, NSMenu *parent, int i, UiMenuItemI *item
     UiMenuItem *it = (UiMenuItem*)item;
     
     NSString *str = [[NSString alloc] initWithUTF8String:it->label];
-    NSMenuItem *menuItem = [parent addItemWithTitle:str action:@selector(menuItemAction) keyEquivalent:@""];
+    NSMenuItem *menuItem = [parent addItemWithTitle:str action:@selector(menuItemAction:) keyEquivalent:@""];
     
     if(it->callback) {
-        EventData *event = [[EventData alloc] init:it->callback userdata:it->userdata];
+        EventData *event = [[EventData alloc] init:it->callback userdata:it->userdata action:it->action];
         if(obj) {
             event.obj = obj;
             menuItem.target = event;
@@ -186,11 +186,19 @@ void add_menuitem_list_widget(UiObject *obj, NSMenu *parent, int i, UiMenuItemI
 }
 
 
+static BOOL menu_is_initialized = NO;
+
 void ui_menu_init(void) {
-    bindingItems = [[NSMutableArray alloc] init];
-    
     UiMenu *menus_begin = uic_get_menu_list();
     UiMenu *ls = menus_begin;
+    
+    if(menu_is_initialized || !ls) {
+        return;
+    }
+    menu_is_initialized = YES;
+    
+    bindingItems = [[NSMutableArray alloc] init];
+    
     int index = 1;
     while(ls) {
         if(ls->item.type == UI_MENU) {
index d4d0e61143ba9925294bb13ee39451a671d65d3a..a37ec4fc07fe219322efe325f6e47a198ff92fa2 100644 (file)
@@ -38,7 +38,7 @@ COCOAOBJ += UiThread.o
 COCOAOBJ += MainWindow.o
 COCOAOBJ += WindowManager.o
 COCOAOBJ += window.o
-COCOAOBJ += Container.o
+COCOAOBJ += container.o
 COCOAOBJ += button.o
 COCOAOBJ += text.o
 COCOAOBJ += menu.o
@@ -51,6 +51,7 @@ COCOAOBJ += widget.o
 COCOAOBJ += image.o
 COCOAOBJ += entry.o
 COCOAOBJ += TabView.o
+COCOAOBJ += action.o
 
 TOOLKITOBJS += $(COCOAOBJ:%=$(COCOA_OBJPRE)%)
 TOOLKITSOURCE += $(COCOAOBJ:%.o=cocoa/%.m)
index 23bc4389d1029e8eb96433ad08ac79c6307fe6eb..eec2fe4f88351b5712267a744862214d8fed6672 100644 (file)
@@ -37,7 +37,7 @@ void  ui_textarea_restore(UiText *text);
 void  ui_textarea_set(UiText *text, const char *str);
 char* ui_textarea_get(UiText *text);
 char* ui_textarea_getsubstr(UiText *text, int begin, int end);
-void  ui_textarea_insert(UiText *text, int pos, char *str);
+void  ui_textarea_insert(UiText *text, int pos, const 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);
@@ -47,3 +47,31 @@ void  ui_textarea_remove(UiText *text, int begin, int end);
 
 char* ui_textfield_get(UiString *s);
 void ui_textfield_set(UiString *s, const char *value);
+
+
+@interface TextAreaDelegate: NSObject<NSTextViewDelegate, NSTextDelegate>
+
+@property UiObject *obj;
+@property UiVar *var;
+@property ui_callback onchange;
+@property void *onchangedata;
+@property NSString *onchange_action;
+@property ui_callback ontextchanged;
+@property void *ontextchangeddata;
+@property NSString *ontextchanged_action;
+
+- (id)init:(UiObject*)obj var:(UiVar*)var args:(UiTextAreaArgs*)args;
+
+@end
+
+@interface TextFieldDelegate : NSObject<NSTextFieldDelegate>
+
+@property UiObject *obj;
+@property UiVar *var;
+@property ui_callback onchange;
+@property void *onchangedata;
+@property NSString *onchange_action;
+
+- (id)init:(UiObject*)obj var:(UiVar*)var;
+
+@end
index 324d6e7560478747b32a79e4c5259f1a278021e4..acbffedd33a593bcc31b203fc38e6b584201f4b7 100644 (file)
@@ -28,7 +28,8 @@
 
 #import "text.h"
 #import "EventData.h"
-#import "Container.h"
+#import "container.h"
+#import "action.h"
 #import <objc/runtime.h>
 
 UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) {
@@ -41,6 +42,11 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) {
     scrollview.hasVerticalScroller = YES;
     scrollview.documentView = textview;
     
+    // store link to the textview
+    // associate it with the textview and the scrollview to support both widgets in ui_textarea_gettextwidget
+    objc_setAssociatedObject(textview, "ui_textarea", textview, OBJC_ASSOCIATION_ASSIGN);
+    objc_setAssociatedObject(scrollview, "ui_textarea", textview, OBJC_ASSOCIATION_ASSIGN);
+    
     UiLayout layout = UI_INIT_LAYOUT(args);
     ui_container_add(obj, scrollview, &layout);
     
@@ -66,11 +72,106 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) {
         text->remove = ui_textarea_remove;
     }
     
+    if(args->onchange || args->ontextchanged || args->onchange_action || args->ontextchanged_action) {
+        TextAreaDelegate * tad = [[TextAreaDelegate alloc] init:obj var:var args:args];
+        textview.delegate = tad;
+        objc_setAssociatedObject(textview, "delegate", tad, OBJC_ASSOCIATION_RETAIN);
+    }
+    
     return (__bridge void*)scrollview;
 }
 
+UIWIDGET ui_textarea_gettextwidget(UIWIDGET textarea) {
+    id view = (__bridge id)textarea;
+    id textview = objc_getAssociatedObject(view, "ui_textarea");
+    return (__bridge void*)textview;
+}
 
+void ui_textarea_focus(UIWIDGET textarea) {
+    textarea = ui_textarea_gettextwidget(textarea);
+    if(!textarea) {
+        fprintf(stderr, "Error: ui_textarea_focus: widget is not a textarea\n");
+        return;
+    }
+    NSTextView *view = (__bridge NSTextView*)textarea;
+    [view.window makeFirstResponder:view];
 
+}
+
+void ui_textarea_set_selection(UIWIDGET textarea, int begin, int end) {
+    textarea = ui_textarea_gettextwidget(textarea);
+    if(!textarea) {
+        fprintf(stderr, "Error: ui_textarea_set_selection: widget is not a textarea\n");
+        return;
+    }
+    NSTextView *view = (__bridge NSTextView*)textarea;
+    NSRange range = NSMakeRange(begin, end-begin);
+    [view setSelectedRange:range];
+}
+
+void ui_textarea_select_all(UIWIDGET textarea) {
+    textarea = ui_textarea_gettextwidget(textarea);
+    if(!textarea) {
+        fprintf(stderr, "Error: ui_textarea_select_all: widget is not a textarea\n");
+        return;
+    }
+}
+
+void ui_textarea_set_editable(UIWIDGET textarea, UiBool editable) {
+    textarea = ui_textarea_gettextwidget(textarea);
+    if(!textarea) {
+        fprintf(stderr, "Error: ui_textarea_set_editable: widget is not a textarea\n");
+        return;
+    }
+    NSTextView *view = (__bridge NSTextView*)textarea;
+    view.editable = editable;
+}
+
+UiBool ui_textarea_is_editable(UIWIDGET textarea) {
+    textarea = ui_textarea_gettextwidget(textarea);
+    if(!textarea) {
+        fprintf(stderr, "Error: ui_textarea_is_editable: widget is not a textarea\n");
+        return 0;
+    }
+    NSTextView *view = (__bridge NSTextView*)textarea;
+    return view.isEditable;
+}
+
+void ui_textarea_set_position(UIWIDGET textarea, int pos) {
+    textarea = ui_textarea_gettextwidget(textarea);
+    if(!textarea) {
+        fprintf(stderr, "Error: ui_textarea_set_position: widget is not a textarea\n");
+        return;
+    }
+    NSTextView *view = (__bridge NSTextView*)textarea;
+    NSRange range = NSMakeRange(pos, 0);
+    [view setSelectedRange:range];
+}
+
+int ui_textarea_get_position(UIWIDGET textarea) {
+    textarea = ui_textarea_gettextwidget(textarea);
+    if(!textarea) {
+        fprintf(stderr, "Error: ui_textarea_get_position: widget is not a textarea\n");
+        return 0;
+    }
+    NSTextView *view = (__bridge NSTextView*)textarea;
+    NSRange range = view.selectedRange;
+    return (int)range.location;
+}
+
+void ui_textarea_scroll_to(UIWIDGET textarea, int pos) {
+    textarea = ui_textarea_gettextwidget(textarea);
+    if(!textarea) {
+        fprintf(stderr, "Error: ui_textarea_scroll_to: widget is not a textarea\n");
+        return;
+    }
+    NSTextView *view = (__bridge NSTextView*)textarea;
+    NSRange range = NSMakeRange(pos, 0);
+    [view scrollRangeToVisible:range];
+}
+
+
+// UiText textarea functions
 
 void ui_textarea_save(UiText *text) {
     
@@ -120,7 +221,7 @@ char* ui_textarea_getsubstr(UiText *text, int begin, int end) {
     return strdup(sub.UTF8String);
 }
 
-void ui_textarea_insert(UiText *text, int pos, char *str) {
+void ui_textarea_insert(UiText *text, int pos, const char *str) {
     NSTextView *textview = (__bridge NSTextView*)text->obj;
     NSString *s = [[NSString alloc] initWithUTF8String:str];
     NSAttributedString *attributedStr = [[NSAttributedString alloc] initWithString:s];
@@ -174,8 +275,116 @@ void ui_textarea_remove(UiText *text, int begin, int end) {
 
 
 
+@implementation TextAreaDelegate
+
+- (id)init:(UiObject*)obj var:(UiVar*)var args:(UiTextAreaArgs*)args {
+    self.onchange = args->onchange;
+    self.onchangedata = args->onchangedata;
+    if(args->onchange_action) {
+        self.onchange_action = [[NSString alloc]initWithUTF8String:args->onchange_action];
+    }
+    self.ontextchanged = args->ontextchanged;
+    self.ontextchangeddata = args->ontextchangeddata;
+    if(args->ontextchanged_action) {
+        self.ontextchanged_action = [[NSString alloc]initWithUTF8String:args->ontextchanged_action];
+    }
+    self.obj = obj;
+    self.var = var;
+    return self;
+}
+
+- (BOOL) textView:(NSTextView *) textView
+    shouldChangeTextInRange:(NSRange) affectedCharRange
+    replacementString:(NSString *) replacementString {
+    
+    if(_onchange == nil && _onchange_action == nil) {
+        return YES;
+    }
+    
+    UiEvent event;
+    event.obj = _obj;
+    event.window = event.obj->window;
+    event.document = event.obj->ctx->document;
+    event.intval = 0;
+    event.set = ui_get_setop();
+    // event data not set yet
+    
+    if(affectedCharRange.length > 0) {
+        UiTextChangeEventData eventdata;
+        eventdata.type = UI_TEXT_DELETE;
+        eventdata.begin = (int)affectedCharRange.location;
+        eventdata.end = (int)(affectedCharRange.location + affectedCharRange.length);
+        eventdata.text = NULL;
+        eventdata.length = 0;
+        
+        event.eventdata = &eventdata;
+        event.eventdatatype = UI_EVENT_DATA_TEXT_CHANGED;
+        
+        if(_onchange) {
+            _onchange(&event, _onchangedata);
+        }
+        
+        if(_onchange_action) {
+            uic_action_callback(&event, _onchange_action.UTF8String);
+        }
+    }
+    
+    if(replacementString.length > 0) {
+        UiTextChangeEventData eventdata;
+        eventdata.type = UI_TEXT_INSERT;
+        eventdata.begin = (int)affectedCharRange.location;
+        eventdata.end = 0;
+        eventdata.text = replacementString.UTF8String;
+        eventdata.length = (int)replacementString.length;
+        
+        event.eventdata = &eventdata;
+        event.eventdatatype = UI_EVENT_DATA_TEXT_CHANGED;
+        
+        if(_onchange) {
+            _onchange(&event, _onchangedata);
+        }
+        
+        if(_onchange_action) {
+            uic_action_callback(&event, _onchange_action.UTF8String);
+        }
+    }
+    
+    return YES;
+}
+
+- (void) textDidChange:(NSNotification *) notification {
+    UiEvent event;
+    event.obj = _obj;
+    event.window = event.obj->window;
+    event.document = event.obj->ctx->document;
+    if(_var) {
+        event.eventdata = _var->value;
+        event.eventdatatype = UI_EVENT_DATA_TEXT_VALUE;
+    } else {
+        event.eventdata = NULL;
+        event.eventdatatype = 0;
+    }
+    event.intval = 0;
+    event.set = ui_get_setop();
+    
+    if(_ontextchanged) {
+        _ontextchanged(&event, _ontextchangeddata);
+    }
+    
+    if(_ontextchanged_action) {
+        uic_action_callback(&event, _ontextchanged_action.UTF8String);
+    }
+}
+
+@end
+
+
 /* -------------------------- TextField -------------------------- */
 
+static void textfield_geteventdata(id sender, UiVar *var, void **eventdata, UiEventType *eventdatatype, int *value) {
+    
+}
+
 static UIWIDGET textfield_create(UiObject *obj, UiTextFieldArgs *args, BOOL password, BOOL frameless) {
     NSTextField *textfield;
     if(password) {
@@ -212,6 +421,27 @@ static UIWIDGET textfield_create(UiObject *obj, UiTextFieldArgs *args, BOOL pass
         s->set = ui_textfield_set;
     }
     
+    if(args->onactivate || args->onactivate_action) {
+        EventData *event = [[EventData alloc] init:args->onactivate userdata:args->onactivatedata action:args->onactivate_action];
+        event.get_eventdata = textfield_geteventdata;
+        event.obj = obj;
+        textfield.target = event;
+        textfield.action = @selector(handleEventWithEventData:);
+        objc_setAssociatedObject(textfield, "eventdata", event, OBJC_ASSOCIATION_RETAIN);
+        ui_cocoa_view_bind_action(obj->ctx, textfield, args->onactivate_action);
+    }
+    
+    if(args->onchange || args->onchange_action) {
+        TextFieldDelegate *tfd = [[TextFieldDelegate alloc]init:obj var:var];
+        tfd.onchange = args->onchange;
+        tfd.onchangedata = args->onchangedata;
+        if(args->onchange_action) {
+            tfd.onchange_action = [[NSString alloc]initWithUTF8String:args->onchange_action];
+        }
+        objc_setAssociatedObject(textfield, "delegate", tfd, OBJC_ASSOCIATION_RETAIN);
+        textfield.delegate = tfd;
+    }
+    
     return (__bridge void*)textfield;
 }
 
@@ -248,3 +478,89 @@ void ui_textfield_set(UiString *s, const char *value) {
     NSTextField *textfield = (__bridge NSTextField*)s->obj;
     textfield.stringValue = [[NSString alloc] initWithUTF8String:value];
 }
+
+/* -------------------------- public Textfield functions -------------------------- */
+
+void ui_textfield_focus(UIWIDGET textfield) {
+    NSTextField *tf = (__bridge NSTextField*)textfield;
+    [tf.window makeFirstResponder:tf];
+    [tf selectText:nil];
+}
+
+void ui_textfield_focus_without_selecting(UIWIDGET textfield) {
+    NSTextField *tf = (__bridge NSTextField*)textfield;
+    [tf.window makeFirstResponder:tf];
+}
+
+void ui_textfield_set_selection(UIWIDGET textfield, int begin, int end) {
+    NSTextField *tf = (__bridge NSTextField*)textfield;
+    [tf.window makeFirstResponder:tf];
+    NSTextView *fieldEditor = (NSTextView *)[tf.window fieldEditor:YES forObject:tf];
+    [fieldEditor setSelectedRange:NSMakeRange(begin, end-begin)];
+}
+
+void ui_textfield_select_all(UIWIDGET textfield) {
+    NSTextField *tf = (__bridge NSTextField*)textfield;
+    [tf selectText:nil];
+}
+
+void ui_textfield_set_editable(UIWIDGET textfield, UiBool editable) {
+    NSTextField *tf = (__bridge NSTextField*)textfield;
+    tf.editable = editable;
+}
+
+UiBool ui_textfield_is_editable(UIWIDGET textfield) {
+    NSTextField *tf = (__bridge NSTextField*)textfield;
+    return tf.isEditable;
+}
+
+void ui_textfield_set_position(UIWIDGET textfield, int pos) {
+    NSTextField *tf = (__bridge NSTextField*)textfield;
+    NSTextView *editor = (NSTextView *)[tf currentEditor];
+    [editor setSelectedRange:NSMakeRange(pos, 0)];
+}
+
+int ui_textfield_get_position(UIWIDGET textfield) {
+    NSTextField *tf = (__bridge NSTextField*)textfield;
+    NSTextView *editor = (NSTextView *)[tf currentEditor];
+    NSRange selectedRange = [editor selectedRange];
+    return (int)selectedRange.location;
+}
+
+
+/* -------------------- textfield delegate -------------------- */
+
+@implementation TextFieldDelegate
+
+- (id)init:(UiObject*)obj var:(UiVar*)var {
+    self.obj = obj;
+    self.var = var;
+    return self;
+}
+
+- (void)controlTextDidChange:(NSNotification *)obj {
+    UiString *value = _var ? _var->value : NULL;
+    
+    UiEvent e;
+    e.obj = _obj;
+    e.window = e.obj->window;
+    e.document = e.obj->ctx->document;
+    e.eventdata = value;
+    e.eventdatatype = value ? UI_EVENT_DATA_STRING_VALUE : 0;
+    e.intval = 0;
+    e.set = ui_get_setop();
+    
+    if(_onchange) {
+        _onchange(&e, _onchangedata);
+    }
+    
+    if(_var) {
+        ui_notify_evt(value->observers, &e);
+    }
+    
+    if(_onchange_action) {
+        uic_action_callback(&e, _onchange_action.UTF8String);
+    }
+}
+
+@end
index 9a377b35343359056fbe034648f9c8b35cc6d1f9..ab4c6da5f5f5909a9403dfad85f03aaa925b18f9 100644 (file)
@@ -51,7 +51,4 @@
 
 @end
 
-void ui_cocoa_onstartup(void);
-void ui_cocoa_onopen(const char *file);
-void ui_cocoa_onexit(void);
 
index c0e9edff00451902f89af3e37c9db80ffe7404f9..9a8e3095ced1e9cbaa2f021dde101e5d72db5fe7 100644 (file)
@@ -28,6 +28,9 @@
 
 #import "toolkit.h"
 
+#include <stdlib.h>
+#include <string.h>
+
 #include "../common/document.h"
 #include "../common/properties.h"
 #include "../common/menu.h"
@@ -47,35 +50,63 @@ static const char *application_name;
 static int app_argc;
 static const char **app_argv;
 
-static UiBool        exit_on_shutdown;
+static UiBool exit_on_shutdown;
+
+static char *main_thread_error_msg;
+
+// This function is only used by language bindings, to improve error messages
+// for example, when using java bindings, this can provide infos how to fix
+// this (-XstartOnFirstThread)
+void ui_set_main_thread_error_msg(const char *msg) {
+    main_thread_error_msg = msg ? strdup(msg) : NULL;
+}
 
 /* ------------------- App Init / Event Loop functions ------------------- */
 
+static AppDelegate *app_delegate;
+
+static void main_thr_check(const char *func) {
+    if(![NSThread isMainThread]) {
+        fprintf(stderr, "Error: %s must run on the main thread.\n", func);
+        if(main_thread_error_msg) {
+            fprintf(stderr, "%s\n", main_thread_error_msg);
+        }
+        exit(1);
+    }
+}
 
 void ui_init(const char *appname, int argc, char **argv) {
-    application_name = appname;
+    main_thr_check("ui_init");
+    
+    application_name = appname ? strdup(appname) : NULL;
     app_argc = argc;
     app_argv = (const char**)argv;
     
     uic_init_global_context();
-
+    
     uic_menu_init();
     uic_toolbar_init();
-
+    
     uic_load_app_properties();
-
+    
     NSApplication *app = [NSApplication sharedApplication];
-    //[app setActivationPolicy:NSApplicationActivationPolicyRegular];
+    [app setActivationPolicy:NSApplicationActivationPolicyRegular];
     
     //[NSBundle loadNibNamed:@"MainMenu" owner:NSApp ];
     //[[NSBundle mainBundle] loadNibNamed:@"MainMenu" owner:NSApp topLevelObjects:&topLevelObjects];
     
+    app_delegate = [[AppDelegate alloc] init];
+    
+    fflush(stdout);
+    app.delegate = app_delegate;
+    
+    
     ui_icon_init();
     ui_toolbar_init();
     
 }
 
-const char* ui_appname() {
+const char* ui_appname(void) {
     return application_name;
 }
 
@@ -83,41 +114,34 @@ void ui_app_exit_on_shutdown(UiBool exitapp) {
     exit_on_shutdown = exitapp;
 }
 
-void ui_cocoa_onstartup(void) {
-    UiEvent e;
-    e.obj = NULL;
-    e.window = NULL;
-    e.document = NULL;
-    e.eventdata = NULL;
-    e.intval = 0;
-    uic_application_startup(&e);
+void ui_main(void) {
+    main_thr_check("ui_main");
+    
+    NSApplicationMain(app_argc,app_argv);
+    //[NSApp finishLaunching];
+    //[NSApp activateIgnoringOtherApps:YES];
+    //[NSApp run];
+    if(exit_on_shutdown) {
+        exit(0);
+    }
 }
 
-void ui_cocoa_onopen(const char *file) {
-    UiEvent e;
-    e.obj = NULL;
-    e.window = NULL;
-    e.document = NULL;
-    e.eventdata = NULL;
-    e.intval = 0;
-    uic_application_open(&e);
+void ui_app_ref(void) {
+    // TODO
 }
 
-void ui_cocoa_onexit(void) {
-    UiEvent e;
-    e.obj = NULL;
-    e.window = NULL;
-    e.document = NULL;
-    e.eventdata = NULL;
-    e.intval = 0;
-    uic_application_exit(&e);
+void ui_app_unref(void) {
+    // TODO
 }
 
-void ui_main(void) {
-    NSApplicationMain(app_argc, app_argv);
-    if(exit_on_shutdown) {
-        exit(0);
-    }
+void ui_app_quit(void) {
+    [[NSApplication sharedApplication] terminate:nil];
+}
+
+void ui_open_uri(const char *uri) {
+    NSString *urlString = [NSString stringWithUTF8String:uri];
+    NSURL *url = [NSURL URLWithString:urlString];
+    [[NSWorkspace sharedWorkspace] openURL:url];
 }
 
 /* ------------------- Window Visibility functions ------------------- */
@@ -174,6 +198,11 @@ void ui_job(UiObject *obj, ui_threadfunc tf, void *td, ui_callback f, void *fd)
 @end
 
 void ui_call_mainthread(ui_threadfunc tf, void* td) {
+    if(uic_mainthread_calls_is_buffered()) {
+        uic_add_buffered_mainthread_call(tf, td);
+        return;
+    }
+    
     UiAppCallback *cb = [[UiAppCallback alloc]initWithCallback:tf userdata:td];
     [cb callMainThread];
 }
index 088ad5f67aa673f5a36d96bd92bbd16d9fc08ef6..a4b4dae6c5a47ef8e0e3dadcff54a3cee6afa9ce 100644 (file)
@@ -52,7 +52,7 @@ UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs *args) {
             data->webview = (__bridge void*)webview;
             data->javascript = TRUE;
             data->zoom = 1;
-            value->value = value;
+            value->value = data;
         }
     }
     
index 772bf88d718e4fe68cc0dfade47684ee1f870de2..5857c86b6242ae4ebe869f92bfe59d829d1339da 100644 (file)
@@ -27,5 +27,5 @@
  */
 
 #import "toolkit.h"
-#import "Container.h"
+#import "container.h"
 #import "../ui/widget.h"
index edc78c138240336a56b4662839db032d1bd07c8e..ff32bfe332b84cb121ba0a703038ed836a67fc0f 100644 (file)
@@ -44,6 +44,14 @@ void ui_set_visible(UIWIDGET widget, int visible) {
     view.hidden = !visible;
 }
 
+void ui_widget_set_size(UIWIDGET w, int width, int height) {
+    NSView *view = (__bridge NSView*)w;
+    NSRect frame = view.frame;
+    frame.size.width = width;
+    frame.size.height = height;
+    view.frame = frame;
+}
+
 
 UIWIDGET ui_separator_create(UiObject *obj, UiWidgetArgs *args) {
     // TODO
index a3fe0890fe9da612168fd43a8a844b32855aff7f..c027867e3ccfffd7c718cf1b595197aeed97e115 100644 (file)
@@ -32,6 +32,7 @@
 #import "WindowManager.h"
 #import "BoxContainer.h"
 #import "EventData.h"
+#import "menu.h"
 
 #import <objc/runtime.h>
 
@@ -41,6 +42,7 @@
 #include "../common/menu.h"
 #include "../common/toolbar.h"
 #include "../common/object.h"
+#include "../common/utils.h"
 
 #include <cx/mempool.h>
 
@@ -50,19 +52,31 @@ static int window_default_height = 550;
 static int splitview_window_default_pos = -1;
 static UiBool splitview_window_use_prop = TRUE;
 
+static void main_window_destroy(UiObject *obj) {
+    MainWindow *window = (__bridge MainWindow*)obj->wobj;
+    [window saveWindowSize];
+    [[WindowManager sharedWindowManager] closeWindow:window];
+}
+
 static UiObject* create_window(const char *title, BOOL simple, BOOL sidebar, BOOL splitview) {
+    ui_menu_init();
     UiObject *obj = uic_object_new_toplevel();
     
-    MainWindow *window = [[MainWindow alloc] init:obj withSidebar:sidebar withSplitview:splitview];
-    [[WindowManager sharedWindowManager] addWindow:window];
-    window.releasedWhenClosed = false; // TODO: we still need a cleanup strategy
+    int width = window_default_width;
+    int height = window_default_height;
+    if(!simple) {
+       ui_get_window_default_width(&width, &height);
+   }
+    
+    MainWindow *window = [[MainWindow alloc] init:obj withSidebar:sidebar withSplitview:splitview width:width height:height];
     
     obj->wobj = (__bridge void*)window;
+    obj->destroy = main_window_destroy;
     
     MainWindowController *controller = [[MainWindowController alloc] initWithWindow:obj window:window];
     window.windowController = controller;
     [window setNextResponder:(NSResponder*)controller];
-    objc_setAssociatedObject(window, "windowcontroller", controller, OBJC_ASSOCIATION_RETAIN);
+    [[WindowManager sharedWindowManager] addWindow:controller];
     
     return obj;
 }
@@ -96,6 +110,35 @@ void ui_window_default_size(int width, int height) {
     window_default_height = height;
 }
 
+/* ------------------------------- SplitView Window-------------------------------- */
+
+void ui_splitview_window_set_pos(UiObject *obj, int pos) {
+    MainWindow *window = (__bridge MainWindow*)obj->wobj;
+    int divider = window.sidebar != nil ? 1 : 0;
+    [window.splitview setPosition:pos ofDividerAtIndex:divider];
+}
+
+int ui_splitview_window_get_pos(UiObject *obj) {
+    MainWindow *window = (__bridge MainWindow*)obj->wobj;
+    int divider = window.sidebar != nil ? 1 : 0;
+    return window.splitview.subviews[divider].frame.size.width;
+}
+
+void ui_splitview_window_set_default_pos(int pos) {
+    splitview_window_default_pos = pos;
+}
+
+void ui_splitview_window_use_property(UiBool enable) {
+    splitview_window_use_prop = enable;
+}
+
+void ui_splitview_window_set_visible(UiObject *obj, int pane, UiBool visible) {
+    MainWindow *window = (__bridge MainWindow*)obj->wobj;
+    if(pane >= 0 && pane < 2) {
+        window.splitview.subviews[pane].hidden = visible;
+    }
+}
+
 /* --------------------------------- File Dialogs --------------------------------- */
 
 void ui_openfiledialog(UiObject *obj, unsigned int mode, ui_callback file_selected_callback, void *cbdata) {
@@ -281,13 +324,15 @@ UiObject *ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
                                                              NSWindowStyleMaskUtilityWindow)
                                                    backing:NSBackingStoreBuffered
                                                      defer:NO];
+    NSWindowController *controller = [[NSWindowController alloc] initWithWindow:panel];
+    panel.windowController = controller;
     panel.parent = (__bridge NSWindow*)parent->wobj;
     panel.obj = obj;
     panel.modal = args->modal;
     panel.onclick = args->onclick;
     panel.onclickdata = args->onclickdata;
     [panel center];
-    [[WindowManager sharedWindowManager] addWindow:panel];
+    [[WindowManager sharedWindowManager] addWindow:controller];
     obj->wobj = (__bridge void*)panel;
     
     NSView *content = panel.contentView;
@@ -314,7 +359,7 @@ UiObject *ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
             [lbutton1.leadingAnchor constraintEqualToAnchor:buttonArea.leadingAnchor constant:0]
         ]];
         
-        EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata];
+        EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata action:nil];
         event.obj = obj;
         event.value = 1;
         lbutton1.target = event;
@@ -334,7 +379,7 @@ UiObject *ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
             [lbutton2.leadingAnchor constraintEqualToAnchor:anchor constant:off]
         ]];
         
-        EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata];
+        EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata action:nil];
         event.obj = obj;
         event.value = 2;
         lbutton2.target = event;
@@ -353,7 +398,7 @@ UiObject *ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
             [rbutton4.trailingAnchor constraintEqualToAnchor:buttonArea.trailingAnchor constant:0]
         ]];
         
-        EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata];
+        EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata action:nil];
         event.obj = obj;
         event.value = 2;
         rbutton4.target = event;
@@ -373,7 +418,7 @@ UiObject *ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
             [rbutton3.trailingAnchor constraintEqualToAnchor:anchor constant:off]
         ]];
         
-        EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata];
+        EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata action:nil];
         event.obj = obj;
         event.value = 2;
         rbutton3.target = event;
@@ -423,7 +468,7 @@ UiObject *ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
         [vbox.bottomAnchor constraintEqualToAnchor:buttonArea.topAnchor constant:0]
     ]];
      
-    UiContainerX *container = ui_create_container(obj, vbox);
+    UiContainer *container = ui_create_container(obj, vbox);
     vbox.container = container;
     uic_object_push_container(obj, container);
     
diff --git a/ui/common/Makefile b/ui/common/Makefile
new file mode 100644 (file)
index 0000000..703da14
--- /dev/null
@@ -0,0 +1,111 @@
+#
+# 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.
+#
+
+FORCE:
+
+$(COMMON_OBJPRE)uic_action$(OBJ_EXT): common/action.c common/action.h \
+ common/../ui/toolkit.h common/context.h common/object.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(COMMON_OBJPRE)uic_app$(OBJ_EXT): common/app.c common/app.h \
+ common/../ui/toolkit.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(COMMON_OBJPRE)uic_args$(OBJ_EXT): common/args.c common/args.h \
+ common/../ui/window.h common/../ui/toolkit.h common/../ui/container.h \
+ common/../ui/display.h common/../ui/button.h common/../ui/entry.h \
+ common/../ui/menu.h common/../ui/toolbar.h common/../ui/list.h \
+ common/../ui/text.h common/../ui/webview.h common/../ui/widget.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(COMMON_OBJPRE)uic_condvar$(OBJ_EXT): common/condvar.c common/condvar.h \
+ common/../ui/toolkit.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(COMMON_OBJPRE)uic_container$(OBJ_EXT): common/container.c \
+ common/container.h common/../ui/container.h common/../ui/toolkit.h \
+ common/object.h common/../ui/toolkit.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(COMMON_OBJPRE)uic_context$(OBJ_EXT): common/context.c common/context.h \
+ common/../ui/toolkit.h common/action.h common/../ui/window.h \
+ common/../ui/toolkit.h common/../ui/widget.h common/document.h \
+ common/types.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(COMMON_OBJPRE)uic_document$(OBJ_EXT): common/document.c \
+ common/document.h common/../ui/toolkit.h common/context.h \
+ common/action.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(COMMON_OBJPRE)uic_icons$(OBJ_EXT): common/icons.c common/icons.h \
+ common/../ui/icons.h common/../ui/toolkit.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(COMMON_OBJPRE)uic_menu$(OBJ_EXT): common/menu.c common/menu.h \
+ common/../ui/menu.h common/../ui/toolkit.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(COMMON_OBJPRE)uic_message$(OBJ_EXT): common/message.c common/message.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(COMMON_OBJPRE)uic_object$(OBJ_EXT): common/object.c common/object.h \
+ common/../ui/toolkit.h common/context.h common/action.h \
+ common/../ui/container.h common/../ui/toolkit.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(COMMON_OBJPRE)uic_properties$(OBJ_EXT): common/properties.c \
+ common/../ui/toolkit.h common/properties.h common/../ui/properties.h \
+ common/../ui/toolkit.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(COMMON_OBJPRE)uic_threadpool$(OBJ_EXT): common/threadpool.c \
+ common/threadpool.h common/../ui/toolkit.h common/context.h \
+ common/action.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(COMMON_OBJPRE)uic_toolbar$(OBJ_EXT): common/toolbar.c common/toolbar.h \
+ common/../ui/toolbar.h common/../ui/toolkit.h common/menu.h \
+ common/../ui/menu.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(COMMON_OBJPRE)uic_types$(OBJ_EXT): common/types.c common/../ui/list.h \
+ common/../ui/toolkit.h common/types.h common/../ui/toolkit.h \
+ common/context.h common/action.h common/../ui/image.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(COMMON_OBJPRE)uic_utils$(OBJ_EXT): common/utils.c common/utils.h \
+ common/../ui/toolkit.h common/../ui/text.h common/../ui/toolkit.h \
+ common/properties.h common/../ui/properties.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(COMMON_OBJPRE)uic_wrapper$(OBJ_EXT): common/wrapper.c common/wrapper.h \
+ common/../ui/toolkit.h common/../ui/list.h common/../ui/toolkit.h \
+ common/../ui/text.h common/types.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
diff --git a/ui/common/action.c b/ui/common/action.c
new file mode 100644 (file)
index 0000000..683ed37
--- /dev/null
@@ -0,0 +1,288 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2026 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "action.h"
+#include "context.h"
+#include "object.h"
+
+#include <cx/string.h>
+
+void uic_add_action(
+        UiContext *ctx,
+        const char *name,
+        ui_callback callback,
+        void *userdata,
+        const char *accelerator,
+        const char *accelerator_text)
+{
+    if(!name) {
+        return;
+    }
+    
+    UiAction action;
+    action.name = ui_strdup(ctx, name);
+    action.callback = callback;
+    action.userdata = userdata;
+    action.accelerator = accelerator ? ui_strdup(ctx, accelerator) : NULL;
+    action.accelerator_text = accelerator_text ? ui_strdup(ctx, accelerator_text) : NULL;
+    action.ctx = ctx;
+    cxMapPut(ctx->actions, name, &action);
+    cxMapRehash(ctx->actions);
+}
+
+void uic_bind_action(
+        UiContext *ctx,
+        const char *action,
+        void *bind_obj,
+        ui_enablefunc set_enabled)
+{
+    if(!action) {
+        return;
+    }
+    
+    UiActionBinding binding;
+    binding.action = ui_strdup(ctx, action);
+    binding.userdata = bind_obj;
+    binding.set_enabled = set_enabled;
+    cxListAdd(ctx->action_bindings, &binding);
+}
+
+UiAction* uic_resolve_action(UiContext *ctx, const char *action) {
+    UiAction *a = NULL;
+    if(ctx->actions) {
+        a = cxMapGet(ctx->actions, action);
+    }
+    // check if any sub-document defines this action
+    // sub-document actions have precedence, the most specific action will
+    // be returned
+    CxIterator i = cxListIterator(ctx->documents);
+    cx_foreach(void *, doc, i) {
+        UiContext *doc_ctx = ui_document_context(doc);
+        UiAction *sub_action = uic_resolve_action(doc_ctx, action);
+        if(sub_action) {
+            a = sub_action;
+            // if one sub-tree has an action, we don't care about other
+            // subtrees
+            break;
+        }
+    }
+    
+    if(!a && ctx->parent) {
+        // check parents
+        a = uic_resolve_action_from_parents(ctx, action);
+    }
+    
+    return a;
+}
+
+UiAction* uic_resolve_action_from_parents(UiContext *ctx, const char *action) {
+    UiContext *parent = ctx->parent;
+    if(parent == NULL) {
+        return NULL;
+    }
+    if(parent->actions) {
+        UiAction *a = cxMapGet(parent->actions, action);
+        if(a) {
+            return a;
+        }
+    }
+    return uic_resolve_action_from_parents(parent, action);
+}
+
+
+
+void ui_update_action_bindings(UiContext *ctx) {
+    CxIterator i = cxListIterator(ctx->action_bindings);
+    cx_foreach(UiActionBinding*, binding, i) {
+        UiAction *action = uic_resolve_action(ctx, binding->action);
+        if(binding->set_enabled) {
+            binding->set_enabled(binding->userdata, action != NULL);
+        }
+    }
+}
+
+void uic_action_callback(UiEvent *event, const char *action_name) {
+    UiContext *ctx = ui_global_context();
+    if(event->obj) {
+        ctx = event->obj->ctx;
+    }
+    
+    UiAction *action = uic_resolve_action(ctx, action_name);
+    if(action) {
+        // override event document: for actions we know that the event is
+        // for a specific document
+        event->document = action->ctx->self_doc;
+        if(action->callback) {
+            action->callback(event, action->userdata);
+        }
+    }
+}
+
+static int call_action(UiContext *ctx, const char *action_name, void *eventdata, UiEventType eventdatatype, int intval) {
+    UiAction *action = uic_resolve_action(ctx, action_name);
+    if(action && action->callback) {
+        UiEvent event;
+        memset(&event, 0, sizeof(UiEvent));
+        event.obj = ctx->obj;
+        event.window = event.obj ? event.obj->window : NULL;
+        event.document = ctx->self_doc ? ctx->self_doc : ctx->document;
+        if(eventdata) {
+            event.eventdata = eventdata;
+            event.eventdatatype = eventdatatype;
+        }
+        event.intval = intval;
+        action->callback(&event, action->userdata);
+        return 1;
+    } else {
+        return 0;
+    }
+}
+
+int ui_call_action(UiContext *ctx, const char *action_name) {
+    return ui_call_action2(ctx, action_name, NULL, 0);
+}
+
+int ui_call_action2(UiContext *ctx, const char *action_name, void *eventdata, int intval) {
+    return call_action(ctx, action_name, eventdata, UI_EVENT_DATA_POINTER, intval);
+}
+
+int ui_call_action3(UiContext *ctx, const char *action_name, void *ptr, uint64_t type_id) {
+    UiTypedObj *obj = malloc(sizeof(UiTypedObj));
+    obj->ptr = ptr;
+    obj->type = type_id;
+    int ret = call_action(ctx, action_name, obj, UI_EVENT_DATA_TYPED_OBJECT, 0);
+    free(obj);
+    return ret;
+}
+
+static void call_action_recursive(const char *action_name, UiContext *ctx, void *eventdata, UiEventType eventdatatype, int intval, UiBool call_children) {
+    UiEvent event;
+    memset(&event, 0, sizeof(UiEvent));
+    event.obj = ctx->obj;
+    event.window = event.obj ? event.obj->window : NULL;
+    event.document = ctx->self_doc ? ctx->self_doc : ctx->document;
+    if(eventdata) {
+        event.eventdata = eventdata;
+        event.eventdatatype = eventdatatype;
+    }
+    event.intval = intval;
+    
+    UiAction *a = NULL;
+    if(ctx->actions) {
+        a = cxMapGet(ctx->actions, action_name);
+    }
+    if(a && a->callback) {
+        a->callback(&event, a->userdata);
+    }
+    
+    if(call_children) {
+        CxIterator i = cxListIterator(ctx->documents);
+        cx_foreach(void *, doc, i) {
+            UiContext *doc_ctx = ui_document_context(doc);
+            call_action_recursive(action_name, doc_ctx, eventdata, eventdatatype, intval, TRUE);
+        }
+    }
+}
+
+static void broadcast_action(const char *action_name, void *eventdata, UiEventType eventdatatype, int intval) {
+    CxList *objects = uic_object_list();
+    CxIterator i = cxListIterator(objects);
+    cx_foreach(UiObject*, obj, i) {
+        call_action_recursive(action_name, obj->ctx, eventdata, eventdatatype, intval, TRUE);
+    }
+    
+    call_action_recursive(action_name, ui_global_context(), eventdata, eventdatatype, intval, FALSE);
+}
+
+void ui_broadcast_action(const char *action_name) {
+    broadcast_action(action_name, NULL, UI_EVENT_DATA_NULL, 0);
+}
+
+void ui_broadcast_action2(const char *action_name, void *eventdata, int intval) {
+    broadcast_action(action_name, eventdata, UI_EVENT_DATA_POINTER, intval);
+}
+
+void ui_call_action_on(UiContext *ctx, const char *action) {
+    UiEvent event;
+    memset(&event, 0, sizeof(UiEvent));
+    event.obj = ctx->obj;
+    event.window = event.obj ? event.obj->window : NULL;
+    event.document = ctx->self_doc ? ctx->self_doc : ctx->document;
+    
+    UiAction *a = NULL;
+    if(ctx->actions) {
+        a = cxMapGet(ctx->actions, action);
+    }
+    if(a && a->callback) {
+        a->callback(&event, a->userdata);
+    }
+}
+
+typedef struct UiActionBroadcast {
+    char *action;
+    void *eventdata;
+    UiEventType eventdatataype;
+    int intval;
+} UiActionBroadcast;
+
+void ui_mainthread_broadcast(const char *action_name) {
+    ui_mainthread_broadcast2(action_name, NULL, 0);
+}
+
+static int mainthread_action_broadcast(void *data) {
+    UiActionBroadcast *broadcast = data;
+    broadcast_action(broadcast->action, broadcast->eventdata, broadcast->eventdatataype, broadcast->intval);
+    if(broadcast->eventdatataype == UI_EVENT_DATA_TYPED_OBJECT) {
+        free(broadcast->eventdata);
+    }
+    free(broadcast->action);
+    free(broadcast);
+    return 0;
+}
+
+void ui_mainthread_broadcast2(const char *action_name, void *eventdata, int intval) {
+    UiActionBroadcast *broadcast = malloc(sizeof(UiActionBroadcast));
+    broadcast->action = strdup(action_name);
+    broadcast->eventdata = eventdata;
+    broadcast->eventdatataype = UI_EVENT_DATA_POINTER;
+    broadcast->intval = intval;
+    ui_call_mainthread(mainthread_action_broadcast, broadcast);
+}
+
+void ui_mainthread_broadcast3(const char *action_name, void *ptr, uint64_t type_id) {
+    UiTypedObj *obj = malloc(sizeof(UiTypedObj));
+    obj->ptr = ptr;
+    obj->type = type_id;
+    
+    UiActionBroadcast *broadcast = malloc(sizeof(UiActionBroadcast));
+    broadcast->action = strdup(action_name);
+    broadcast->eventdata = obj;
+    broadcast->eventdatataype = UI_EVENT_DATA_TYPED_OBJECT;
+    broadcast->intval = 0;
+    ui_call_mainthread(mainthread_action_broadcast, broadcast);
+}
diff --git a/ui/common/action.h b/ui/common/action.h
new file mode 100644 (file)
index 0000000..1364635
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2026 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef UIC_ACTION_H
+#define UIC_ACTION_H
+
+#include "../ui/toolkit.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct UiAction        UiAction;
+typedef struct UiActionBinding UiActionBinding;
+
+struct UiAction {
+    char *name;
+    char *accelerator;
+    char *accelerator_text;
+    ui_callback callback;
+    void *userdata;
+    UiContext *ctx;
+};
+
+struct UiActionBinding {
+    const char *action;
+    ui_enablefunc set_enabled;
+    void *userdata;
+};
+
+void uic_add_action(
+        UiContext *ctx,
+        const char *name,
+        ui_callback callback,
+        void *userdata,
+        const char *accelerator,
+        const char *accelerator_text);
+
+void uic_bind_action(
+        UiContext *ctx,
+        const char *action,
+        void *bind_obj,
+        ui_enablefunc set_enabled);
+
+UiAction* uic_resolve_action(UiContext *ctx, const char *action);
+UiAction* uic_resolve_action_from_parents(UiContext *ctx, const char *action);
+
+// action event wrapper
+void uic_action_callback(UiEvent *event, const char *action_name);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UIC_ACTION_H */
+
index 9674599fdd794e92a54da6e8405ef0a70425d078..c7f80decaa2438a7c40533e382c8f0697036e81c 100644 (file)
@@ -30,6 +30,8 @@
 
 static ui_callback   startup_func;
 static void          *startup_data;
+static ui_callback   newwindow_func;
+static void          *newwindow_data;
 static ui_callback   open_func;
 void                 *open_data;
 static ui_callback   exit_func;
@@ -41,6 +43,11 @@ void ui_onstartup(ui_callback f, void *userdata) {
     startup_data = userdata;
 }
 
+void ui_onnewwindow(ui_callback f, void *userdata) {
+    newwindow_func = f;
+    newwindow_data = userdata;
+}
+
 void ui_onopen(ui_callback f, void *userdata) {
     open_func = f;
     open_data = userdata;
@@ -51,13 +58,18 @@ void ui_onexit(ui_callback f, void *userdata) {
     exit_data = userdata;
 }
 
-
 void uic_application_startup(UiEvent *event) {
     if(startup_func) {
         startup_func(event, startup_data);
     }
 }
 
+void uic_application_newwindow(UiEvent *event) {
+    if(newwindow_func) {
+        newwindow_func(event, newwindow_data);
+    }
+}
+
 void uic_application_open(UiEvent *event) {
     if(open_func) {
         open_func(event, open_data);
@@ -69,3 +81,7 @@ void uic_application_exit(UiEvent *event) {
         exit_func(event, exit_data);
     }
 }
+
+void ui_newwindow(void) {
+    uic_application_newwindow(NULL);
+}
index 02356a916e5fcc3e96d85b51e59bff838a32555b..9176e85f8f99e2466e9c8a068835cf41accea6d8 100644 (file)
@@ -36,6 +36,7 @@ extern "C" {
 #endif
 
 void uic_application_startup(UiEvent *event);
+void uic_application_newwindow(UiEvent *event);
 void uic_application_open(UiEvent *event);
 void uic_application_exit(UiEvent *event);
 
index 0ec8a4e5c9d1d19d9245ddc2e0b3acf038756d0c..8c1e2b4027c13f9dbee4d61c17a0ae8493c64681 100644 (file)
@@ -215,9 +215,14 @@ void ui_menuitem_args_set_onclickdata(UiMenuItemArgs *args, void *onclickdata) {
     args->onclickdata = onclickdata;
 }
 
+void ui_menuitem_args_set_action(UiMenuItemArgs *args, const char *action) {
+    args->action = strdup(action);
+}
+
 void ui_menuitem_args_free(UiMenuItemArgs *args) {
     free((void*)args->label);
     free((void*)args->icon);
+    free((void*)args->action);
     free(args);
 }
 
@@ -250,10 +255,15 @@ void ui_menutoggleitem_args_set_onchangedata(UiMenuToggleItemArgs *args, void *o
     args->onchangedata = onclickdata;
 }
 
+void ui_menutoggleitem_args_set_action(UiMenuToggleItemArgs *args, const char *action) {
+    args->action = strdup(action);
+}
+
 void ui_menutoggleitem_args_free(UiMenuToggleItemArgs *args) {
     free((void*)args->label);
     free((void*)args->icon);
     free((void*)args->varname);
+    free((void*)args->action);
     free(args);
 }
 
@@ -273,6 +283,14 @@ void ui_menuitemlist_args_set_getvalue(UiMenuItemListArgs *args, ui_getvaluefunc
     args->getvalue = func;
 }
 
+void ui_menuitemlist_args_set_getvalue2(UiMenuItemListArgs *args, ui_getvaluefunc2 func) {
+    args->getvalue2 = func;
+}
+
+void ui_menuitemlist_args_set_getvaluedata(UiMenuItemListArgs *args, void *data) {
+    args->getvaluedata = data;
+}
+
 void ui_menuitemlist_args_set_onselect(UiMenuItemListArgs *args, ui_callback callback) {
     args->onselect = callback;
 }
@@ -310,6 +328,10 @@ void ui_toolbar_item_args_set_tooltip(UiToolbarItemArgs *args, const char *toolt
     args->tooltip = strdup(tooltip);
 }
 
+void ui_toolbar_item_args_set_action(UiToolbarItemArgs *args, const char *action) {
+    args->action = strdup(action);
+}
+
 void ui_toolbar_item_args_set_onclick(UiToolbarItemArgs *args, ui_callback callback) {
     args->onclick = callback;
 }
@@ -327,6 +349,7 @@ void ui_toolbar_item_args_free(UiToolbarItemArgs *args) {
     free((void*)args->label);
     free((void*)args->icon);
     free((void*)args->tooltip);
+    free((void*)args->action);
     free((void*)args->states);
     free(args);
 }
@@ -355,6 +378,10 @@ void ui_toolbar_toggleitem_args_set_varname(UiToolbarToggleItemArgs *args, const
     args->varname = strdup(varname);
 }
 
+void ui_toolbar_toggleitem_args_set_action(UiToolbarToggleItemArgs *args, const char *action) {
+    args->action = strdup(action);
+}
+
 void ui_toolbar_toggleitem_args_set_onchange(UiToolbarToggleItemArgs *args, ui_callback callback) {
     args->onchange = callback;
 }
@@ -374,6 +401,82 @@ void ui_toolbar_toggleitem_args_free(UiToolbarToggleItemArgs *args) {
     free((void*)args->icon);
     free((void*)args->tooltip);
     free((void*)args->varname);
+    free((void*)args->action);
+    free((void*)args->states);
+    free(args);
+}
+
+/* ---------------------------- UiToolbarContentToggleItemArgs ---------------------------- */
+
+UiToolbarContentToggleItemArgs* ui_toolbar_content_toggleitem_args_new(void) {
+    UiToolbarContentToggleItemArgs *args = malloc(sizeof(UiToolbarContentToggleItemArgs));
+    memset(args, 0, sizeof(UiToolbarContentToggleItemArgs));
+    return args;
+}
+
+void ui_toolbar_content_toggleitem_args_set_label0(UiToolbarContentToggleItemArgs *args, const char *label) {
+    args->label0 = strdup(label);
+}
+
+void ui_toolbar_content_toggleitem_args_set_icon0(UiToolbarContentToggleItemArgs *args, const char *icon) {
+    args->icon0 = strdup(icon);
+}
+
+void ui_toolbar_content_toggleitem_args_set_tooltip0(UiToolbarContentToggleItemArgs *args, const char *tooltip) {
+    args->tooltip0 = strdup(tooltip);
+}
+
+void ui_toolbar_content_toggleitem_args_set_label1(UiToolbarContentToggleItemArgs *args, const char *label) {
+    args->label1 = strdup(label);
+}
+
+void ui_toolbar_content_toggleitem_args_set_icon1(UiToolbarContentToggleItemArgs *args, const char *icon) {
+    args->icon1 = strdup(icon);
+}
+
+void ui_toolbar_content_toggleitem_args_set_tooltip1(UiToolbarContentToggleItemArgs *args, const char *tooltip) {
+    args->tooltip1 = strdup(tooltip);
+}
+
+void ui_toolbar_content_toggleitem_args_set_varname(UiToolbarContentToggleItemArgs *args, const char *varname) {
+    args->varname = strdup(varname);
+}
+
+void ui_toolbar_content_toggleitem_args_set_action(UiToolbarContentToggleItemArgs *args, const char *action) {
+    args->action = strdup(action);
+}
+
+void ui_toolbar_content_toggleitem_args_set_onchange(UiToolbarContentToggleItemArgs *args, ui_callback callback) {
+    args->onchange = callback;
+}
+
+void ui_toolbar_content_toggleitem_args_set_onchangedata(UiToolbarContentToggleItemArgs *args, void *onchangedata) {
+    args->onchangedata = onchangedata;
+}
+
+void ui_toolbar_content_toggleitem_args_set_istogglebutton(UiToolbarContentToggleItemArgs *args, UiBool value) {
+    args->istogglebutton = value;
+}
+
+void ui_toolbar_content_toggleitem_args_set_toggled_by_state(UiToolbarContentToggleItemArgs *args, int state) {
+    args->toggled_by_state = state;
+}
+
+void ui_toolbar_content_toggleitem_args_set_states(UiToolbarContentToggleItemArgs *args,int *states, int numstates) {
+    args->states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->states, states, numstates * sizeof(int));
+    ((int*)args->states)[numstates] = -1;
+}
+
+void ui_toolbar_content_toggleitem_args_free(UiToolbarContentToggleItemArgs *args) {
+    free((void*)args->label0);
+    free((void*)args->icon0);
+    free((void*)args->tooltip0);
+    free((void*)args->label1);
+    free((void*)args->icon1);
+    free((void*)args->tooltip1);
+    free((void*)args->varname);
+    free((void*)args->action);
     free((void*)args->states);
     free(args);
 }
@@ -519,10 +622,17 @@ void ui_container_args_set_rowspacing(UiContainerArgs *args, int value) {
     args->rowspacing = value;
 }
 
+void ui_container_args_set_visibility_states(UiContainerArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
 
 void ui_container_args_free(UiContainerArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
+    free((void*)args->visibility_states);
     free(args);
 }
 
@@ -637,10 +747,17 @@ void ui_frame_args_set_label(UiFrameArgs *args, const char *label) {
     args->label = strdup(label);
 }
 
+void ui_frame_args_set_visibility_states(UiFrameArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
 void ui_frame_args_free(UiFrameArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
     free((void*)args->label);
+    free((void*)args->visibility_states);
     free(args);
 }
 
@@ -797,11 +914,18 @@ void ui_splitpane_args_set_max_panes(UiSplitPaneArgs *args, int max) {
     args->max_panes = max;
 }
 
+void ui_splitpane_args_set_visibility_states(UiSplitPaneArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
 void ui_splitpane_args_free(UiSplitPaneArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
     free((void*)args->varname);
     free((void*)args->position_property);
+    free((void*)args->visibility_states);
     free(args);
 }
 
@@ -915,10 +1039,17 @@ void ui_tabview_args_set_subcontainer(UiTabViewArgs *args, UiSubContainerType su
     args->subcontainer = subcontainer;
 }
 
+void ui_tabview_args_set_visibility_states(UiTabViewArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
 void ui_tabview_args_free(UiTabViewArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
     free((void*)args->varname);
+    free((void*)args->visibility_states);
     free(args);
 }
 
@@ -1097,11 +1228,18 @@ void ui_label_args_set_value(UiLabelArgs *args, UiString *value) {
     args->value = value;
 }
 
+void ui_label_args_set_visibility_states(UiLabelArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
 void ui_label_args_free(UiLabelArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
     free((void*)args->label);
     free((void*)args->varname);
+    free((void*)args->visibility_states);
     free(args);
 }
 
@@ -1200,10 +1338,17 @@ void ui_progressbar_args_set_value(UiProgressbarArgs *args, UiDouble *value) {
     args->value = value;
 }
 
+void ui_progressbar_args_set_visibility_states(UiProgressbarArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
 void ui_progressbar_args_free(UiProgressbarArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
     free((void*)args->varname);
+    free((void*)args->visibility_states);
     free(args);
 }
 
@@ -1284,10 +1429,17 @@ void ui_progress_spinner_args_set_value(UiProgressbarSpinnerArgs *args, UiIntege
     args->value = value;
 }
 
+void ui_progress_spinner_args_set_visibility_states(UiProgressbarSpinnerArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
 void ui_progress_spinner_args_free(UiProgressbarSpinnerArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
     free((void*)args->varname);
+    free((void*)args->visibility_states);
     free(args);
 }
 
@@ -1391,19 +1543,31 @@ void ui_button_args_set_onclickdata(UiButtonArgs *args, void *onclickdata){
     args->onclickdata = onclickdata;
 }
 
+void ui_button_args_set_action(UiButtonArgs *args, const char *action) {
+    args->action = strdup(action);
+}
+
 void ui_button_args_set_states(UiButtonArgs *args, int *states, int numstates) {
     args->states = calloc(numstates+1, sizeof(int));
     memcpy((void*)args->states, states, numstates * sizeof(int));
     ((int*)args->states)[numstates] = -1;
 }
 
+void ui_button_args_set_visibility_states(UiButtonArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
 void ui_button_args_free(UiButtonArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
     free((void*)args->label);
     free((void*)args->icon);
     free((void*)args->tooltip);
+    free((void*)args->action);
     free((void*)args->states);
+    free((void*)args->visibility_states);
     free(args);
 }
 
@@ -1502,6 +1666,10 @@ void ui_toggle_args_set_onchangedata(UiToggleArgs *args, void *onchangedata){
     args->onchangedata = onchangedata;
 }
 
+void ui_toggle_args_set_action(UiToggleArgs *args, const char *action) {
+    args->action = strdup(action);
+}
+
 void ui_toggle_args_set_varname(UiToggleArgs *args, const char *varname) {
     args->varname = strdup(varname);
 }
@@ -1520,6 +1688,12 @@ void ui_toggle_args_set_states(UiToggleArgs *args, int *states, int numstates) {
     ((int*)args->states)[numstates] = -1;
 }
 
+void ui_toggle_args_set_visibility_states(UiToggleArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
 void ui_toggle_args_free(UiToggleArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
@@ -1527,7 +1701,167 @@ void ui_toggle_args_free(UiToggleArgs *args) {
     free((void*)args->icon);
     free((void*)args->tooltip);
     free((void*)args->varname);
+    free((void*)args->action);
     free((void*)args->states);
+    free((void*)args->visibility_states);
+    free(args);
+}
+
+/* ------------------------- UiContentToggleArgs ----------------------------*/
+
+
+UiContentToggleArgs* ui_content_toggle_args_new(void) {
+    UiContentToggleArgs *args = malloc(sizeof(UiContentToggleArgs));
+    memset(args, 0, sizeof(UiContentToggleArgs));
+    return args;
+}
+
+void ui_content_toggle_args_set_fill(UiContentToggleArgs *args, UiBool fill) {
+    args->fill = fill;
+}
+
+void ui_content_toggle_args_set_hexpand(UiContentToggleArgs *args, UiBool value) {
+    args->hexpand = value;
+}
+
+void ui_content_toggle_args_set_vexpand(UiContentToggleArgs *args, UiBool value) {
+    args->vexpand = value;
+}
+
+void ui_content_toggle_args_set_hfill(UiContentToggleArgs *args, UiBool value) {
+    args->hfill = value;
+}
+
+void ui_content_toggle_args_set_vfill(UiContentToggleArgs *args, UiBool value) {
+    args->vfill = value;
+}
+
+void ui_content_toggle_args_set_override_defaults(UiContentToggleArgs *args, UiBool value) {
+    args->override_defaults = value;
+}
+
+void ui_content_toggle_args_set_margin(UiContentToggleArgs *args, int value) {
+    args->margin = value;
+}
+
+void ui_content_toggle_args_set_margin_left(UiContentToggleArgs *args, int value) {
+    args->margin_left = value;
+}
+
+void ui_content_toggle_args_set_margin_right(UiContentToggleArgs *args, int value) {
+    args->margin_right = value;
+}
+
+void ui_content_toggle_args_set_margin_top(UiContentToggleArgs *args, int value) {
+    args->margin_top = value;
+}
+
+void ui_content_toggle_args_set_margin_bottom(UiContentToggleArgs *args, int value) {
+    args->margin_bottom = value;
+}
+
+void ui_content_toggle_args_set_colspan(UiContentToggleArgs *args, int colspan) {
+    args->colspan = colspan;
+}
+
+void ui_content_toggle_args_set_rowspan(UiContentToggleArgs *args, int rowspan) {
+    args->rowspan = rowspan;
+}
+
+
+void ui_content_toggle_args_set_name(UiContentToggleArgs *args, const char *name) {
+    args->name = strdup(name);
+}
+
+void ui_content_toggle_args_set_style_class(UiContentToggleArgs *args, const char *classname) {
+    args->style_class = strdup(classname);
+}
+
+void ui_content_toggle_args_set_label0(UiContentToggleArgs *args, const char *label){
+    args->label0 = strdup(label);
+}
+
+void ui_content_toggle_args_set_icon0(UiContentToggleArgs *args, const char *icon){
+    args->icon0 = strdup(icon);
+}
+
+void ui_content_toggle_args_set_tooltip0(UiContentToggleArgs *args, const char *tooltip) {
+    args->tooltip0 = strdup(tooltip);
+}
+
+void ui_content_toggle_args_set_label1(UiContentToggleArgs *args, const char *label){
+    args->label1 = strdup(label);
+}
+
+void ui_content_toggle_args_set_icon1(UiContentToggleArgs *args, const char *icon){
+    args->icon1 = strdup(icon);
+}
+
+void ui_content_toggle_args_set_tooltip1(UiContentToggleArgs *args, const char *tooltip) {
+    args->tooltip1 = strdup(tooltip);
+}
+
+void ui_content_toggle_args_set_labeltype(UiContentToggleArgs *args, int labeltype){
+    args->labeltype = labeltype;
+}
+
+void ui_content_toggle_args_set_onchange(UiContentToggleArgs *args, ui_callback callback){
+    args->onchange = callback;
+}
+
+void ui_content_toggle_args_set_onchangedata(UiContentToggleArgs *args, void *onchangedata){
+    args->onchangedata = onchangedata;
+}
+
+void ui_content_toggle_args_set_action(UiContentToggleArgs *args, const char *action) {
+    args->action = strdup(action);
+}
+
+void ui_content_toggle_args_set_varname(UiContentToggleArgs *args, const char *varname) {
+    args->varname = strdup(varname);
+}
+
+void ui_content_toggle_args_set_value(UiContentToggleArgs *args, UiInteger *value) {
+    args->value = value;
+}
+
+void ui_content_toggle_args_set_toggled_by_state(UiContentToggleArgs *args, int state) {
+    args->toggled_by_state = state;
+}
+
+void ui_content_toggle_args_set_istogglebutton(UiContentToggleArgs *args, UiBool value) {
+    args->istogglebutton = value;
+}
+
+void ui_content_toggle_args_set_enablestate(UiContentToggleArgs *args, int state) {
+    args->enable_state = state;
+}
+
+void ui_content_toggle_args_set_states(UiContentToggleArgs *args, int *states, int numstates) {
+    args->states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->states, states, numstates * sizeof(int));
+    ((int*)args->states)[numstates] = -1;
+}
+
+void ui_content_toggle_args_set_visibility_states(UiContentToggleArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
+void ui_content_toggle_args_free(UiContentToggleArgs *args) {
+    free((void*)args->name);
+    free((void*)args->style_class);
+    free((void*)args->label0);
+    free((void*)args->icon0);
+    free((void*)args->tooltip0);
+    free((void*)args->label1);
+    free((void*)args->icon1);
+    free((void*)args->tooltip1);
+    free((void*)args->varname);
+    free((void*)args->action);
+    free((void*)args->states);
+    free((void*)args->visibility_states);
     free(args);
 }
 
@@ -1625,6 +1959,10 @@ void ui_linkbutton_args_set_onclickdata(UiLinkButtonArgs *args, void *userdata)
     args->onclickdata = userdata;
 }
 
+void ui_linkbutton_args_set_action(UiLinkButtonArgs *args, const char *action) {
+    args->action = strdup(action);
+}
+
 void ui_linkbutton_args_set_nofollow(UiLinkButtonArgs *args, UiBool value) {
     args->nofollow = value;
 }
@@ -1647,11 +1985,18 @@ void ui_linkbutton_args_set_states(UiLinkButtonArgs *args, int *states, int nums
     ((int*)args->states)[numstates] = -1;
 }
 
+void ui_linkbutton_args_set_visibility_states(UiLinkButtonArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
 void ui_linkbutton_args_free(UiLinkButtonArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
     free((void*)args->label);
     free((void*)args->uri);
+    free((void*)args->action);
     free((void*)args->varname);
     free((void*)args->states);
     free(args);
@@ -1775,6 +2120,10 @@ void ui_list_args_set_onactivatedata(UiListArgs *args, void *userdata) {
     args->onactivatedata = userdata;
 }
 
+void ui_list_args_set_onactivate_action(UiListArgs *args, const char *action) {
+    args->onactivate_action = strdup(action);
+}
+
 void ui_list_args_set_onselection(UiListArgs *args, ui_callback callback) {
     args->onselection = callback;
 }
@@ -1783,6 +2132,10 @@ void ui_list_args_set_onselectiondata(UiListArgs *args, void *userdata) {
     args->onselectiondata = userdata;
 }
 
+void ui_list_args_set_onselection_action(UiListArgs *args, const char *action) {
+    args->onselection_action = strdup(action);
+}
+
 void ui_list_args_set_ondragstart(UiListArgs *args, ui_callback callback) {
     args->ondragstart = callback;
 }
@@ -1791,6 +2144,10 @@ void ui_list_args_set_ondragstartdata(UiListArgs *args, void *userdata) {
     args->ondragstartdata = userdata;
 }
 
+void ui_list_args_set_ondragstart_action(UiListArgs *args, const char *action) {
+    args->ondragstart_action = strdup(action);
+}
+
 void ui_list_args_set_ondragcomplete(UiListArgs *args, ui_callback callback) {
     args->ondragcomplete = callback;
 }
@@ -1799,6 +2156,10 @@ void ui_list_args_set_ondragcompletedata(UiListArgs *args, void *userdata) {
     args->ondragcompletedata = userdata;
 }
 
+void ui_list_args_set_ondragcomplete_action(UiListArgs *args, const char *action) {
+    args->ondragcomplete_action = strdup(action);
+}
+
 void ui_list_args_set_ondrop(UiListArgs *args, ui_callback callback) {
     args->ondrop = callback;
 }
@@ -1807,6 +2168,10 @@ void ui_list_args_set_ondropdata(UiListArgs *args, void *userdata) {
     args->ondropdata = userdata;
 }
 
+void ui_list_args_set_ondrop_action(UiListArgs *args, const char *action) {
+    args->ondrop_action = strdup(action);
+}
+
 void ui_list_args_set_onsave(UiListArgs *args, ui_list_savefunc onsave) {
     args->onsave = onsave;
 }
@@ -1829,10 +2194,21 @@ void ui_list_args_set_states(UiListArgs *args, int *states, int numstates) {
     ((int*)args->states)[numstates] = -1;
 }
 
+void ui_list_args_set_visibility_states(UiListArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
 void ui_list_args_free(UiListArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
     free((void*)args->varname);
+    free((void*)args->onactivate_action);
+    free((void*)args->onselection_action);
+    free((void*)args->ondragstart_action);
+    free((void*)args->ondragcomplete_action);
+    free((void*)args->ondrop_action);
     if(args->static_elements) {
         for(int i=0;i<args->static_nelm;i++) {
             free(args->static_elements[i]);
@@ -1840,6 +2216,7 @@ void ui_list_args_free(UiListArgs *args) {
         free(args->static_elements);
     }
     free((void*)args->states);
+    free((void*)args->visibility_states);
     free(args);
 }
 
@@ -1961,7 +2338,6 @@ void ui_sourcelist_args_set_onbuttonclick(UiSourceListArgs *args, ui_callback ca
     
 }
 
-
 void ui_sourcelist_args_set_onbuttonclickdata(UiSourceListArgs *args, void *userdata) {
     args->onbuttonclickdata = userdata;
 }
@@ -1974,12 +2350,25 @@ void ui_sourcelist_args_set_header_is_item(UiSourceListArgs *args, UiBool value)
     args->header_is_item = value;
 }
 
+UIEXPORT void ui_sourcelist_args_set_states(UiSourceListArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->states, states, numstates * sizeof(int));
+    ((int*)args->states)[numstates] = -1;
+}
+
+void ui_sourcelist_args_set_visibility_states(UiSourceListArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
 void ui_sourcelist_args_free(UiSourceListArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
     free((void*)args->varname);
     free((void*)args->sublists);
     free((void*)args->states);
+    free((void*)args->visibility_states);
     free(args);
 }
 
@@ -2071,6 +2460,22 @@ void ui_textarea_args_set_onchangedata(UiTextAreaArgs *args, void *onchangedata)
     args->onchangedata = onchangedata;
 }
 
+void ui_textarea_args_set_onchange_action(UiTextAreaArgs *args, const char *action) {
+    args->onchange_action = strdup(action);
+}
+
+void ui_textarea_args_set_ontextchanged(UiTextAreaArgs *args, ui_callback callback) {
+    args->ontextchanged = callback;
+}
+
+void ui_textarea_args_set_ontextchangeddata(UiTextAreaArgs *args, void *onchangedata) {
+    args->ontextchangeddata = onchangedata;
+}
+
+void ui_textarea_args_set_ontextchanged_action(UiTextAreaArgs *args, const char *action) {
+    args->ontextchanged_action = strdup(action);
+}
+
 void ui_textarea_args_set_varname(UiTextAreaArgs *args, const char *varname) {
     args->varname = strdup(varname);
 }
@@ -2085,11 +2490,20 @@ void ui_textarea_args_set_states(UiTextAreaArgs *args, int *states, int numstate
     ((int*)args->states)[numstates] = -1;
 }
 
+void ui_textarea_args_set_visibility_states(UiTextAreaArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
 void ui_textarea_args_free(UiTextAreaArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
     free((void*)args->varname);
+    free((void*)args->onchange_action);
+    free((void*)args->ontextchanged_action);
     free((void*)args->states);
+    free((void*)args->visibility_states);
     free(args);
 }
 
@@ -2191,6 +2605,14 @@ void ui_textfield_args_set_onactivatedata(UiTextFieldArgs *args, void *onactivat
     args->onactivatedata = onactivatedata;
 }
 
+void ui_textfield_args_set_onactivate_action(UiTextFieldArgs *args, const char *action) {
+    args->onactivate_action = strdup(action);
+}
+
+void ui_textfield_args_set_onchange_action(UiTextFieldArgs *args, const char *action) {
+    args->onchange_action = action;
+}
+
 void ui_textfield_args_set_varname(UiTextFieldArgs *args, const char *varname) {
     args->varname = strdup(varname);
 }
@@ -2205,11 +2627,20 @@ void ui_textfield_args_set_states(UiTextFieldArgs *args, int *states, int numsta
     ((int*)args->states)[numstates] = -1;
 }
 
+void ui_textfield_args_set_visibility_states(UiTextFieldArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
 void ui_textfield_args_free(UiTextFieldArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
     free((void*)args->varname);
+    free((void*)args->onactivate_action);
+    free((void*)args->onchange_action);
     free((void*)args->states);
+    free((void*)args->visibility_states);
     free(args);
 }
 
@@ -2328,11 +2759,18 @@ void ui_spinbox_args_set_states(UiSpinBoxArgs *args, int *states, int numstates)
     ((int*)args->states)[numstates] = -1;
 }
 
+void ui_spinbox_args_set_visibility_states(UiSpinBoxArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
 void ui_spinbox_args_free(UiSpinBoxArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
     free((void*)args->varname);
     free((void*)args->states);
+    free((void*)args->visibility_states);
     free(args);
 }
 
@@ -2428,11 +2866,18 @@ void ui_webview_args_set_states(UiWebviewArgs *args, int *states, int numstates)
     ((int*)args->states)[numstates] = -1;
 }
 
+void ui_webview_args_set_visibility_states(UiWebviewArgs *args, int *states, int numstates) {
+    args->visibility_states = calloc(numstates+1, sizeof(int));
+    memcpy((void*)args->visibility_states, states, numstates * sizeof(int));
+    ((int*)args->visibility_states)[numstates] = -1;
+}
+
 void ui_webview_args_free(UiWebviewArgs *args) {
     free((void*)args->name);
     free((void*)args->style_class);
     free((void*)args->varname);
     free((void*)args->states);
+    free((void*)args->visibility_states);
     free(args);
 }
 
index 12c0160b0fe1a8a2d99a7a137cb783ab7a23e5f1..7a8dbd73025e8521ab2d6bf49e2b57d960dbb3a4 100644 (file)
@@ -83,6 +83,7 @@ UIEXPORT void ui_menuitem_args_set_label(UiMenuItemArgs *args, const char *label
 UIEXPORT void ui_menuitem_args_set_icon(UiMenuItemArgs *args, const char *icon);
 UIEXPORT void ui_menuitem_args_set_onclick(UiMenuItemArgs *args, ui_callback callback);
 UIEXPORT void ui_menuitem_args_set_onclickdata(UiMenuItemArgs *args, void *onclickdata);
+UIEXPORT void ui_menuitem_args_set_action(UiMenuItemArgs *args, const char *action);
 UIEXPORT void ui_menuitem_args_free(UiMenuItemArgs *args);
 
 UIEXPORT UiMenuToggleItemArgs* ui_menutoggleitem_args_new(void);
@@ -91,11 +92,14 @@ UIEXPORT void ui_menutoggleitem_args_set_icon(UiMenuToggleItemArgs *args, const
 UIEXPORT void ui_menutoggleitem_args_set_varname(UiMenuToggleItemArgs *args, const char *varname);
 UIEXPORT void ui_menutoggleitem_args_set_onchange(UiMenuToggleItemArgs *args, ui_callback callback);
 UIEXPORT void ui_menutoggleitem_args_set_onchangedata(UiMenuToggleItemArgs *args, void *onchangedata);
+UIEXPORT void ui_menutoggleitem_args_set_action(UiMenuToggleItemArgs *args, const char *action);
 UIEXPORT void ui_menutoggleitem_args_free(UiMenuToggleItemArgs *args);
 
 UIEXPORT UiMenuItemListArgs* ui_menuitemlist_args_new(void);
 UIEXPORT void ui_menuitemlist_args_set_varname(UiMenuItemListArgs *args, const char *varname);
 UIEXPORT void ui_menuitemlist_args_set_getvalue(UiMenuItemListArgs *args, ui_getvaluefunc func);
+UIEXPORT void ui_menuitemlist_args_set_getvalue2(UiMenuItemListArgs *args, ui_getvaluefunc2 func);
+UIEXPORT void ui_menuitemlist_args_set_getvaluedata(UiMenuItemListArgs *args, void *data);
 UIEXPORT void ui_menuitemlist_args_set_onselect(UiMenuItemListArgs *args, ui_callback callback);
 UIEXPORT void ui_menuitemlist_args_set_onselectdata(UiMenuItemListArgs *args, void *data);
 UIEXPORT void ui_menuitemlist_args_set_addseparator(UiMenuItemListArgs *args, UiBool value);
@@ -105,6 +109,7 @@ UIEXPORT UiToolbarItemArgs* ui_toolbar_item_args_new(void);
 UIEXPORT void ui_toolbar_item_args_set_label(UiToolbarItemArgs *args, const char *label);
 UIEXPORT void ui_toolbar_item_args_set_icon(UiToolbarItemArgs *args, const char *icon);
 UIEXPORT void ui_toolbar_item_args_set_tooltip(UiToolbarItemArgs *args, const char *tooltip);
+UIEXPORT void ui_toolbar_item_args_set_action(UiToolbarItemArgs *args, const char *action);
 UIEXPORT void ui_toolbar_item_args_set_onclick(UiToolbarItemArgs *args, ui_callback callback);
 UIEXPORT void ui_toolbar_item_args_set_onclickdata(UiToolbarItemArgs *args, void *onclickdata);
 UIEXPORT void ui_toolbar_item_args_set_states(UiToolbarItemArgs *args, int *states, int numstates);
@@ -115,11 +120,28 @@ UIEXPORT void ui_toolbar_toggleitem_args_set_label(UiToolbarToggleItemArgs *args
 UIEXPORT void ui_toolbar_toggleitem_args_set_icon(UiToolbarToggleItemArgs *args, const char *icon);
 UIEXPORT void ui_toolbar_toggleitem_args_set_tooltip(UiToolbarToggleItemArgs *args, const char *tooltip);
 UIEXPORT void ui_toolbar_toggleitem_args_set_varname(UiToolbarToggleItemArgs *args, const char *varname);
+UIEXPORT void ui_toolbar_toggleitem_args_set_action(UiToolbarToggleItemArgs *args, const char *action);
 UIEXPORT void ui_toolbar_toggleitem_args_set_onchange(UiToolbarToggleItemArgs *args, ui_callback callback);
 UIEXPORT void ui_toolbar_toggleitem_args_set_onchangedata(UiToolbarToggleItemArgs *args, void *onchangedata);
 UIEXPORT void ui_toolbar_toggleitem_args_set_states(UiToolbarToggleItemArgs *args, int *states, int numstates);
 UIEXPORT void ui_toolbar_toggleitem_args_free(UiToolbarToggleItemArgs *args);
 
+UIEXPORT UiToolbarContentToggleItemArgs* ui_toolbar_content_toggleitem_args_new(void);
+UIEXPORT void ui_toolbar_content_toggleitem_args_set_label0(UiToolbarContentToggleItemArgs *args, const char *label);
+UIEXPORT void ui_toolbar_content_toggleitem_args_set_icon0(UiToolbarContentToggleItemArgs *args, const char *icon);
+UIEXPORT void ui_toolbar_content_toggleitem_args_set_tooltip0(UiToolbarContentToggleItemArgs *args, const char *tooltip);
+UIEXPORT void ui_toolbar_content_toggleitem_args_set_label1(UiToolbarContentToggleItemArgs *args, const char *label);
+UIEXPORT void ui_toolbar_content_toggleitem_args_set_icon1(UiToolbarContentToggleItemArgs *args, const char *icon);
+UIEXPORT void ui_toolbar_content_toggleitem_args_set_tooltip1(UiToolbarContentToggleItemArgs *args, const char *tooltip);
+UIEXPORT void ui_toolbar_content_toggleitem_args_set_varname(UiToolbarContentToggleItemArgs *args, const char *varname);
+UIEXPORT void ui_toolbar_content_toggleitem_args_set_action(UiToolbarContentToggleItemArgs *args, const char *action);
+UIEXPORT void ui_toolbar_content_toggleitem_args_set_onchange(UiToolbarContentToggleItemArgs *args, ui_callback callback);
+UIEXPORT void ui_toolbar_content_toggleitem_args_set_onchangedata(UiToolbarContentToggleItemArgs *args, void *onchangedata);
+UIEXPORT void ui_toolbar_content_toggleitem_args_set_states(UiToolbarContentToggleItemArgs *args, int *states, int numstates);
+UIEXPORT void ui_toolbar_content_toggleitem_args_set_istogglebutton(UiToolbarContentToggleItemArgs *args, UiBool value);
+UIEXPORT void ui_toolbar_content_toggleitem_args_set_toggled_by_state(UiToolbarContentToggleItemArgs *args, int state);
+UIEXPORT void ui_toolbar_content_toggleitem_args_free(UiToolbarContentToggleItemArgs *args);
+
 UIEXPORT UiToolbarMenuArgs* ui_toolbar_menu_args_new(void);
 UIEXPORT void ui_toolbar_menu_args_set_label(UiToolbarMenuArgs *args, const char *label);
 UIEXPORT void ui_toolbar_menu_args_set_icon(UiToolbarMenuArgs *args, const char *icon);
@@ -149,6 +171,7 @@ UIEXPORT void ui_container_args_set_style_class(UiContainerArgs *args, const cha
 UIEXPORT void ui_container_args_set_spacing(UiContainerArgs *args, int value);
 UIEXPORT void ui_container_args_set_columnspacing(UiContainerArgs *args, int value);
 UIEXPORT void ui_container_args_set_rowspacing(UiContainerArgs *args, int value);
+UIEXPORT void ui_container_args_set_visibility_states(UiContainerArgs *args, int *states, int numstates);
 UIEXPORT void ui_container_args_free(UiContainerArgs *args);
     
 UIEXPORT UiFrameArgs* ui_frame_args_new(void);
@@ -174,6 +197,7 @@ UIEXPORT void ui_frame_args_set_columnspacing(UiFrameArgs *args, int value);
 UIEXPORT void ui_frame_args_set_rowspacing(UiFrameArgs *args, int value);
 UIEXPORT void ui_frame_args_set_expanded(UiFrameArgs *args, UiBool value);
 UIEXPORT void ui_frame_args_set_label(UiFrameArgs *args, const char *label);
+UIEXPORT void ui_frame_args_set_visibility_states(UiFrameArgs *args, int *states, int numstates);
 UIEXPORT void ui_frame_args_free(UiFrameArgs *args);
 
 UIEXPORT UiSidebarArgs* ui_sidebar_args_new(void);
@@ -211,6 +235,7 @@ UIEXPORT void ui_splitpane_args_set_position_property(UiSplitPaneArgs *args, con
 UIEXPORT void ui_splitpane_args_set_varname(UiSplitPaneArgs *args, const char *varname);
 UIEXPORT void ui_splitpane_args_set_value(UiSplitPaneArgs *args, UiInteger *value);
 UIEXPORT void ui_splitpane_args_set_max_panes(UiSplitPaneArgs *args, int max);
+UIEXPORT void ui_splitpane_args_set_visibility_states(UiSplitPaneArgs *args, int *states, int numstates);
 UIEXPORT void ui_splitpane_args_free(UiSplitPaneArgs *args);
 
 UIEXPORT UiTabViewArgs* ui_tabview_args_new(void);
@@ -239,6 +264,7 @@ UIEXPORT void ui_tabview_args_set_onchangedata(UiTabViewArgs *args, void *userda
 UIEXPORT void ui_tabview_args_set_varname(UiTabViewArgs *args, const char *varname);
 UIEXPORT void ui_tabview_args_set_value(UiTabViewArgs *args, UiInteger *value);
 UIEXPORT void ui_tabview_args_set_subcontainer(UiTabViewArgs *args, UiSubContainerType subcontainer);
+UIEXPORT void ui_tabview_args_set_visibility_states(UiTabViewArgs *args, int *states, int numstates);
 UIEXPORT void ui_tabview_args_free(UiTabViewArgs *args);
 
 UIEXPORT UiWidgetArgs* ui_widget_args_new(void);
@@ -280,6 +306,7 @@ UIEXPORT void ui_label_args_set_align(UiLabelArgs *args, UiAlignment align);
 UIEXPORT void ui_label_args_set_style(UiLabelArgs *args, UiLabelStyle style);
 UIEXPORT void ui_label_args_set_value(UiLabelArgs *args, UiString *value);
 UIEXPORT void ui_label_args_set_varname(UiLabelArgs *args, const char *varname);
+UIEXPORT void ui_label_args_set_visibility_states(UiLabelArgs *args, int *states, int numstates);
 UIEXPORT void ui_label_args_free(UiLabelArgs *args);
 
 UIEXPORT UiProgressbarArgs* ui_progressbar_args_new(void);
@@ -302,6 +329,7 @@ UIEXPORT void ui_progressbar_args_set_min(UiProgressbarArgs *args, double min);
 UIEXPORT void ui_progressbar_args_set_max(UiProgressbarArgs *args, double max);
 UIEXPORT void ui_progressbar_args_set_value(UiProgressbarArgs *args, UiDouble *value);
 UIEXPORT void ui_progressbar_args_set_varname(UiProgressbarArgs *args, const char *varname);
+UIEXPORT void ui_progressbar_args_set_visibility_states(UiProgressbarArgs *args, int *states, int numstates);
 UIEXPORT void ui_progressbar_args_free(UiProgressbarArgs *args);
 
 UIEXPORT UiProgressbarSpinnerArgs* ui_progress_spinner_args_new(void);
@@ -322,6 +350,7 @@ UIEXPORT void ui_progress_spinner_args_set_name(UiProgressbarSpinnerArgs *args,
 UIEXPORT void ui_progress_spinner_args_set_style_class(UiProgressbarSpinnerArgs *args, const char *classname);
 UIEXPORT void ui_progress_spinner_args_set_value(UiProgressbarSpinnerArgs *args, UiInteger *value);
 UIEXPORT void ui_progress_spinner_args_set_varname(UiProgressbarSpinnerArgs *args, const char *varname);
+UIEXPORT void ui_progress_spinner_args_set_visibility_states(UiProgressbarSpinnerArgs *args, int *states, int numstates);
 UIEXPORT void ui_progress_spinner_args_free(UiProgressbarSpinnerArgs *args);
 
 UIEXPORT UiButtonArgs* ui_button_args_new(void);
@@ -346,7 +375,9 @@ UIEXPORT void ui_button_args_set_tooltip(UiButtonArgs *args, const char *tooltip
 UIEXPORT void ui_button_args_set_labeltype(UiButtonArgs *args, int labeltype);
 UIEXPORT void ui_button_args_set_onclick(UiButtonArgs *args, ui_callback callback);
 UIEXPORT void ui_button_args_set_onclickdata(UiButtonArgs *args, void *onclickdata);
+UIEXPORT void ui_button_args_set_action(UiButtonArgs *args, const char *action);
 UIEXPORT void ui_button_args_set_states(UiButtonArgs *args, int *states, int numstates);
+UIEXPORT void ui_button_args_set_visibility_states(UiButtonArgs *args, int *states, int numstates);
 UIEXPORT void ui_button_args_free(UiButtonArgs *args);
 
 UIEXPORT UiToggleArgs* ui_toggle_args_new(void);
@@ -371,12 +402,49 @@ UIEXPORT void ui_toggle_args_set_tooltip(UiToggleArgs *args, const char *tooltip
 UIEXPORT void ui_toggle_args_set_labeltype(UiToggleArgs *args, int labeltype);
 UIEXPORT void ui_toggle_args_set_onchange(UiToggleArgs *args, ui_callback callback);
 UIEXPORT void ui_toggle_args_set_onchangedata(UiToggleArgs *args, void *onchangedata);
+UIEXPORT void ui_toggle_args_set_action(UiToggleArgs *args, const char *action);
 UIEXPORT void ui_toggle_args_set_varname(UiToggleArgs *args, const char *varname);
 UIEXPORT void ui_toggle_args_set_value(UiToggleArgs *args, UiInteger *value);
 UIEXPORT void ui_toggle_args_set_enablestate(UiToggleArgs *args, int state);
 UIEXPORT void ui_toggle_args_set_states(UiToggleArgs *args, int *states, int numstates);
+UIEXPORT void ui_toggle_args_set_visibility_states(UiToggleArgs *args, int *states, int numstates);
 UIEXPORT void ui_toggle_args_free(UiToggleArgs *args);
 
+UIEXPORT UiContentToggleArgs* ui_content_toggle_args_new(void);
+UIEXPORT void ui_content_toggle_args_set_fill(UiContentToggleArgs *args, UiBool fill);
+UIEXPORT void ui_content_toggle_args_set_hexpand(UiContentToggleArgs *args, UiBool value);
+UIEXPORT void ui_content_toggle_args_set_vexpand(UiContentToggleArgs *args, UiBool value);
+UIEXPORT void ui_content_toggle_args_set_hfill(UiContentToggleArgs *args, UiBool value);
+UIEXPORT void ui_content_toggle_args_set_vfill(UiContentToggleArgs *args, UiBool value);
+UIEXPORT void ui_content_toggle_args_set_override_defaults(UiContentToggleArgs *args, UiBool value);
+UIEXPORT void ui_content_toggle_args_set_margin(UiContentToggleArgs *args, int value);
+UIEXPORT void ui_content_toggle_args_set_margin_left(UiContentToggleArgs *args, int value);
+UIEXPORT void ui_content_toggle_args_set_margin_right(UiContentToggleArgs *args, int value);
+UIEXPORT void ui_content_toggle_args_set_margin_top(UiContentToggleArgs *args, int value);
+UIEXPORT void ui_content_toggle_args_set_margin_bottom(UiContentToggleArgs *args, int value);
+UIEXPORT void ui_content_toggle_args_set_colspan(UiContentToggleArgs *args, int colspan);
+UIEXPORT void ui_content_toggle_args_set_rowspan(UiContentToggleArgs *args, int rowspan);
+UIEXPORT void ui_content_toggle_args_set_name(UiContentToggleArgs *args, const char *name);
+UIEXPORT void ui_content_toggle_args_set_style_class(UiContentToggleArgs *args, const char *classname);
+UIEXPORT void ui_content_toggle_args_set_label0(UiContentToggleArgs *args, const char *label);
+UIEXPORT void ui_content_toggle_args_set_icon0(UiContentToggleArgs *args, const char *icon);
+UIEXPORT void ui_content_toggle_args_set_tooltip0(UiContentToggleArgs *args, const char *tooltip);
+UIEXPORT void ui_content_toggle_args_set_label1(UiContentToggleArgs *args, const char *label);
+UIEXPORT void ui_content_toggle_args_set_icon1(UiContentToggleArgs *args, const char *icon);
+UIEXPORT void ui_content_toggle_args_set_tooltip1(UiContentToggleArgs *args, const char *tooltip);
+UIEXPORT void ui_content_toggle_args_set_labeltype(UiContentToggleArgs *args, int labeltype);
+UIEXPORT void ui_content_toggle_args_set_onchange(UiContentToggleArgs *args, ui_callback callback);
+UIEXPORT void ui_content_toggle_args_set_onchangedata(UiContentToggleArgs *args, void *onchangedata);
+UIEXPORT void ui_content_toggle_args_set_action(UiContentToggleArgs *args, const char *action);
+UIEXPORT void ui_content_toggle_args_set_varname(UiContentToggleArgs *args, const char *varname);
+UIEXPORT void ui_content_toggle_args_set_value(UiContentToggleArgs *args, UiInteger *value);
+UIEXPORT void ui_content_toggle_args_set_toggled_by_state(UiContentToggleArgs *args, int state);
+UIEXPORT void ui_content_toggle_args_set_istogglebutton(UiContentToggleArgs *args, UiBool value);
+UIEXPORT void ui_content_toggle_args_set_enablestate(UiContentToggleArgs *args, int state);
+UIEXPORT void ui_content_toggle_args_set_states(UiContentToggleArgs *args, int *states, int numstates);
+UIEXPORT void ui_content_toggle_args_set_visibility_states(UiContentToggleArgs *args, int *states, int numstates);
+UIEXPORT void ui_content_toggle_args_free(UiContentToggleArgs *args);
+
 UIEXPORT UiLinkButtonArgs* ui_linkbutton_args_new(void);
 UIEXPORT void ui_linkbutton_args_set_fill(UiLinkButtonArgs *args, UiBool fill);
 UIEXPORT void ui_linkbutton_args_set_hexpand(UiLinkButtonArgs *args, UiBool value);
@@ -399,9 +467,11 @@ UIEXPORT void ui_linkbutton_args_set_label(UiLinkButtonArgs *args, const char *l
 UIEXPORT void ui_linkbutton_args_set_uri(UiLinkButtonArgs *args, const char *uri);
 UIEXPORT void ui_linkbutton_args_set_onclick(UiLinkButtonArgs *args, ui_callback callback);
 UIEXPORT void ui_linkbutton_args_set_onclickdata(UiLinkButtonArgs *args, void *userdata);
+UIEXPORT void ui_linkbutton_args_set_action(UiLinkButtonArgs *args, const char *action);
 UIEXPORT void ui_linkbutton_args_set_nofollow(UiLinkButtonArgs *args, UiBool value);
 UIEXPORT void ui_linkbutton_args_set_type(UiLinkButtonArgs *args, UiLinkType type);
 UIEXPORT void ui_linkbutton_args_set_states(UiLinkButtonArgs *args, int *states, int numstates);
+UIEXPORT void ui_linkbutton_args_set_visibility_states(UiLinkButtonArgs *args, int *states, int numstates);
 UIEXPORT void ui_linkbutton_args_free(UiLinkButtonArgs *args);
 
 UIEXPORT UiListArgs* ui_list_args_new(void);
@@ -431,19 +501,25 @@ UIEXPORT void ui_list_args_set_getstyle_func(UiListArgs *args, ui_getstylefunc g
 UIEXPORT void ui_list_args_set_getstyle_data(UiListArgs *args, void *userdata);
 UIEXPORT void ui_list_args_set_onactivate(UiListArgs *args, ui_callback callback);
 UIEXPORT void ui_list_args_set_onactivatedata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_onactivate_action(UiListArgs *args, const char *action);
 UIEXPORT void ui_list_args_set_onselection(UiListArgs *args, ui_callback callback);
 UIEXPORT void ui_list_args_set_onselectiondata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_onselection_action(UiListArgs *args, const char *action);
 UIEXPORT void ui_list_args_set_ondragstart(UiListArgs *args, ui_callback callback);
 UIEXPORT void ui_list_args_set_ondragstartdata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_ondragstart_action(UiListArgs *args, const char *action);
 UIEXPORT void ui_list_args_set_ondragcomplete(UiListArgs *args, ui_callback callback);
 UIEXPORT void ui_list_args_set_ondragcompletedata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_ondragcomplete_action(UiListArgs *args, const char *action);
 UIEXPORT void ui_list_args_set_ondrop(UiListArgs *args, ui_callback callback);
 UIEXPORT void ui_list_args_set_ondropdata(UiListArgs *args, void *userdata);
+UIEXPORT void ui_list_args_set_ondrop_action(UiListArgs *args, const char *action);
 UIEXPORT void ui_list_args_set_onsave(UiListArgs *args, ui_list_savefunc onsave);
 UIEXPORT void ui_list_args_set_onsavedata(UiListArgs *args, void *userdata);
 UIEXPORT void ui_list_args_set_multiselection(UiListArgs *args, UiBool multiselection);
 UIEXPORT void ui_list_args_set_contextmenu(UiListArgs *args, UiMenuBuilder *menubuilder);
 UIEXPORT void ui_list_args_set_states(UiListArgs *args, int *states, int numstates);
+UIEXPORT void ui_list_args_set_visibility_states(UiListArgs *args, int *states, int numstates);
 UIEXPORT void ui_list_args_free(UiListArgs *args);
 
 UIEXPORT UiSourceListArgs* ui_sourcelist_args_new(void);
@@ -473,6 +549,8 @@ UIEXPORT void ui_sourcelist_args_set_onbuttonclick(UiSourceListArgs *args, ui_ca
 UIEXPORT void ui_sourcelist_args_set_onbuttonclickdata(UiSourceListArgs *args, void *userdata);
 UIEXPORT void ui_sourcelist_args_set_contextmenu(UiSourceListArgs *args, UiMenuBuilder *menubuilder);
 UIEXPORT void ui_sourcelist_args_set_header_is_item(UiSourceListArgs *args, UiBool value);
+UIEXPORT void ui_sourcelist_args_set_states(UiSourceListArgs *args, int *states, int numstates);
+UIEXPORT void ui_sourcelist_args_set_visibility_states(UiSourceListArgs *args, int *states, int numstates);
 UIEXPORT void ui_sourcelist_args_free(UiSourceListArgs *args);
 
 UIEXPORT UiTextAreaArgs* ui_textarea_args_new(void);
@@ -493,9 +571,14 @@ UIEXPORT void ui_textarea_args_set_name(UiTextAreaArgs *args, const char *name);
 UIEXPORT void ui_textarea_args_set_style_class(UiTextAreaArgs *args, const char *classname);
 UIEXPORT void ui_textarea_args_set_onchange(UiTextAreaArgs *args, ui_callback callback);
 UIEXPORT void ui_textarea_args_set_onchangedata(UiTextAreaArgs *args, void *onchangedata);
+UIEXPORT void ui_textarea_args_set_onchange_action(UiTextAreaArgs *args, const char *action);
+UIEXPORT void ui_textarea_args_set_ontextchanged(UiTextAreaArgs *args, ui_callback callback);
+UIEXPORT void ui_textarea_args_set_ontextchangeddata(UiTextAreaArgs *args, void *onchangedata);
+UIEXPORT void ui_textarea_args_set_ontextchanged_action(UiTextAreaArgs *args, const char *action);
 UIEXPORT void ui_textarea_args_set_varname(UiTextAreaArgs *args, const char *varname);
 UIEXPORT void ui_textarea_args_set_value(UiTextAreaArgs *args, UiText *value);
 UIEXPORT void ui_textarea_args_set_states(UiTextAreaArgs *args, int *states, int numstates);
+UIEXPORT void ui_textarea_args_set_visibility_states(UiTextAreaArgs *args, int *states, int numstates);
 UIEXPORT void ui_textarea_args_free(UiTextAreaArgs *args);
 
 UIEXPORT UiTextFieldArgs* ui_textfield_args_new(void);
@@ -518,9 +601,12 @@ UIEXPORT void ui_textfield_args_set_onchange(UiTextFieldArgs *args, ui_callback
 UIEXPORT void ui_textfield_args_set_onchangedata(UiTextFieldArgs *args, void *onchangedata);
 UIEXPORT void ui_textfield_args_set_onactivate(UiTextFieldArgs *args, ui_callback callback);
 UIEXPORT void ui_textfield_args_set_onactivatedata(UiTextFieldArgs *args, void *onactivatedata);
+UIEXPORT void ui_textfield_args_set_onactivate_action(UiTextFieldArgs *args, const char *action);
+UIEXPORT void ui_textfield_args_set_onchange_action(UiTextFieldArgs *args, const char *action);
 UIEXPORT void ui_textfield_args_set_varname(UiTextFieldArgs *args, const char *varname);
 UIEXPORT void ui_textfield_args_set_value(UiTextFieldArgs *args, UiString *value);
 UIEXPORT void ui_textfield_args_set_states(UiTextFieldArgs *args, int *states, int numstates);
+UIEXPORT void ui_textfield_args_set_visibility_states(UiTextFieldArgs *args, int *states, int numstates);
 UIEXPORT void ui_textfield_args_free(UiTextFieldArgs *args);
 
 UIEXPORT UiSpinBoxArgs* ui_spinbox_args_new(void);
@@ -550,6 +636,7 @@ UIEXPORT void ui_spinbox_args_set_intvalue(UiSpinBoxArgs *args, UiInteger *value
 UIEXPORT void ui_spinbox_args_set_doublevalue(UiSpinBoxArgs *args, UiDouble *value);
 UIEXPORT void ui_spinbox_args_set_rangevalue(UiSpinBoxArgs *args, UiRange *value);
 UIEXPORT void ui_spinbox_args_set_states(UiSpinBoxArgs *args, int *states, int numstates);
+UIEXPORT void ui_spinbox_args_set_visibility_states(UiSpinBoxArgs *args, int *states, int numstates);
 UIEXPORT void ui_spinbox_args_free(UiSpinBoxArgs *args);
 
 UIEXPORT UiWebviewArgs* ui_webview_args_new(void);
@@ -571,6 +658,7 @@ UIEXPORT void ui_webview_args_set_style_class(UiWebviewArgs *args, const char *c
 UIEXPORT void ui_webview_args_set_varname(UiWebviewArgs *args, const char *varname);
 UIEXPORT void ui_webview_args_set_value(UiWebviewArgs *args, UiGeneric *value);
 UIEXPORT void ui_webview_args_set_states(UiWebviewArgs *args, int *states, int numstates);
+UIEXPORT void ui_webview_args_set_visibility_states(UiWebviewArgs *args, int *states, int numstates);
 UIEXPORT void ui_webview_args_free(UiWebviewArgs *args);
 
 #ifdef __cplusplus
index 6f0dde99465680b45d09170db06832b5d64836a4..12c62676107e6118043c2d1c11a187204d8e96a1 100644 (file)
@@ -33,13 +33,13 @@ void ui_end_new(UiObject *obj) {
     if(!obj->container_end) {
         return;
     }
-    UiContainerX *rm = obj->container_end;
+    UiContainer *rm = obj->container_end;
     uic_object_pop_container(obj);
     ui_free(obj->ctx, rm);
 }
 
 void ui_newline(UiObject *obj) {
-    UiContainerX *container = obj->container_end;
+    UiContainer *container = obj->container_end;
     if(container) {
         container->newline = TRUE;
     }
index 9ddfdb75b4c0974dfe6c4e20f17690b9b0b55f32..757056f491e17100abccadb87920d3b5d0144c65 100644 (file)
@@ -67,9 +67,11 @@ UiContext* uic_context(UiObject *toplevel, CxMempool *mp) {
     ctx->state_widgets = cxLinkedListCreate(mp->allocator, sizeof(UiStateWidget));
     ctx->states = cxArrayListCreate(mp->allocator, sizeof(int), 32);
     cxSetCompareFunc(ctx->states, cx_cmp_int);
+    ctx->suppressed_states = cxArrayListCreate(mp->allocator, sizeof(int), 16);
+    cxSetCompareFunc(ctx->suppressed_states, cx_cmp_int);
     
-    ctx->attach_document = uic_context_attach_document;
-    ctx->detach_document2 = uic_context_detach_document;
+    ctx->actions = cxHashMapCreate(ctx->allocator, sizeof(UiAction), 8);
+    ctx->action_bindings = cxArrayListCreate(ctx->allocator, sizeof(UiActionBinding), 0);
     
 #if UI_GTK2 || UI_GTK3
     if(toplevel && toplevel->widget) {
@@ -78,6 +80,8 @@ UiContext* uic_context(UiObject *toplevel, CxMempool *mp) {
     }
 #endif
     
+    ctx->ref = 1;
+    
     return ctx;
 }
 
@@ -92,33 +96,64 @@ void uic_context_add_destructor(UiContext *ctx, cx_destructor_func func, void *d
     cxListAdd(ctx->destroy_handler, &handler);
 }
 
+void uic_context_remove_destructor(UiContext *ctx, void *data) {
+    CxIterator i = cxListIterator(ctx->destroy_handler);
+    cx_foreach(UiDestroyHandler *, handler, i) {
+        if(handler->data == data) {
+            cxIteratorFlagRemoval(i);
+        }
+    }
+}
+
 void uic_context_prepare_close(UiContext *ctx) {
     cxListClear(ctx->states);
     cxListClear(ctx->state_widgets);
+    cxListClear(ctx->action_bindings);
+    uic_context_detach_all(ctx);
 }
 
-void uic_context_attach_document(UiContext *ctx, void *document) {
-    if(ctx->single_document_mode) {
-        if(ctx->document) {
-            uic_context_detach_document(ctx, ctx->document);
-        }
+void uic_context_destroy(UiContext *ctx, void *document) {
+    if(!ctx) {
+        return;
     }
     
-    cxListAdd(ctx->documents, document);
-    ctx->document = document;
+    UiEvent ev;
+    ev.obj = ctx->obj;
+    ev.window = ev.obj ? ev.obj->window : NULL;
+    ev.document = document;
+    ev.eventdata = NULL;
+    ev.eventdatatype = 0;
+    ev.intval = 0;
+    ev.set = 0;
+
+    if(ctx->onclose) {
+        ctx->onclose(&ev, ctx->onclosedata);
+    }
     
-    UiContext *doc_ctx = ui_document_context(document);
-    doc_ctx->parent = ctx;
+    CxIterator i = cxListIterator(ctx->destroy_handler);
+    cx_foreach(UiDestroyHandler *, h, i) {
+        h->destructor(h->data);
+    }
     
+    uic_context_detach_all(ctx);
+
+    cxMempoolFree(ctx->mp);
+}
+
+void uic_context_update_bindings(UiContext *ctx) {
+    int onchange_enabled = ui_onchange_events_is_enabled();
+    int onselection_enabled = ui_selection_events_is_enabled();
+    ui_onchange_events_enable(FALSE);
+    ui_selection_events_enable(FALSE);
     // if a document variable has the same name as a parent variable,
     // move the bindings to the document
-    UiContext *var_ctx = ctx;
+    UiContext *var_ctx = ctx->parent;
     while(var_ctx) {
         CxMapIterator i = cxMapIterator(var_ctx->vars);
         cx_foreach(CxMapEntry*, entry, i) {
-            printf("attach %.*s\n", (int)entry->key->len, (char*)entry->key->data);
+            // printf("attach %.*s\n", (int)entry->key->len, (char*)entry->key->data);
             UiVar *var = entry->value;
-            UiVar *docvar = cxMapGet(doc_ctx->vars, *entry->key);
+            UiVar *docvar = cxMapGet(ctx->vars, *entry->key);
             if(docvar) {
                 // bind var to document var
                 uic_copy_var_binding(var, docvar, TRUE);
@@ -128,13 +163,59 @@ void uic_context_attach_document(UiContext *ctx, void *document) {
         
         var_ctx = var_ctx->parent;
     }
+      
+    ui_update_action_bindings(ctx);
+    
+    if(ctx->documents) {
+        CxIterator i = cxListIterator(ctx->documents);
+        cx_foreach(void *, doc, i) {
+            UiContext *subctx = ui_document_context(doc);
+            uic_context_update_bindings(subctx);
+        }
+    }
+    ui_onchange_events_enable(onchange_enabled);
+    ui_selection_events_enable(onselection_enabled);
+}
+
+void uic_context_attach_document(UiContext *ctx, void *document) {
+    if(ctx->single_document_mode) {
+        if(ctx->document) {
+            uic_context_detach_document(ctx, ctx->document);
+        }
+    }
+    
+    cxListAdd(ctx->documents, document);
+    ctx->document = document;
+    
+    UiContext *doc_ctx = ui_document_context(document);
+    doc_ctx->parent = ctx;
+    doc_ctx->ref++;
+    
+    uic_context_update_bindings(doc_ctx);
+    if(doc_ctx->onattach) {
+        UiEvent event;
+        memset(&event, 0, sizeof(UiEvent));
+        event.document = document;
+        doc_ctx->onattach(&event, doc_ctx->onattachdata);
+    }
+    uic_check_state_widgets(ui_context_toplevel_parent(ctx));
+    UiObject *obj = ui_context_get_parent_obj(ctx);
+    uic_send_status_change(doc_ctx, obj);
+    
+    UiContext *obj_ctx = uic_obj_context(ctx);
+    if(obj_ctx) {
+        ui_update_action_bindings(obj_ctx);
+    }
 }
 
 static void uic_context_unbind_vars(UiContext *ctx) {
+    int onchange_enabled = ui_onchange_events_is_enabled();
+    int onselection_enabled = ui_selection_events_is_enabled();
     ui_onchange_events_enable(FALSE);
+    ui_selection_events_enable(FALSE);
     CxMapIterator mi = cxMapIterator(ctx->vars);
     cx_foreach(CxMapEntry*, entry, mi) {
-        printf("detach %.*s\n", (int)entry->key->len, (char*)entry->key->data);
+        //printf("detach %.*s\n", (int)entry->key->len, (char*)entry->key->data);
         UiVar *var = entry->value;
         // var->from && var->from_ctx && var->from_ctx != ctx
         uic_save_var(var);
@@ -154,7 +235,8 @@ static void uic_context_unbind_vars(UiContext *ctx) {
         }
     }
     
-    ui_onchange_events_enable(TRUE);
+    ui_onchange_events_enable(onchange_enabled);
+    ui_selection_events_enable(onselection_enabled);
 }
 
 void uic_context_detach_document(UiContext *ctx, void *document) {
@@ -167,9 +249,24 @@ void uic_context_detach_document(UiContext *ctx, void *document) {
     cxListRemove(ctx->documents, docIndex);
     ctx->document = cxListAt(ctx->documents, 0);
     
-    UiContext *docctx = ui_document_context(document);
-    uic_context_unbind_vars(docctx); // unbind all doc/subdoc vars from the parent
-    docctx->parent = NULL;
+    UiContext *doc_ctx = ui_document_context(document);
+    uic_context_unbind_vars(doc_ctx); // unbind all doc/subdoc vars from the parent
+    doc_ctx->parent = NULL;
+    
+    UiContext *obj_ctx = uic_obj_context(ctx);
+    if(obj_ctx) {
+        ui_update_action_bindings(obj_ctx);
+    }
+    if(doc_ctx->ondetach) {
+        UiEvent event;
+        memset(&event, 0, sizeof(UiEvent));
+        event.document = document;
+        doc_ctx->ondetach(&event, doc_ctx->ondetachdata);
+    }
+    
+    uic_check_state_widgets(ui_context_toplevel_parent(ctx));
+    uic_send_status_change(doc_ctx, NULL);
+    ui_document_unref(document);
 }
 
 void uic_context_detach_all(UiContext *ctx) {
@@ -183,12 +280,40 @@ void uic_context_detach_all(UiContext *ctx) {
     // detach documents
     i = cxListIterator(ls);
     cx_foreach(void *, doc, i) {
-        ctx->detach_document2(ctx, doc);
+        uic_context_detach_document(ctx, doc);
     }
     
     cxListFree(ls);
+    ui_update_action_bindings(ctx);
 }
 
+static void send_status_change(UiContext *ctx, UiEvent *event, UiObject *obj) {
+    CxIterator i = cxListIterator(ctx->documents);
+    cx_foreach(void *, doc, i) {
+        UiContext *doc_ctx = ui_document_context(doc);
+        if(doc_ctx->onattachmentstatuschange) {
+            event->obj = doc_ctx->obj ? doc_ctx->obj : obj;
+            event->window = event->obj ? event->obj->window : NULL;
+            event->document = doc_ctx->self_doc ? doc_ctx->self_doc : doc_ctx->document;
+            doc_ctx->onattachmentstatuschange(event, doc_ctx->onattachmentstatuschangedata);
+        }
+    }
+    
+    if(ctx->onattachmentstatuschange) {
+        event->obj = ctx->obj ? ctx->obj : obj;
+        event->window = event->obj ? event->obj->window : NULL;
+        event->document = ctx->self_doc ? ctx->self_doc : ctx->document;
+        ctx->onattachmentstatuschange(event, ctx->onattachmentstatuschangedata);
+    }
+}
+
+void uic_send_status_change(UiContext *ctx, UiObject *obj) {
+    UiEvent event;
+    memset(&event, 0, sizeof(UiEvent));
+    send_status_change(ctx, &event, obj);
+}
+
+
 static UiVar* ctx_getvar(UiContext *ctx, CxHashKey key) {
     UiVar *var = cxMapGet(ctx->vars, key);
     if(!var && ctx->documents) {
@@ -404,8 +529,21 @@ void uic_copy_value_binding(UiVarType type, void *from, void *to) {
         case UI_VAR_LIST: {         
             UiList *f = from;
             UiList *t = to;
+            // save selection
+            ui_list_selection_free(f->saved_selection);
+            if(f->getselection && f->save_selection) {
+                f->saved_selection = ui_list_get_selection_allocated(f);
+            } else {
+                f->saved_selection = NULL;
+            }
+    
             uic_list_copy(f, t);
             ui_list_update(t);
+            if(t->setselection && t->saved_selection) {
+                t->setselection(t, *t->saved_selection);
+            }
+            ui_list_selection_free(t->saved_selection);
+            t->saved_selection = NULL;
             break;
         }
         case UI_VAR_RANGE: {
@@ -517,22 +655,23 @@ void ui_detach_document(UiContext *ctx, void *document) {
 }
 
 void ui_context_closefunc(UiContext *ctx, ui_callback fnc, void *udata) {
-    ctx->close_callback = fnc;
-    ctx->close_data = udata;
-}
-
-void ui_context_destroy(UiContext *ctx) {
-    CxIterator i = cxListIterator(ctx->destroy_handler);
-    cx_foreach(UiDestroyHandler *, h, i) {
-        h->destructor(h->data);
-    }
-    cxMempoolFree(ctx->mp);
+    ctx->onclose = fnc;
+    ctx->onclosedata = udata;
 }
 
 UiContext* ui_context_parent(UiContext *ctx) {
     return ctx->parent;
 }
 
+UiContext* ui_context_toplevel_parent(UiContext *ctx) {
+    if(ctx->obj) {
+        return ctx;
+    } else if (ctx->parent) {
+        return ui_context_toplevel_parent(ctx->parent);
+    }
+    return NULL;
+}
+
 
 void ui_set_state(UiContext *ctx, int state) {
     if(!cxListIndexValid(ctx->states, cxListFind(ctx->states, &state))) {
@@ -540,7 +679,7 @@ void ui_set_state(UiContext *ctx, int state) {
     }
     
     // enable/disable group widgets
-    uic_check_state_widgets(ctx);
+    uic_check_state_widgets(ui_context_toplevel_parent(ctx));
 }
 
 void ui_unset_state(UiContext *ctx, int state) {
@@ -550,25 +689,94 @@ void ui_unset_state(UiContext *ctx, int state) {
     }
     
     // enable/disable group widgets
-    uic_check_state_widgets(ctx);
+    uic_check_state_widgets(ui_context_toplevel_parent(ctx));
+}
+
+void ui_suppress_state(UiContext *ctx, int state) {
+    if(!cxListIndexValid(ctx->suppressed_states, cxListFind(ctx->suppressed_states, &state))) {
+        cxListAdd(ctx->suppressed_states, &state);
+    }
+    
+    // enable/disable group widgets
+    uic_check_state_widgets(ui_context_toplevel_parent(ctx));
+}
+
+void ui_unsuppress_state(UiContext *ctx, int state) {
+    int i = cxListFind(ctx->suppressed_states, &state);
+    if(i != -1) {
+        cxListRemove(ctx->suppressed_states, i);
+    }
+    
+    // enable/disable group widgets
+    uic_check_state_widgets(ui_context_toplevel_parent(ctx));
+}
+
+typedef struct StatesList {
+    CX_ARRAY(int, states);
+    CX_ARRAY(int, suppressed);
+} StatesList;
+
+static void add_ctx_states(UiContext *ctx, StatesList *states) {
+    size_t nstates = cxListSize(ctx->states);
+    int *ctx_states = cxListAt(ctx->states, 0);
+    
+    size_t nsuppressed = cxListSize(ctx->suppressed_states);
+    int *ctx_suppressed_states = cxListAt(ctx->suppressed_states, 0);
+    
+    cx_array_add_array(states->states, ctx_states, nstates);
+    cx_array_add_array(states->suppressed, ctx_suppressed_states, nsuppressed);
+    
+    CxIterator i = cxListIterator(ctx->documents);
+    cx_foreach(void *, doc, i) {
+        UiContext *doc_ctx = ui_document_context(doc);
+        add_ctx_states(doc_ctx, states);
+    }
 }
 
 int* ui_active_states(UiContext *ctx, int *nstates) {
-    *nstates = cxListSize(ctx->states);
-    return cxListAt(ctx->states, 0);
+    StatesList states;
+    cx_array_init(states.states, 32);
+    cx_array_init(states.suppressed, 8);
+    add_ctx_states(ctx, &states);
+    
+    // remove suppressed states
+    for(size_t i=0;i<states.suppressed.size;i++) {
+        int suppressed = states.suppressed.data[i];
+        // important to use ssize_t for the index here
+        for(ssize_t s=0;s<states.states.size;s++) {
+            if(states.states.data[s] == suppressed) {
+                // this state is suppressed
+                if(s+1 < states.states.size) {
+                    // copy last element to the current position
+                    states.states.data[s] = states.states.data[states.states.size-1];
+                    // we need to check the current index again
+                    s--;
+                }
+                states.states.size--;
+            }
+        }
+    }
+    
+    free(states.suppressed.data);
+    *nstates = (int)states.states.size;
+    return states.states.data;
 }
 
 void uic_check_state_widgets(UiContext *ctx) {
-    int ngroups = 0;
-    int *groups = ui_active_states(ctx, &ngroups);
+    if(!ctx) {
+        return;
+    }
+    
+    int nstates = 0;
+    int *states = ui_active_states(ctx, &nstates);
     
     CxIterator i = cxListIterator(ctx->state_widgets);
     cx_foreach(UiStateWidget *, gw, i) {
         char *check = calloc(1, gw->numstates);
         
-        for(int i=0;i<ngroups;i++) {
+        for(int i=0;i<nstates;i++) {
             for(int k=0;k<gw->numstates;k++) {
-                if(groups[i] == gw->states[k]) {
+                if(states[i] == gw->states[k]) {
                     check[k] = 1;
                 }
             }
@@ -584,6 +792,8 @@ void uic_check_state_widgets(UiContext *ctx) {
         free(check);
         gw->enable(gw->widget, enable);
     }
+    
+    free(states);
 }
 
 void ui_widget_set_states(UiContext *ctx, UIWIDGET widget, ui_enablefunc enable, ...) {
@@ -621,6 +831,13 @@ void ui_widget_set_visibility_states(UiContext *ctx, UIWIDGET widget, const int
     ui_widget_set_states2(ctx, widget, (ui_enablefunc)ui_set_visible, states, nstates);
 }
 
+void uic_widget_set_visibility_states(UiContext *ctx, UIWIDGET widget, const int *states) {
+    if(states) {
+        size_t nstates = uic_state_array_size(states);
+        ui_widget_set_visibility_states(ctx, widget, states, (int)nstates);
+    }
+}
+
 size_t uic_state_array_size(const int *states) {
     int i;
     for(i=0;states[i] >= 0;i++) { }
@@ -661,26 +878,30 @@ void* ui_cx_mempool(UiContext *ctx) {
 }
 
 void* ui_malloc(UiContext *ctx, size_t size) {
-    return ctx ? cxMalloc(ctx->allocator, size) : NULL;
+    return ctx ? cxMalloc(ctx->allocator, size) : malloc(size);
 }
 
 void* ui_calloc(UiContext *ctx, size_t nelem, size_t elsize) {
-    return ctx ? cxCalloc(ctx->allocator, nelem, elsize) : NULL;
+    return ctx ? cxCalloc(ctx->allocator, nelem, elsize) : calloc(nelem, elsize);
 }
 
 void ui_free(UiContext *ctx, void *ptr) {
-    if(ctx && ptr) {
-        cxFree(ctx->allocator, ptr);
+    if(ptr) {
+        if(ctx) {
+            cxFree(ctx->allocator, ptr);
+        } else {
+            free(ptr);
+        }
     }
 }
 
 void* ui_realloc(UiContext *ctx, void *ptr, size_t size) {
-    return ctx ? cxRealloc(ctx->allocator, ptr, size) : NULL;
+    return ctx ? cxRealloc(ctx->allocator, ptr, size) : realloc(ptr, size);
 }
 
 char* ui_strdup(UiContext *ctx, const char *str) {
     if(!ctx) {
-        return NULL;
+        return strdup(str ? str : "");
     }
     cxstring s = cx_str(str);
     cxmutstr d = cx_strdup_a(ctx->allocator, s);
@@ -688,7 +909,12 @@ char* ui_strdup(UiContext *ctx, const char *str) {
 }
 
 void  ui_reg_destructor(UiContext *ctx, void *data, ui_destructor_func destr) {
-    cxMempoolRegister(ctx->mp, data, (cx_destructor_func)destr);
+    //cxMempoolRegister(ctx->mp, data, (cx_destructor_func)destr);
+    uic_context_add_destructor(ctx, destr, data);
+}
+
+void  ui_remove_destructor(UiContext *ctx, void *data) {
+    uic_context_remove_destructor(ctx, data);
 }
 
 void  ui_set_destructor(void *mem, ui_destructor_func destr) {
@@ -840,3 +1066,66 @@ UiGeneric* ui_get_generic_var(UiContext *ctx, const char *name) {
     UiVar *var = uic_get_var_t(ctx, name, UI_VAR_GENERIC);
     return var ? var->value : NULL;
 }
+
+
+
+void ui_context_onattach(UiContext *ctx, ui_callback cb, void *data) {
+    ctx->onattach = cb;
+    ctx->onattachdata = data;
+}
+
+void ui_context_ondetach(UiContext *ctx, ui_callback cb, void *data) {
+    ctx->ondetach = cb;
+    ctx->ondetachdata = data;
+}
+
+void ui_context_onattachmentstatuschange(UiContext *ctx, ui_callback cb, void *data) {
+    ctx->onattachmentstatuschange = cb;
+    ctx->onattachmentstatuschangedata = data;
+}
+
+static void attachment_action_callback(UiEvent *event, void *action) {
+    if(event->document) {
+        UiContext *ctx = ui_document_context(event->document);
+        ui_call_action_on(ctx, action);
+    }
+}
+
+void ui_context_onattach_action(UiContext *ctx, const char *action) {
+    ctx->onattach = attachment_action_callback;
+    ctx->onattachdata = ui_strdup(ctx, action);
+}
+
+void ui_context_ondetach_action(UiContext *ctx, const char *action) {
+    ctx->ondetach = attachment_action_callback;
+    ctx->ondetachdata = ui_strdup(ctx, action);
+}
+
+void ui_context_onattachmentstatuschange_action(UiContext *ctx, const char *action) {
+    ctx->onattachmentstatuschange = attachment_action_callback;
+    ctx->onattachmentstatuschangedata = ui_strdup(ctx, action);
+}
+
+
+int ui_context_is_attached(UiContext *ctx) {
+    return ctx->parent != NULL;
+}
+
+int ui_context_is_attached_to_obj(UiContext *ctx) {
+    return uic_obj_context(ctx) != NULL;
+}
+
+UIEXPORT UiObject* ui_context_get_parent_obj(UiContext *ctx) {
+    UiContext *obj_ctx = uic_obj_context(ctx);
+    return obj_ctx ? obj_ctx->obj : NULL;
+}
+
+UiContext* uic_obj_context(UiContext *ctx) {
+    if(ctx->obj) {
+        return ctx;
+    }
+    if(ctx->parent == NULL) {
+        return NULL;
+    }
+    return uic_obj_context(ctx->parent);
+}
index 407c051d963dd7d620f3cfb0120199d31a61a528..071800749f55dd11ba5f4809dd4aa61531a6c3ad 100644 (file)
@@ -36,6 +36,8 @@
 #include <cx/list.h>
 #include <cx/linked_list.h>
 
+#include "action.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -60,20 +62,24 @@ typedef enum UiVarType {
 struct UiContext {
     UiContext     *parent;
     UiObject      *obj;
-    CxMempool *mp;
+    CxMempool     *mp;
     const CxAllocator *allocator;
     CxList *destroy_handler;
     
+    // document pointer, if this is a document context
+    void          *self_doc;
+    
     void          *document;
     CxList        *documents;
     
     CxMap         *vars;
     
     CxList        *states; // int list
+    CxList        *suppressed_states; // int list
     CxList        *state_widgets; // UiGroupWidget list
     
-    void (*attach_document)(UiContext *ctx, void *document);
-    void (*detach_document2)(UiContext *ctx, void *document); 
+    CxMap         *actions; // key: action name (string), value: UiAction
+    CxList        *action_bindings; // UiActionBinding list
     
     char          *title;
     
@@ -93,8 +99,19 @@ struct UiContext {
     // attaching a document will automatically detach the current document
     UiBool single_document_mode;
     
-    ui_callback   close_callback;
-    void          *close_data;
+    ui_callback   onattach;
+    void          *onattachdata;
+    
+    ui_callback   ondetach;
+    void          *ondetachdata;
+    
+    ui_callback   onattachmentstatuschange;
+    void          *onattachmentstatuschangedata;
+    
+    ui_callback   onclose;
+    void          *onclosedata;
+    
+    unsigned int  ref;
 };
 
 struct UiVar {
@@ -124,15 +141,20 @@ void uic_init_global_context(void);
 UiContext* uic_context(UiObject *toplevel, CxMempool *mp);
 UiContext* uic_root_context(UiContext *ctx);
 void uic_context_add_destructor(UiContext *ctx, cx_destructor_func func, void *data);
+void uic_context_remove_destructor(UiContext *ctx, void *data);
 
 void uic_context_prepare_close(UiContext *ctx);
+void uic_context_destroy(UiContext *ctx, void *document);
 
+void uic_context_update_bindings(UiContext *ctx);
 void uic_context_attach_document(UiContext *ctx, void *document);
 void uic_context_detach_document(UiContext *ctx, void *document);
 void uic_context_attach_context(UiContext *ctx, UiContext *doc_ctx); // TODO
 void uic_context_detach_context(UiContext *ctx, UiContext *doc_ctx); // TODO
 void uic_context_detach_all(UiContext *ctx);
 
+void uic_send_status_change(UiContext *ctx, UiObject *obj);
+
 UiVar* uic_get_var(UiContext *ctx, const char *name);
 UiVar* uic_get_var_t(UiContext *ctx, const char *name, UiVarType type);
 UiVar* uic_create_var(UiContext *ctx, const char *name, UiVarType type);
@@ -150,12 +172,26 @@ const char *uic_type2str(UiVarType type);
 
 void uic_reg_var(UiContext *ctx, const char *name, UiVarType type, void *value);
 
+void uic_widget_set_visibility_states(UiContext *ctx, UIWIDGET widget, const int *states);
 size_t uic_state_array_size(const int *states);
 void uic_check_state_widgets(UiContext *ctx);
 void uic_add_state_widget(UiContext *ctx, void *widget, ui_enablefunc enable, CxList *states);
 void uic_add_state_widget_i(UiContext *ctx, void *widget, ui_enablefunc enable, const int *states, size_t numstates);
 void uic_remove_state_widget(UiContext *ctx, void *widget);
 
+UiContext* uic_obj_context(UiContext *ctx);
+
+UIEXPORT void ui_context_onattach(UiContext *ctx, ui_callback cb, void *data);
+UIEXPORT void ui_context_ondetach(UiContext *ctx, ui_callback cb, void *data);
+UIEXPORT void ui_context_onattachmentstatuschange(UiContext *ctx, ui_callback cb, void *data);
+UIEXPORT void ui_context_onattach_action(UiContext *ctx, const char *action);
+UIEXPORT void ui_context_ondetach_action(UiContext *ctx, const char *action);
+UIEXPORT void ui_context_onattachmentstatuschange_action(UiContext *ctx, const char *action);
+
+UIEXPORT int ui_context_is_attached(UiContext *ctx);
+UIEXPORT int ui_context_is_attached_to_obj(UiContext *ctx);
+UIEXPORT UiObject* ui_context_get_parent_obj(UiContext *ctx);
+
 #ifdef __cplusplus
 }
 #endif
index 3eb5874d870d9989fd28d3b6fbbb0f5ce45ac2c3..287b5b51f81d7dd1001b5c0aba93a492b540f7eb 100644 (file)
@@ -45,24 +45,27 @@ void* ui_document_new(size_t size) {
     
     UiDoc *document = cxCalloc(a, sizeof(UiDoc) + size, 1);
     document->ctx = ctx;
-    return &document->doc;
+    ctx->self_doc = &document->doc;
+    return ctx->self_doc;
 }
 
 void ui_document_destroy(void *doc) {
+    uic_context_destroy(ui_document_context(doc), doc);
+}
+
+void ui_document_ref(void *doc) {
     UiContext *ctx = ui_document_context(doc);
     if(ctx) {
-        UiEvent ev;
-        ev.window = NULL;
-        ev.document = doc;
-        ev.obj = NULL;
-        ev.eventdata = NULL;
-        ev.eventdatatype = 0;
-        ev.intval = 0;
-
-        if(ctx->close_callback) {
-            ctx->close_callback(&ev, ctx->close_data);
+        ctx->ref++;
+    }
+}
+
+void ui_document_unref(void *doc) {
+    UiContext *ctx = ui_document_context(doc);
+    if(ctx) {
+        if(--ctx->ref == 0) {
+            uic_context_destroy(ctx, doc);
         }
-        cxMempoolFree(ctx->mp);
     }
 }
 
@@ -75,3 +78,52 @@ UiContext* ui_document_context(void *doc) {
         return NULL;
     }
 }
+
+void* ui_context_document(UiContext *ctx) {
+    return ctx->self_doc;
+}
+
+UiObject* ui_context_obj(UiContext *ctx) {
+    return ctx->obj;
+}
+
+void ui_document_onattach(void *doc, ui_callback cb, void *data) {
+    UiContext *ctx = ui_document_context(doc);
+    ui_context_onattach(ctx, cb, data);
+}
+
+void ui_document_ondetach(void *doc, ui_callback cb, void *data) {
+    UiContext *ctx = ui_document_context(doc);
+    ui_context_ondetach(ctx, cb, data);
+}
+
+void  ui_document_onattachmentstatuschange(void *doc, ui_callback cb, void *data) {
+    UiContext *ctx = ui_document_context(doc);
+    ui_context_onattachmentstatuschange(ctx, cb, data);
+}
+
+void ui_document_onattach_action(void *doc, const char *action) {
+    UiContext *ctx = ui_document_context(doc);
+    ui_context_onattach_action(ctx, action);
+}
+
+void ui_document_ondetach_action(void *doc, const char *action) {
+    UiContext *ctx = ui_document_context(doc);
+    ui_context_ondetach_action(ctx, action);
+}
+
+void  ui_document_onattachmentstatuschange_action(void *doc, const char *action) {
+    UiContext *ctx = ui_document_context(doc);
+    ui_context_onattachmentstatuschange_action(ctx, action);
+}
+
+
+int ui_document_is_attached(void *doc) {
+    UiContext *ctx = ui_document_context(doc);
+    return ui_context_is_attached(ctx);
+}
+
+int ui_document_is_attached_to_obj(void *doc) {
+    UiContext *ctx = ui_document_context(doc);
+    return ui_context_is_attached_to_obj(ctx);
+}
diff --git a/ui/common/icons.c b/ui/common/icons.c
new file mode 100644 (file)
index 0000000..377b1a7
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2026 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "icons.h"
+
+const char* ui_icon_name(enum UiIconId icon_id) {
+    switch(icon_id) {
+        case UI_ICON_ID_HOME                 : return UI_ICON_HOME;
+        case UI_ICON_ID_NEW_WINDOW           : return UI_ICON_NEW_WINDOW;
+        case UI_ICON_ID_NEW_TAB              : return UI_ICON_NEW_TAB;
+        case UI_ICON_ID_NEW_FOLDER           : return UI_ICON_NEW_FOLDER;
+        case UI_ICON_ID_NEW_DOCUMENT         : return UI_ICON_NEW_DOCUMENT;
+        case UI_ICON_ID_NEW_APPOINTMENT      : return UI_ICON_NEW_APPOINTMENT;
+        case UI_ICON_ID_NEW_CHAT_MESSAGE     : return UI_ICON_NEW_CHAT_MESSAGE;
+        case UI_ICON_ID_NEW_CONTACT          : return UI_ICON_NEW_CONTACT;
+        case UI_ICON_ID_NEW_MAIL             : return UI_ICON_NEW_MAIL;
+        case UI_ICON_ID_ADD_BOOKMARK         : return UI_ICON_ADD_BOOKMARK;
+        case UI_ICON_ID_ADD_IMAGE            : return UI_ICON_ADD_IMAGE;
+        case UI_ICON_ID_ADD_LINK             : return UI_ICON_ADD_LINK;
+        case UI_ICON_ID_ADD_TEXT             : return UI_ICON_ADD_TEXT;
+        case UI_ICON_ID_ADD                  : return UI_ICON_ADD;
+        case UI_ICON_ID_REMOVE               : return UI_ICON_REMOVE;
+        case UI_ICON_ID_REFRESH              : return UI_ICON_REFRESH;
+        case UI_ICON_ID_UPLOAD               : return UI_ICON_UPLOAD;
+        case UI_ICON_ID_SAVE_LOCAL           : return UI_ICON_SAVE_LOCAL;
+        case UI_ICON_ID_EDIT_COPY            : return UI_ICON_EDIT_COPY;
+        case UI_ICON_ID_EDIT_CUT             : return UI_ICON_EDIT_CUT;
+        case UI_ICON_ID_EDIT_DELETE          : return UI_ICON_EDIT_DELETE;
+        case UI_ICON_ID_EDIT_PASTE           : return UI_ICON_EDIT_PASTE ;
+        case UI_ICON_ID_UNDO                 : return UI_ICON_UNDO;
+        case UI_ICON_ID_REDO                 : return UI_ICON_REDO;
+        case UI_ICON_ID_SIDEBAR_LEFT         : return UI_ICON_SIDEBAR_LEFT;
+        case UI_ICON_ID_SIDEBAR_RIGHT        : return UI_ICON_SIDEBAR_RIGHT;
+        case UI_ICON_ID_GO_BACK              : return UI_ICON_GO_BACK;
+        case UI_ICON_ID_GO_FORWARD           : return UI_ICON_GO_FORWARD ;
+        case UI_ICON_ID_GO_UP                : return UI_ICON_GO_UP;
+        case UI_ICON_ID_GO_DOWN              : return UI_ICON_GO_DOWN;
+        case UI_ICON_ID_VIEW_LIST            : return UI_ICON_VIEW_LIST;
+        case UI_ICON_ID_VIEW_GRID            : return UI_ICON_VIEW_GRID;
+        case UI_ICON_ID_VIEW_DUAL            : return UI_ICON_VIEW_DUAL;
+        case UI_ICON_ID_VIEW_FULLSCREEN      : return UI_ICON_VIEW_FULLSCREEN;
+        case UI_ICON_ID_VIEW_RESTORE         : return UI_ICON_VIEW_RESTORE;
+        case UI_ICON_ID_TEXT_BOLD            : return UI_ICON_TEXT_BOLD;
+        case UI_ICON_ID_TEXT_ITALIC          : return UI_ICON_TEXT_ITALIC;
+        case UI_ICON_ID_TEXT_UNDERLINE       : return UI_ICON_TEXT_UNDERLINE;
+        case UI_ICON_ID_LIST_BULLET          : return UI_ICON_LIST_BULLET ;
+        case UI_ICON_ID_LIST_ORDERED         : return UI_ICON_LIST_ORDERED;
+        case UI_ICON_ID_LIST_CHECK           : return UI_ICON_LIST_CHECK;
+        case UI_ICON_ID_CHECKBOX             : return UI_ICON_CHECKBOX;
+        case UI_ICON_ID_STAR                 : return UI_ICON_STAR;
+        case UI_ICON_ID_VIEW_REVEAL          : return UI_ICON_VIEW_REVEAL;
+        case UI_ICON_ID_VIEW_CONCEAL         : return UI_ICON_VIEW_CONCEAL;
+        case UI_ICON_ID_SETTINGS             : return UI_ICON_SETTINGS;
+        case UI_ICON_ID_MEDIA_PLAY           : return UI_ICON_MEDIA_PLAY;
+        case UI_ICON_ID_MEDIA_STOP           : return UI_ICON_MEDIA_STOP;
+        case UI_ICON_ID_MEDIA_PAUSE          : return UI_ICON_MEDIA_PAUSE;
+        case UI_ICON_ID_MEDIA_SEEK_BACKWARD  : return UI_ICON_MEDIA_SEEK_BACKWARD;
+        case UI_ICON_ID_MEDIA_SEEK_FORWARD   : return UI_ICON_MEDIA_SEEK_FORWARD;
+        case UI_ICON_ID_MEDIA_SKIP_BACKWARD  : return UI_ICON_MEDIA_SKIP_BACKWARD;
+        case UI_ICON_ID_MEDIA_SKIP_FORWARD   : return UI_ICON_MEDIA_SKIP_FORWARD;
+        case UI_ICON_ID_CALL_START           : return UI_ICON_CALL_START;
+        case UI_ICON_ID_CALL_STOP            : return UI_ICON_CALL_STOP;
+        case UI_ICON_ID_CALL_INCOMING        : return UI_ICON_CALL_INCOMING;
+        case UI_ICON_ID_CALL_OUTGOING        : return UI_ICON_CALL_OUTGOING;
+        case UI_ICON_ID_MICROPHONE_ON        : return UI_ICON_MICROPHONE_ON;
+        case UI_ICON_ID_MICROPHONE_OFF       : return UI_ICON_MICROPHONE_OFF;
+        case UI_ICON_ID_LOCKED               : return UI_ICON_LOCKED;
+        case UI_ICON_ID_UNLOCKED             : return UI_ICON_UNLOCKED;
+        case UI_ICON_ID_SECURE               : return UI_ICON_SECURE;
+        case UI_ICON_ID_INSECURE             : return UI_ICON_INSECURE;    
+    }
+    return NULL;
+}
diff --git a/ui/common/icons.h b/ui/common/icons.h
new file mode 100644 (file)
index 0000000..d7062a6
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2026 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef UIC_ICONS_H
+#define UIC_ICONS_H
+
+#include "../ui/icons.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* UIC_ICONS_H */
+
index b0a5d2e6bad0e69bdf40c2e182563cf6e54feeaa..83eb2589e238701b32fbcdf5d1e2ac53e0ecbf6a 100644 (file)
@@ -44,6 +44,17 @@ static int menu_item_counter = 0;
 static void *tmp_eventdata;
 static int tmp_eventdata_type;
 
+
+static void* getvalue_wrapper(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) {
+    ui_getvaluefunc getvalue = (ui_getvaluefunc)userdata;
+    return getvalue(elm, col);
+}
+
+static void* str_getvalue(UiList *list, void *elm, int row, int col, void *userdata, UiBool *freeResult) {
+    return elm;
+}
+
+
 void uic_set_tmp_eventdata(void *eventdata, int type) {
     tmp_eventdata = eventdata;
     tmp_eventdata_type = type;
@@ -148,6 +159,7 @@ void ui_menuitem_create(UiMenuItemArgs *args) {
     item->item.next = NULL;
     item->item.type = UI_MENU_ITEM;
 
+    item->action = nl_strdup(args->action);
     item->label = nl_strdup(args->label);
     item->icon = nl_strdup(args->icon);
     item->userdata = args->onclickdata;
@@ -207,7 +219,15 @@ void ui_menu_itemlist_create(UiMenuItemListArgs *args) {
     item->item.prev = NULL;
     item->item.next = NULL;
     item->item.type = UI_MENU_ITEM_LIST;
-    item->getvalue = args->getvalue;
+    if(args->getvalue2) {
+        item->getvalue = args->getvalue2;
+        item->getvaluedata = args->getvaluedata;
+    } else if(args->getvalue) {
+        item->getvalue = getvalue_wrapper;
+        item->getvaluedata = (void*)args->getvalue;
+    } else {
+        item->getvalue = str_getvalue;
+    }
     item->callback = args->onselect;
     item->userdata = args->onselectdata;
     item->varname = nl_strdup(args->varname);
@@ -222,6 +242,15 @@ void ui_menu_checkitemlist_create(UiMenuItemListArgs *args) {
     item->item.prev = NULL;
     item->item.next = NULL;
     item->item.type = UI_MENU_CHECKITEM_LIST;
+    if(args->getvalue2) {
+        item->getvalue = args->getvalue2;
+        item->getvaluedata = args->getvaluedata;
+    } else if(args->getvalue) {
+        item->getvalue = getvalue_wrapper;
+        item->getvaluedata = (void*)args->getvalue;
+    } else {
+        item->getvalue = str_getvalue;
+    }
     item->callback = args->onselect;
     item->userdata = args->onselectdata;
     item->varname = nl_strdup(args->varname);
@@ -235,6 +264,15 @@ void ui_menu_radioitemlist_create(UiMenuItemListArgs *args) {
     item->item.prev = NULL;
     item->item.next = NULL;
     item->item.type = UI_MENU_RADIOITEM_LIST;
+    if(args->getvalue2) {
+        item->getvalue = args->getvalue2;
+        item->getvaluedata = args->getvaluedata;
+    } else if(args->getvalue) {
+        item->getvalue = getvalue_wrapper;
+        item->getvaluedata = (void*)args->getvalue;
+    } else {
+        item->getvalue = str_getvalue;
+    }
     item->callback = args->onselect;
     item->userdata = args->onselectdata;
     item->varname = nl_strdup(args->varname);
index 9aea5789962c531fddfc7e618f7307197a1c275f..510e504f100f1fa0a6a5466fbc7e67aede2848d4 100644 (file)
@@ -76,6 +76,7 @@ struct UiMenu {
 struct UiMenuItem {
     UiMenuItemI    item;
     ui_callback    callback;
+    char           *action;
     char           *label;
     char           *icon;
     void           *userdata;
@@ -106,12 +107,13 @@ struct UiMenuRadioItem {
 };
 
 struct UiMenuItemList {
-    UiMenuItemI     item;
-    ui_getvaluefunc getvalue;
-    ui_callback     callback;
-    void            *userdata;
-    char            *varname;
-    UiBool          addseparator;
+    UiMenuItemI      item;
+    ui_getvaluefunc2 getvalue;
+    void             *getvaluedata;
+    ui_callback      callback;
+    void             *userdata;
+    char             *varname;
+    UiBool           addseparator;
 };
 
 
index f1582307ef28081cd2889fac28f2fa6c8964720b..8ea5b37e6438154a3ecdf73f2b1cabeb283e650b 100644 (file)
@@ -39,6 +39,8 @@
 static CxList *creation_callbacks;
 static CxList *destruction_callbacks;
 
+static CxList *objects;
+
 typedef struct objcallback {
     ui_object_callback func;
     void *userdata;
@@ -60,7 +62,18 @@ void ui_register_object_destruction_callback(ui_object_callback func, void *user
     cxListAdd(destruction_callbacks, &cb);
 }
 
+UiObject* ui_dummy_object(void) {
+    UiObject *obj = uic_object_new_toplevel();
+    obj->ref = 1;
+    return obj;
+}
+
 void uic_object_created(UiObject *obj) {
+    if(!objects) {
+        objects = cxLinkedListCreate(NULL, CX_STORE_POINTERS);
+    }
+    cxListAdd(objects, obj);
+    
     CxIterator i = cxListIterator(creation_callbacks);
     cx_foreach(objcallback *, cb, i) {
         cb->func(obj, cb->userdata);
@@ -68,12 +81,20 @@ void uic_object_created(UiObject *obj) {
 }
 
 void uic_object_destroyed(UiObject *obj) {
+    if(objects) {
+        cxListFindRemove(objects, obj);
+    }
+    
     CxIterator i = cxListIterator(destruction_callbacks);
     cx_foreach(objcallback *, cb, i) {
         cb->func(obj, cb->userdata);
     }
 }
 
+CxList* uic_object_list(void) {
+    return objects ? objects : cxEmptyList;
+}
+
 void ui_object_ref(UiObject *obj) {
     obj->ref++;
 }
@@ -82,28 +103,20 @@ int ui_object_unref(UiObject *obj) {
     // it is possible to have 0 references, in case
     // a window was created but ui_show was never called
     if(obj->ref == 0 || --obj->ref == 0) {
+        uic_context_prepare_close(obj->ctx);
         if(obj->destroy) {
             obj->destroy(obj);
+        } else {
+            uic_object_destroy(obj);
         }
-        uic_object_destroy(obj);
         return 0;
     }
     return 1;
 }
 
 void uic_object_destroy(UiObject *obj) {
-    if(obj->ctx->close_callback) {
-        UiEvent ev;
-        ev.window = obj->window;
-        ev.document = obj->ctx->document;
-        ev.obj = obj;
-        ev.eventdata = NULL;
-        ev.eventdatatype = 0;
-        ev.intval = 0;
-        obj->ctx->close_callback(&ev, obj->ctx->close_data);
-    }
     uic_object_destroyed(obj);
-    cxMempoolFree(obj->ctx->mp);
+    uic_context_destroy(obj->ctx, obj->ctx->document);
 }
 
 UiObject* uic_object_new_toplevel(void) {
@@ -123,7 +136,7 @@ UiObject* uic_ctx_object_new(UiContext *ctx, UIWIDGET widget) {
     return newobj;
 }
 
-void uic_object_push_container(UiObject *toplevel, UiContainerX *newcontainer) {
+void uic_object_push_container(UiObject *toplevel, UiContainer *newcontainer) {
     newcontainer->prev = toplevel->container_end;
     if(toplevel->container_end) {
         toplevel->container_end->next = newcontainer;
@@ -152,8 +165,8 @@ void uic_object_pop_container(UiObject *toplevel) {
  */
 void uic_object_remove_second_last_container(UiObject *toplevel) {
     if(toplevel->container_end && toplevel->container_end->prev) {
-        UiContainerX *end = toplevel->container_end;
-        UiContainerX *rm = toplevel->container_end->prev;
+        UiContainer *end = toplevel->container_end;
+        UiContainer *rm = toplevel->container_end->prev;
         
         end->prev = rm->prev;
         if(rm->prev) {
index 43278752ef904f4cef2741721d3b639f66ff6832..7ef1e1232af0269b722d7a7c5249cf38bfe88c26 100644 (file)
@@ -50,12 +50,14 @@ void uic_object_created(UiObject *obj);
 void uic_object_destroyed(UiObject *obj);
     
 void uic_object_destroy(UiObject *obj);
+
+CxList* uic_object_list(void);
     
 UiObject* uic_object_new_toplevel(void);
 UiObject* uic_object_new(UiObject *toplevel, UIWIDGET widget);
 UiObject* uic_ctx_object_new(UiContext *ctx, UIWIDGET widget);
 
-void uic_object_push_container(UiObject *toplevel, UiContainerX *newcontainer);
+void uic_object_push_container(UiObject *toplevel, UiContainer *newcontainer);
 void uic_object_pop_container(UiObject *toplevel);
 void uic_object_remove_second_last_container(UiObject *toplevel);
 
index e69125caa6865580629a16a70b5cf06e5ce2eea5..35fb9d6d28255f2706c28bf13fbc1c2b1ae86014 100644 (file)
@@ -32,6 +32,7 @@ COMMON_OBJPRE = $(OBJ_DIR)$(COMMON_SRC_DIR)
 COMMON_OBJ = context$(OBJ_EXT)
 COMMON_OBJ += document$(OBJ_EXT)
 COMMON_OBJ += object$(OBJ_EXT)
+COMMON_OBJ += action$(OBJ_EXT)
 COMMON_OBJ += container$(OBJ_EXT)
 COMMON_OBJ += types$(OBJ_EXT)
 COMMON_OBJ += app$(OBJ_EXT)
@@ -44,6 +45,7 @@ COMMON_OBJ += args$(OBJ_EXT)
 COMMON_OBJ += wrapper$(OBJ_EXT)
 COMMON_OBJ += utils$(OBJ_EXT)
 COMMON_OBJ += message$(OBJ_EXT)
+COMMON_OBJ += icons$(OBJ_EXT)
 
 TOOLKITOBJS += $(COMMON_OBJ:%=$(COMMON_OBJPRE)uic_%)
 TOOLKITSOURCE += $(COMMON_OBJ:%$(OBJ_EXT)=common/%.c)
index 642603da398d26f74faabc48f1ac20b945036bcb..29c8ce60f47ec64f988abdbeb0c26e31ec6787ef 100644 (file)
@@ -62,6 +62,8 @@ static UiBool load_on_startup = TRUE;
 static void *properties_data = NULL;
 static size_t properties_data_length = 0;
 
+static char *config_root = NULL;
+
 void ui_load_properties_file_on_startup(UiBool enable) {
     load_on_startup = enable;
 }
@@ -77,13 +79,26 @@ void ui_set_properties_data(const char *str, size_t len) {
 }
 
 char* ui_getappdir(void) {
-    if(ui_appname() == NULL) {
+    if(ui_appname() == NULL && config_root == NULL) {
         return NULL;
     }
 
     return ui_configfile(NULL);
 }
 
+void ui_setappdir(const char *path) {
+    free(config_root);
+    if(path) {
+        cxmutstr cfgpath = cx_strdup(path);
+        config_root = cfgpath.ptr;
+        if(cfgpath.length > 0 && cfgpath.ptr[cfgpath.length-1] == '/') {
+            config_root[cfgpath.length-1] = 0;
+        }
+    } else {
+        config_root = NULL;
+    }
+}
+
 #ifndef _WIN32
 #define UI_PATH_SEPARATOR '/'
 #define UI_ENV_HOME "HOME"
@@ -95,6 +110,16 @@ char* ui_getappdir(void) {
 #define UI_XDG_CONFIG_HOME_VAR "XDG_CONFIG_HOME"
 
 char* ui_configfile(const char *name) {
+    if(config_root) {
+        if(!name) {
+            return strdup(config_root);
+        } else if(name[0] == '/') {
+            return cx_strdup(cx_strcat(CX_NULLSTR, 2, cx_str(config_root), cx_str(name))).ptr;
+        } else {
+            return cx_strdup(cx_strcat(CX_NULLSTR, 3, cx_str(config_root), cx_str("/"), cx_str(name))).ptr;
+        }
+    }
+    
     const char *appname = ui_appname();
     if(!appname) {
         return NULL;
@@ -209,11 +234,6 @@ void uic_load_app_properties() {
         return;
     }
     
-    if(!ui_appname()) {
-        // applications without name cannot load app properties
-        return;
-    }
-    
     char *dir = ui_configfile(NULL);
     if(!dir) {
         return;
index 3b4c096509861abc266c59e5698daf5aa16d342e..0710dcd48aa4cfd2674de020072f0207a93439a7 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "threadpool.h"
 #include "context.h"
+#include <cx/linked_list.h>
 
 #include <pthread.h>
 #include <stdio.h>
 
 static threadpool_job kill_job;
 
+
+
+static pthread_mutex_t mc_buffer_mutex;
+static pthread_cond_t  mc_buffer_available;
+static CxList *mainthread_call_buffer;
+static volatile int mainthread_call_buffered = 0;
+
+typedef struct UiMainCall {
+    ui_threadfunc func;
+    void *data;
+} UiMainCall;
+
+void uic_init_threads(void) {
+    pthread_mutex_init(&mc_buffer_mutex, NULL);
+    pthread_cond_init(&mc_buffer_available, NULL);
+    mainthread_call_buffer = cxLinkedListCreate(NULL, sizeof(UiMainCall));
+}
+
+int uic_mainthread_calls_is_buffered(void) {
+    return mainthread_call_buffered;
+}
+
+void uic_add_buffered_mainthread_call(ui_threadfunc func, void *data) {
+    pthread_mutex_lock(&mc_buffer_mutex);
+    UiMainCall call;
+    call.func = func;
+    call.data = data;
+    cxListAdd(mainthread_call_buffer, &call);
+    pthread_cond_signal(&mc_buffer_available);
+    pthread_mutex_unlock(&mc_buffer_mutex);
+}
+
+
+void ui_buffer_mainthread_calls(UiBool enable_buffering) {
+    mainthread_call_buffered = enable_buffering;
+    if(!enable_buffering) {
+        ui_exec_buffered_mainthread_calls();
+    }
+}
+
+static void exec_buffered_calls(void) {
+    CxIterator i = cxListIterator(mainthread_call_buffer);
+    cx_foreach(UiMainCall *, call, i) {
+        if(call->func) {
+            call->func(call->data);
+        }
+    }
+    cxListClear(mainthread_call_buffer);
+}
+
+void ui_exec_buffered_mainthread_calls(void) {
+    pthread_mutex_lock(&mc_buffer_mutex);
+    exec_buffered_calls();
+    pthread_mutex_unlock(&mc_buffer_mutex);
+}
+
+UIEXPORT void ui_exec_buffered_mainthread_calls_wait(int timeout) {
+    struct timespec ts;
+    if(timeout > 0) {
+        clock_gettime(CLOCK_REALTIME, &ts);
+        ts.tv_sec += timeout;
+    }
+    
+    pthread_mutex_lock(&mc_buffer_mutex);
+    while(cxListSize(mainthread_call_buffer) == 0) {
+        if(timeout > 0) {
+            if(pthread_cond_timedwait(&mc_buffer_available, &mc_buffer_mutex, &ts)) {
+                break;
+            }
+        } else {
+            pthread_cond_wait(&mc_buffer_available, &mc_buffer_mutex);
+        }
+    }
+    exec_buffered_calls();
+    pthread_mutex_unlock(&mc_buffer_mutex);
+}
+
 UiThreadpool* threadpool_new(int min, int max) {
     UiThreadpool *pool = malloc(sizeof(UiThreadpool));
     pool->queue = ui_queue_create();
index 4a997f6802a0cab9f4af2a630c935749263f9720..8413b240acdece14f2bd9e7485316f7c1844b67b 100644 (file)
 extern "C" {
 #endif
     
+void uic_init_threads(void);
+int uic_mainthread_calls_is_buffered(void);
+void uic_add_buffered_mainthread_call(ui_threadfunc func, void *data);
+    
 typedef struct UiQueueElm UiQueueElm;
 typedef struct UiQueue    UiQueue;
     
index f87e02a373a8fd97ca16e63ef1b9b3ddf98a47ee..552b8e12dc26d279c94a77bbe555094ebe8182ca 100644 (file)
@@ -57,6 +57,7 @@ static UiToolbarItemArgs itemargs_copy(UiToolbarItemArgs *args, size_t *ngroups,
     newargs.tooltip = nl_strdup(args->tooltip);\r
     newargs.onclick = args->onclick;\r
     newargs.onclickdata = args->onclickdata;\r
+    newargs.action = nl_strdup(args->action);\r
     newargs.states = uic_copy_states(args->states, ngroups);\r
     newargs.visibility_states = uic_copy_states(args->visibility_states, nvstates);\r
     return newargs;\r
@@ -78,6 +79,26 @@ static UiToolbarToggleItemArgs toggleitemargs_copy(UiToolbarToggleItemArgs *args
     newargs.varname = nl_strdup(args->varname);\r
     newargs.onchange = args->onchange;\r
     newargs.onchangedata = args->onchangedata;\r
+    newargs.action = nl_strdup(args->action);\r
+    newargs.states = uic_copy_states(args->states, ngroups);\r
+    newargs.visibility_states = uic_copy_states(args->visibility_states, nvstates);\r
+    return newargs;\r
+}\r
+\r
+static UiToolbarContentToggleItemArgs contenttoggleitemargs_copy(UiToolbarContentToggleItemArgs *args, size_t *ngroups, size_t *nvstates) {\r
+    UiToolbarContentToggleItemArgs newargs;\r
+    newargs.label0 = nl_strdup(args->label0);\r
+    newargs.icon0 = nl_strdup(args->icon0);\r
+    newargs.tooltip0 = nl_strdup(args->tooltip0);\r
+    newargs.label1 = nl_strdup(args->label1);\r
+    newargs.icon1 = nl_strdup(args->icon1);\r
+    newargs.tooltip1 = nl_strdup(args->tooltip1);\r
+    newargs.varname = nl_strdup(args->varname);\r
+    newargs.onchange = args->onchange;\r
+    newargs.onchangedata = args->onchangedata;\r
+    newargs.action = nl_strdup(args->action);\r
+    newargs.toggled_by_state = args->toggled_by_state;\r
+    newargs.istogglebutton = args->istogglebutton;\r
     newargs.states = uic_copy_states(args->states, ngroups);\r
     newargs.visibility_states = uic_copy_states(args->visibility_states, nvstates);\r
     return newargs;\r
@@ -90,6 +111,13 @@ void ui_toolbar_toggleitem_create(const char* name, UiToolbarToggleItemArgs *arg
     cxMapPut(toolbar_items, name, item);\r
 }\r
 \r
+void ui_toolbar_content_toggleitem_create(const char* name, UiToolbarContentToggleItemArgs *args) {\r
+    UiToolbarContentToggleItem* item = malloc(sizeof(UiToolbarContentToggleItem));\r
+    item->item.type = UI_TOOLBAR_CONTENT_TOGGLEITEM;\r
+    item->args = contenttoggleitemargs_copy(args, &item->nstates, &item->nvstates);\r
+    cxMapPut(toolbar_items, name, item);\r
+}\r
+\r
 static UiToolbarMenuArgs menuargs_copy(UiToolbarMenuArgs *args, size_t *nvstates) {\r
     UiToolbarMenuArgs newargs;\r
     newargs.label = nl_strdup(args->label);\r
index 9ae60f07cb5b0c04a0cd70b2ae0bcd70441ae49f..dd792644c20b5d7ec5b50e6ff3bdc11befb31d9e 100644 (file)
 extern "C" {\r
 #endif\r
 \r
-typedef struct UiToolbarItemI      UiToolbarItemI;\r
+typedef struct UiToolbarItemI               UiToolbarItemI;\r
 \r
-typedef struct UiToolbarItem       UiToolbarItem;\r
-typedef struct UiToolbarToggleItem UiToolbarToggleItem;\r
+typedef struct UiToolbarItem                UiToolbarItem;\r
+typedef struct UiToolbarToggleItem          UiToolbarToggleItem;\r
+typedef struct UiToolbarContentToggleItem   UiToolbarContentToggleItem;\r
 \r
-typedef struct UiToolbarMenuItem   UiToolbarMenuItem;\r
+typedef struct UiToolbarMenuItem            UiToolbarMenuItem;\r
 \r
 enum UiToolbarItemType {\r
     UI_TOOLBAR_ITEM = 0,\r
     UI_TOOLBAR_TOGGLEITEM,\r
+    UI_TOOLBAR_CONTENT_TOGGLEITEM,\r
     UI_TOOLBAR_MENU\r
 };\r
 \r
@@ -73,6 +75,13 @@ struct UiToolbarToggleItem {
     size_t nvstates;\r
 };\r
 \r
+struct UiToolbarContentToggleItem {\r
+    UiToolbarItemI item;\r
+    UiToolbarContentToggleItemArgs args;\r
+    size_t nstates;\r
+    size_t nvstates;\r
+};\r
+\r
 struct UiToolbarMenuItem {\r
     UiToolbarItemI item;\r
     UiMenu menu;\r
index 2f65c16083d8fe68c40c80b399593ee1f321ff8b..fd1712bf8bec715599d71297c7f221bd32b2655d 100644 (file)
@@ -100,7 +100,9 @@ void ui_notify_evt(UiObserver *observer, UiEvent *event) {
 /* --------------------------- UiList --------------------------- */
 
 void uic_ucx_list_init(UiContext *ctx, UiList *list, void *unused) {
-    list->data = cxArrayListCreate(ctx->mp->allocator, CX_STORE_POINTERS, 32);
+    const CxAllocator *a = ctx ? ctx->allocator : cxDefaultAllocator;
+    list->destroy = uic_ucx_list_destroy;
+    list->data = cxArrayListCreate(a, CX_STORE_POINTERS, 32);
     list->first = ui_list_first;
     list->next = ui_list_next;
     list->get = ui_list_get;
@@ -109,7 +111,6 @@ void uic_ucx_list_init(UiContext *ctx, UiList *list, void *unused) {
 
 void uic_ucx_list_destroy(UiContext *ctx, UiList *list, void *unused) {
     cxListFree(list->data);
-    ui_free(ctx, list);
 }
 
 UiList* ui_list_new(UiContext *ctx, const char *name) {
@@ -117,11 +118,12 @@ UiList* ui_list_new(UiContext *ctx, const char *name) {
 }
 
 UiList* ui_list_new2(UiContext *ctx, const char *name, ui_list_init_func listinit, void *userdata) {
-    UiList *list = cxMalloc(ctx->mp->allocator, sizeof(UiList));
+    UiList *list = ui_malloc(ctx, sizeof(UiList));
     memset(list, 0, sizeof(UiList));
     listinit(ctx, list, userdata);
+    list->save_selection = TRUE;
     
-    if(name) {
+    if(name && ctx) {
         uic_reg_var(ctx, name, UI_VAR_LIST, list);
     }
     
@@ -129,12 +131,15 @@ UiList* ui_list_new2(UiContext *ctx, const char *name, ui_list_init_func listini
 }
 
 void ui_list_free(UiContext *ctx, UiList *list) {
-    if(!default_list_destroy) {
+    if(list->destroy) {
+        list->destroy(ctx, list, NULL);
+    } else if(!default_list_destroy) {
         uic_ucx_list_destroy(ctx, list, NULL);
     } else {
         default_list_destroy(ctx, list, default_list_destroy_userdata);
     }
-    
+    ui_list_selection_free(list->saved_selection);
+    ui_free(ctx, list);
 }
 
 void* ui_list_first(UiList *list) {
@@ -153,7 +158,7 @@ void* ui_list_next(UiList *list) {
 }
 
 void* ui_list_get(UiList *list, int i) {
-    return cxListAt(list->data, i);
+    return i >= 0 ? cxListAt(list->data, i) : NULL;
 }
 
 int ui_list_count(UiList *list) {
@@ -168,8 +173,14 @@ void ui_list_prepend(UiList *list, void *data) {
     cxListInsert(list->data, 0, data);
 }
 
+void ui_list_insert(UiList *list, int index, void *data) {
+    cxListInsert(list->data, (size_t)index, data);
+}
+
 void ui_list_remove(UiList *list, int i) {
-    cxListRemove(list->data, i);
+    if(i >= 0) {
+        cxListRemove(list->data, i);
+    }
 }
 
 void ui_list_clear(UiList *list) {
@@ -196,6 +207,12 @@ UiListSelection ui_list_get_selection(UiList *list) {
     }
 }
 
+UIEXPORT void ui_list_set_selection(UiList *list, UiListSelection sel) {
+    if(list->setselection) {
+        list->setselection(list, sel);
+    }
+}
+
 void ui_list_addobsv(UiList *list, ui_callback f, void *data) {
     list->observers = ui_add_observer(list->observers, f, data);
 }
@@ -204,6 +221,11 @@ void ui_list_notify(UiList *list) {
     ui_notify(list->observers, list);
 }
 
+void ui_list_clear_saved_selection(UiList *list) {
+    ui_list_selection_free(list->saved_selection);
+    list->saved_selection = NULL;
+}
+
 
 typedef struct {
     int  type;
@@ -213,6 +235,7 @@ typedef struct {
 UiModel* ui_model(UiContext *ctx, ...) {
     UiModel *info = ui_calloc(ctx, 1, sizeof(UiModel));
     info->ctx = ctx;
+    info->ref = 1;
     
     va_list ap;
     va_start(ap, ctx);
@@ -264,6 +287,7 @@ static void model_notify_observer(UiModel *model, int insert, int delete) {
 UiModel* ui_model_new(UiContext *ctx) {
     UiModel *info = ui_calloc(ctx, 1, sizeof(UiModel));
     info->ctx = ctx;
+    info->ref = 1;
     info->alloc = UI_MODEL_DEFAULT_ALLOC_SIZE;
     info->types = ui_calloc(ctx, UI_MODEL_DEFAULT_ALLOC_SIZE, sizeof(UiModelType));
     info->titles = ui_calloc(ctx, UI_MODEL_DEFAULT_ALLOC_SIZE, sizeof(char*));
@@ -360,7 +384,7 @@ void ui_model_remove_observer(UiModel *model, void *data) {
 
 void ui_model_free(UiModel *mi) {
     UiContext *ctx = mi->ctx;
-    const CxAllocator* a = ctx->allocator;
+    const CxAllocator* a = ctx ? ctx->allocator : cxDefaultAllocator;
     for(int i=0;i<mi->columns;i++) {
         ui_free(ctx, mi->titles[i]);
     }
@@ -382,7 +406,7 @@ void ui_model_free(UiModel *mi) {
 UiInteger* ui_int_new(UiContext *ctx, const char *name) {
     UiInteger *i = ui_malloc(ctx, sizeof(UiInteger));
     memset(i, 0, sizeof(UiInteger));
-    if(name) {
+    if(name && ctx) {
         uic_reg_var(ctx, name, UI_VAR_INTEGER, i);
     }
     return i;
@@ -391,7 +415,7 @@ UiInteger* ui_int_new(UiContext *ctx, const char *name) {
 UiDouble* ui_double_new(UiContext *ctx, const char *name) {
     UiDouble *d = ui_malloc(ctx, sizeof(UiDouble));
     memset(d, 0, sizeof(UiDouble));
-    if(name) {
+    if(name && ctx) {
         uic_reg_var(ctx, name, UI_VAR_DOUBLE, d);
     }
     return d;
@@ -407,13 +431,16 @@ UiString* ui_string_new(UiContext *ctx, const char *name) {
     UiString *s = ui_malloc(ctx, sizeof(UiString));
     memset(s, 0, sizeof(UiString));
     ui_set_destructor(s, (ui_destructor_func)string_destroy);
-    if(name) {
+    if(name && ctx) {
         uic_reg_var(ctx, name, UI_VAR_STRING, s);
     }
     return s;
 }
 
 static void text_destroy(UiText *t) {
+    if(t->value.free) {
+        t->value.free(t->value.ptr);
+    }
     if(t->destroy) {
         t->destroy(t);
     }
@@ -423,7 +450,7 @@ UiText* ui_text_new(UiContext *ctx, const char *name) {
     UiText *t = ui_malloc(ctx, sizeof(UiText));
     memset(t, 0, sizeof(UiText));
     ui_set_destructor(t, (ui_destructor_func)text_destroy);
-    if(name) {
+    if(name && ctx) {
         uic_reg_var(ctx, name, UI_VAR_TEXT, t);
     }
     return t;
@@ -432,7 +459,7 @@ UiText* ui_text_new(UiContext *ctx, const char *name) {
 UiRange* ui_range_new(UiContext *ctx, const char *name) {
     UiRange *r = ui_malloc(ctx, sizeof(UiRange));
     memset(r, 0, sizeof(UiRange));
-    if(name) {
+    if(name && ctx) {
         uic_reg_var(ctx, name, UI_VAR_RANGE, r);
     }
     return r;
@@ -447,8 +474,10 @@ static void generic_destroy(UiGeneric *g) {
 UiGeneric* ui_generic_new(UiContext *ctx, const char *name) {
     UiGeneric *g = ui_malloc(ctx, sizeof(UiGeneric));
     memset(g, 0, sizeof(UiGeneric));
-    ui_set_destructor(g, (ui_destructor_func)generic_destroy);
-    if(name) {
+    if(ctx) {
+        ui_set_destructor(g, (ui_destructor_func)generic_destroy);
+    }
+    if(name && ctx) {
         uic_reg_var(ctx, name, UI_VAR_GENERIC, g);
     }
     return g;
@@ -500,7 +529,7 @@ void ui_string_set(UiString* s, const char* value) {
     if (s) {
         if (s->set) {
             ui_setop_enable(TRUE);
-            s->set(s, value);
+            s->set(s, value ? value : "");
             ui_setop_enable(FALSE);
         } else {
             if(s->value.free) {
@@ -530,7 +559,7 @@ void ui_text_set(UiText* s, const char* value) {
     if (s) {
         if (s->set) {
             ui_setop_enable(TRUE);
-            s->set(s, value);
+            s->set(s, value ? value : "");
             ui_setop_enable(FALSE);
         } else {
             if(s->value.free) {
@@ -668,11 +697,15 @@ void uic_text_copy(UiText *from, UiText *to) {
     to->set = from->set;
     to->getsubstr = from->getsubstr;
     to->insert = from->insert;
+    to->replace = from->replace;
     to->setposition = from->setposition;
     to->position = from->position;
+    to->showposition = from->showposition;
+    to->setselection = from->setselection;
     to->selection = from->selection;
     to->length = from->length;
     to->remove = from->remove;
+    to->setreadonly = from->setreadonly;
     to->restore = from->restore;
     to->save = from->save;
     to->destroy = from->destroy;
@@ -731,6 +764,9 @@ void uic_range_save(UiRange *r) {
 
 void uic_generic_save(UiGeneric *g) {
     if(!g->obj) return;
+    // TODO: this leaks memory
+    // we can't just use get on Generic and ignore the result
+    // probably a separate save method is required
     g->get(g);
 }
 
@@ -754,16 +790,27 @@ void uic_string_unbind(UiString *s) {
 }
 
 void uic_text_unbind(UiText *t) {
+    t->obj = NULL;
+    if(t->data1 && t->datatype == UI_TEXT_TYPE_BUFFER) {
+        // the binding functions all work with t->data1, not t->obj
+        // and we don't want to NULL them, because they will be still
+        // functional even without a widget binding
+        return;
+    }
+    
     t->set = NULL;
     t->get = NULL;
     t->getsubstr = NULL;
     t->insert = NULL;
+    t->replace = NULL;
     t->setposition = NULL;
     t->position = NULL;
+    t->showposition = NULL;
     t->selection = NULL;
+    t->setselection = NULL;
     t->length = NULL;
     t->remove = NULL;
-    t->obj = NULL;
+    t->setreadonly = NULL;
 }
 
 void uic_range_unbind(UiRange *r) {
@@ -789,21 +836,52 @@ void uic_generic_unbind(UiGeneric *g) {
 }
 
 
-UIEXPORT UiListSelection ui_list_getselection(UiList *list) {
+
+UiListSelection* ui_list_get_selection_allocated(UiList *list) {
+    UiListSelection *sel = malloc(sizeof(UiListSelection));
+    *sel = ui_list_get_selection(list);
+    return sel;
+    
+}
+
+void ui_list_selection_free(UiListSelection *sel) {
+    if(!sel) {
+        return;
+    }
+    ui_listselection_free(*sel);
+    free(sel);
+}
+
+
+UIEXPORT int ui_list_getselection(UiList *list) {
+    int selection = -1;
     if (list->getselection) {
-        return list->getselection(list);
+        UiListSelection sel = list->getselection(list);
+        if(sel.count > 0) {
+            selection = sel.rows[0];
+        }
+        ui_listselection_free(sel);
     }
-    return (UiListSelection){ 0, NULL };
+    return selection;
 }
 
 UIEXPORT void ui_list_setselection(UiList *list, int index) {
+    ui_list_setselection2(list, index, TRUE);
+}
+
+UIEXPORT void ui_list_setselection2(UiList *list, int index, UiBool selection_event) {
     if (list->setselection) {
         UiListSelection sel = { 0, NULL };
         if(index >= 0) {
             sel.count = 1;
             sel.rows = &index;
         }
+        UiBool events = ui_selection_events_is_enabled();
+        if(!selection_event) {
+            ui_selection_events_enable(FALSE);
+        }
         list->setselection(list, sel);
+        ui_selection_events_enable(events);
     }
 }
 
@@ -870,6 +948,7 @@ void uic_list_register_observer_destructor(UiContext *ctx, UiList *list, UiObser
 
 static int ui_set_op = 0;
 static int ui_onchange_events_enabled = TRUE;
+static int ui_selection_events_enabled = TRUE;
 
 void ui_setop_enable(int set) {
     ui_set_op = set;
@@ -887,6 +966,14 @@ UiBool ui_onchange_events_is_enabled(void) {
     return ui_onchange_events_enabled;
 }
 
+void ui_selection_events_enable(UiBool enable) {
+    ui_selection_events_enabled = enable;
+}
+
+UiBool ui_selection_events_is_enabled(void) {
+    return ui_selection_events_enabled;
+}
+
 /* ---------------- List initializers and wrapper functions ---------------- */
 
 void ui_global_list_initializer(ui_list_init_func func, void *userdata) {
@@ -899,6 +986,10 @@ void ui_global_list_destructor(ui_list_destroy_func func, void *userdata) {
     default_list_destroy_userdata = userdata;
 }
 
+UIEXPORT void ui_list_class_set_destructor(UiList *list, ui_list_destroy_func destroy) {
+    list->destroy = destroy;
+}
+
 void ui_list_class_set_first(UiList *list, void*(*first)(UiList *list)) {
     list->first = first;
 }
@@ -922,3 +1013,85 @@ void ui_list_class_set_data(UiList *list, void *data) {
 void ui_list_class_set_iter(UiList *list, void *iter) {
     list->iter = iter;
 }
+
+/* ---------------- Text functions ---------------- */
+
+char* ui_text_getsubstr(UiText *text, int begin, int end) {
+    if(text->getsubstr) {
+        return text->getsubstr(text, begin, end);
+    } else {
+        return NULL;
+    }
+}
+
+void  ui_text_insert(UiText *text, int pos, const char *str) {
+    if(text->insert) {
+        text->insert(text, pos, str);
+    }
+}
+
+void  ui_text_replace(UiText *text, int begin, int end, const char *str) {
+    if(text->replace) {
+        text->replace(text, begin, end, str);
+    }
+}
+
+void  ui_text_setposition(UiText *text, int pos) {
+    if(text->setposition) {
+        text->setposition(text, pos);
+    }
+}
+
+int   ui_text_position(UiText *text) {
+    if(text->position) {
+        return text->position(text);
+    } else {
+        return 0;
+    }
+}
+
+void  ui_text_showposition(UiText *text, int pos) {
+    if(text->showposition) {
+        text->showposition(text, pos);
+    }
+}
+
+void  ui_text_setselection(UiText *text, int begin, int end) {
+    if(text->setselection) {
+        text->setselection(text, begin, end);
+    }
+}
+
+void  ui_text_selection(UiText *text, int *begin, int *end) {
+    if(text->selection) {
+        text->selection(text, begin, end);
+    } else {
+        if(begin) {
+            *begin = 0;
+        }
+        if(end) {
+            *end = 0;
+        }
+    }
+}
+
+int   ui_text_length(UiText *text) {
+    if(text->length) {
+        return text->length(text);
+    } else {
+        return 0;
+    }
+}
+void  ui_text_remove(UiText *text, int begin, int end) {
+    if(text->remove) {
+        text->remove(text, begin, end);
+    }
+}
+
+void  ui_text_setreadonly(UiText *text, int readonly) {
+    if(text->setreadonly) {
+        text->setreadonly(text, readonly);
+    } else {
+        text->readonly = readonly;
+    }
+}
index 2f4a5249ea8bd3e53de2e1f5608c2ba2e4054e35..8723ce0dc7685e4d1b54bd5df9ce3fc9852c55cf 100644 (file)
@@ -61,6 +61,9 @@ void uic_range_unbind(UiRange *r);
 void uic_list_unbind(UiList *l);
 void uic_generic_unbind(UiGeneric *g);
 
+UIEXPORT UiListSelection* ui_list_get_selection_allocated(UiList *list);
+UIEXPORT void ui_list_selection_free(UiListSelection *sel);
+
 void uic_list_register_observer_destructor(UiContext *ctx, UiList *list, UiObserver *observer);
   
 #ifdef __cplusplus
index 575dd2989f65b13ddec22503fd89ad0c612f3947..29af77edfbb9296a7f98c536ee9529f6f99b9987 100644 (file)
@@ -45,6 +45,40 @@ void ui_object_set_windowdata(UiObject *obj, void *windowdata) {
     obj->window = windowdata;
 }
 
+void ui_object_set_onclose(UiObject *obj, ui_callback callback, void *userdata) {
+    obj->onclose = callback;
+    obj->onclosedata = userdata;
+}
+
+static int obj_unref(void *ptr) {
+    ui_object_unref(ptr);
+    return 0;
+}
+
+void ui_mainthread_object_unref(UiObject *obj) {
+    // TODO: detect if this is already the main thread and call
+    //       ui_object_unref directly in that case
+    ui_call_mainthread(obj_unref, obj);
+}
+
+static int doc_unref(void *ptr) {
+    ui_document_unref(ptr);
+    return 0;
+}
+
+void ui_mainthread_document_unref(void *doc) {
+    // TODO: see ui_mainthread_object_unref
+    ui_call_mainthread(doc_unref, doc);
+}
+
+static int app_unref(void *unused) {
+    ui_app_unref();
+    return 0;
+}
+
+void ui_mainthread_app_unref() {
+    ui_call_mainthread(app_unref, NULL);
+}
 
 /* ---------------------------- UiList ---------------------------- */
 
@@ -64,6 +98,13 @@ void ui_list_set_iter(UiList *list, void *iter) {
     list->iter = iter;
 }
 
+void ui_list_set_save_selection(UiList *list, UiBool value) {
+    list->save_selection = value;
+}
+
+UiBool ui_list_get_save_selection(UiList *list) {
+    return list->save_selection;
+}
 
 /* ------------------------------ UiSublist ------------------------------ */
 
@@ -209,6 +250,17 @@ int ui_event_get_set(UiEvent *event) {
 }
 
 
+/* ---------------------------- UiTypedObj ---------------------------- */
+
+void* ui_typed_obj_get_ptr(UiTypedObj *obj) {
+    return obj->ptr;
+}
+
+uint64_t ui_typed_obj_get_type(UiTypedObj *obj) {
+    return obj->type;
+}
+
+
 /* ------------------------- SubListItem (public) ------------------------- */
 
 void ui_sublist_item_set_icon(UiSubListItem *item, const char *icon) {
@@ -241,13 +293,6 @@ void ui_sublist_item_set_eventdata(UiSubListItem *item, void *eventdata) {
 
 /* ---------------------------- UiListSelection ---------------------------- */
 
-UiListSelection* ui_list_get_selection_allocated(UiList *list) {
-    UiListSelection *sel = malloc(sizeof(UiListSelection));
-    *sel = ui_list_get_selection(list);
-    return sel;
-    
-}
-
 int ui_list_selection_get_count(UiListSelection *sel) {
     return sel->count;
 }
@@ -265,9 +310,27 @@ UIEXPORT void ui_list_set_selected_indices(UiList *list, int *indices, int num)
     }
 }
 
-void ui_list_selection_free(UiListSelection *sel) {
-    ui_listselection_free(*sel);
-    free(sel);
+
+/* -------------------------- UiTextChangedEvent -------------------------- */
+
+int ui_text_change_event_get_type(UiTextChangeEventData *event) {
+    return event->type;
+}
+
+int ui_text_change_event_get_begin(UiTextChangeEventData *event) {
+    return event->begin;
+}
+
+int ui_text_change_event_get_end(UiTextChangeEventData *event) {
+    return event->end;
+}
+
+const char* ui_text_change_event_get_text(UiTextChangeEventData *event) {
+    return event->text;
+}
+
+int ui_text_change_event_get_length(UiTextChangeEventData *event) {
+    return event->length;
 }
 
 /* ---------------------------- UiFileList ---------------------------- */
index 37f2f38a9f4de88d7dc584e2b178a5bc0bac1b57..2883e56d56ce234b2931be09b74687867f1b0ec1 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "../ui/toolkit.h"
 #include "../ui/list.h"
+#include "../ui/text.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -39,10 +40,17 @@ extern "C" {
 UIEXPORT UiContext* ui_object_get_context(UiObject *obj);
 UIEXPORT void* ui_object_get_windowdata(UiObject *obj);
 UIEXPORT void ui_object_set_windowdata(UiObject *obj, void *windowdata);
+UIEXPORT void ui_object_set_onclose(UiObject *obj, ui_callback callback, void *userdata);
+
+UIEXPORT void ui_mainthread_object_unref(UiObject *obj);
+UIEXPORT void ui_mainthread_document_unref(void *doc);
+UIEXPORT void ui_mainthread_app_unref();
 
 UIEXPORT void* ui_list_get_data(UiList *list);
 UIEXPORT void* ui_list_get_iter(UiList *list);
 UIEXPORT void ui_list_set_iter(UiList *list, void *iter);
+UIEXPORT void ui_list_set_save_selection(UiList *list, UiBool value);
+UIEXPORT UiBool ui_list_get_save_selection(UiList *list);
 
 UIEXPORT UiSubList* ui_sublist_new(void);
 UIEXPORT void ui_sublist_set_value(UiSubList *sublist, UiList *value);
@@ -76,11 +84,18 @@ UIEXPORT int ui_event_get_eventdatatype(UiEvent *event);
 UIEXPORT int ui_event_get_int(UiEvent *event);
 UIEXPORT int ui_event_get_set(UiEvent *event);
 
-UIEXPORT UiListSelection* ui_list_get_selection_allocated(UiList *list);
+UIEXPORT void* ui_typed_obj_get_ptr(UiTypedObj *obj);
+UIEXPORT uint64_t ui_typed_obj_get_type(UiTypedObj *obj);
+
 UIEXPORT int ui_list_selection_get_count(UiListSelection *sel);
 UIEXPORT int* ui_list_selection_get_rows(UiListSelection *sel);
 UIEXPORT void ui_list_set_selected_indices(UiList *list, int *indices, int num);
-UIEXPORT void ui_list_selection_free(UiListSelection *sel);
+
+UIEXPORT int ui_text_change_event_get_type(UiTextChangeEventData *event);
+UIEXPORT int ui_text_change_event_get_begin(UiTextChangeEventData *event);
+UIEXPORT int ui_text_change_event_get_end(UiTextChangeEventData *event);
+UIEXPORT const char* ui_text_change_event_get_text(UiTextChangeEventData *event);
+UIEXPORT int ui_text_change_event_get_length(UiTextChangeEventData *event);
 
 UIEXPORT int ui_filelist_count(UiFileList *flist);
 UIEXPORT char* ui_filelist_get(UiFileList *flist, int index);
index d1979fb679363275ee0324300dc598bc6a5a4c83..8f43a1b5d621d8ac54e5591ef325c0d29abdb853 100644 (file)
 # POSSIBILITY OF SUCH DAMAGE.
 #
 
-$(GTK_OBJPRE)%.o: gtk/%.c
-       $(CC) -o $@ -c -I../ucx $(CFLAGS) $(SHLIB_CFLAGS) $(TK_CFLAGS) $<
-       
 $(UI_LIB): $(OBJ)
        $(AR) $(ARFLAGS) $(UI_LIB) $(OBJ)       
 
 $(UI_SHLIB): $(OBJ)
        $(CC) -o $(UI_SHLIB) $(LDFLAGS) $(SHLIB_LDFLAGS) $(TK_LDFLAGS) $(OBJ) -L../build/lib -lucx
+
+FORCE:
+
+$(GTK_OBJPRE)action.o: gtk/action.c gtk/action.h gtk/../ui/toolkit.h \
+ gtk/../common/action.h gtk/../common/../ui/toolkit.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)button.o: gtk/button.c gtk/button.h gtk/../ui/toolkit.h \
+ gtk/../ui/button.h gtk/../ui/toolkit.h gtk/toolkit.h \
+ gtk/../common/context.h gtk/../common/../ui/toolkit.h \
+ gtk/../common/action.h gtk/../common/object.h gtk/container.h \
+ gtk/../ui/container.h gtk/widget.h gtk/../ui/widget.h \
+ gtk/../common/action.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)container.o: gtk/container.c gtk/container.h \
+ gtk/../ui/toolkit.h gtk/../ui/container.h gtk/../ui/toolkit.h \
+ gtk/toolkit.h gtk/../common/context.h gtk/../common/../ui/toolkit.h \
+ gtk/../common/action.h gtk/../common/object.h gtk/headerbar.h \
+ gtk/../ui/toolbar.h gtk/../common/toolbar.h \
+ gtk/../common/../ui/toolbar.h gtk/../common/menu.h \
+ gtk/../common/../ui/menu.h gtk/../common/../ui/toolkit.h \
+ gtk/../common/container.h gtk/../common/../ui/container.h \
+ gtk/../ui/properties.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)display.o: gtk/display.c gtk/display.h gtk/../ui/toolkit.h \
+ gtk/toolkit.h gtk/../common/context.h gtk/../common/../ui/toolkit.h \
+ gtk/../common/action.h gtk/../common/object.h gtk/container.h \
+ gtk/../ui/container.h gtk/../ui/toolkit.h gtk/../ui/display.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)dnd.o: gtk/dnd.c gtk/dnd.h gtk/../ui/dnd.h \
+ gtk/../ui/toolkit.h gtk/toolkit.h gtk/../ui/toolkit.h \
+ gtk/../common/context.h gtk/../common/../ui/toolkit.h \
+ gtk/../common/action.h gtk/../common/object.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)draw_cairo.o: gtk/draw_cairo.c gtk/container.h \
+ gtk/../ui/toolkit.h gtk/../ui/container.h gtk/../ui/toolkit.h \
+ gtk/toolkit.h gtk/../common/context.h gtk/../common/../ui/toolkit.h \
+ gtk/../common/action.h gtk/../common/object.h gtk/draw_cairo.h \
+ gtk/graphics.h gtk/../ui/graphics.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)draw_gdk.o: gtk/draw_gdk.c gtk/container.h \
+ gtk/../ui/toolkit.h gtk/../ui/container.h gtk/../ui/toolkit.h \
+ gtk/toolkit.h gtk/../common/context.h gtk/../common/../ui/toolkit.h \
+ gtk/../common/action.h gtk/../common/object.h gtk/draw_gdk.h \
+ gtk/graphics.h gtk/../ui/graphics.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)entry.o: gtk/entry.c gtk/../common/context.h \
+ gtk/../common/../ui/toolkit.h gtk/../common/action.h \
+ gtk/../common/object.h gtk/container.h gtk/../ui/toolkit.h \
+ gtk/../ui/container.h gtk/../ui/toolkit.h gtk/toolkit.h gtk/entry.h \
+ gtk/../ui/entry.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)graphics.o: gtk/graphics.c gtk/graphics.h \
+ gtk/../ui/graphics.h gtk/../ui/toolkit.h gtk/toolkit.h \
+ gtk/../ui/toolkit.h gtk/../common/context.h \
+ gtk/../common/../ui/toolkit.h gtk/../common/action.h \
+ gtk/../common/object.h gtk/container.h gtk/../ui/container.h \
+ gtk/draw_cairo.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)headerbar.o: gtk/headerbar.c gtk/headerbar.h gtk/toolkit.h \
+ gtk/../ui/toolkit.h gtk/../common/context.h \
+ gtk/../common/../ui/toolkit.h gtk/../common/action.h \
+ gtk/../common/object.h gtk/../ui/toolbar.h gtk/../ui/toolkit.h \
+ gtk/../common/toolbar.h gtk/../common/../ui/toolbar.h \
+ gtk/../common/menu.h gtk/../common/../ui/menu.h \
+ gtk/../common/../ui/toolkit.h gtk/button.h gtk/../ui/button.h gtk/menu.h \
+ gtk/../ui/menu.h gtk/../common/menu.h gtk/../ui/properties.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)icon.o: gtk/icon.c gtk/toolkit.h gtk/../ui/toolkit.h \
+ gtk/../common/context.h gtk/../common/../ui/toolkit.h \
+ gtk/../common/action.h gtk/../common/object.h gtk/icon.h \
+ gtk/../ui/icons.h gtk/../ui/toolkit.h gtk/../common/properties.h \
+ gtk/../common/../ui/properties.h gtk/../common/../ui/toolkit.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)image.o: gtk/image.c gtk/image.h gtk/../ui/image.h \
+ gtk/../ui/toolkit.h gtk/toolkit.h gtk/../ui/toolkit.h \
+ gtk/../common/context.h gtk/../common/../ui/toolkit.h \
+ gtk/../common/action.h gtk/../common/object.h gtk/container.h \
+ gtk/../ui/container.h gtk/menu.h gtk/../ui/menu.h gtk/../common/menu.h \
+ gtk/../common/../ui/menu.h gtk/widget.h gtk/../ui/widget.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)list.o: gtk/list.c gtk/../common/context.h \
+ gtk/../common/../ui/toolkit.h gtk/../common/action.h \
+ gtk/../common/object.h gtk/../common/action.h gtk/container.h \
+ gtk/../ui/toolkit.h gtk/../ui/container.h gtk/../ui/toolkit.h \
+ gtk/toolkit.h gtk/list.h gtk/../ui/list.h gtk/button.h \
+ gtk/../ui/button.h gtk/icon.h gtk/../ui/icons.h gtk/menu.h \
+ gtk/../ui/menu.h gtk/../common/menu.h gtk/../common/../ui/menu.h \
+ gtk/dnd.h gtk/../ui/dnd.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)menu.o: gtk/menu.c gtk/menu.h gtk/../ui/menu.h \
+ gtk/../ui/toolkit.h gtk/../common/menu.h gtk/../common/../ui/menu.h \
+ gtk/toolkit.h gtk/../ui/toolkit.h gtk/../common/context.h \
+ gtk/../common/../ui/toolkit.h gtk/../common/action.h \
+ gtk/../common/object.h gtk/widget.h gtk/../ui/widget.h \
+ gtk/../common/types.h gtk/../common/action.h gtk/../ui/properties.h \
+ gtk/../ui/window.h gtk/container.h gtk/../ui/container.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)range.o: gtk/range.c gtk/range.h gtk/toolkit.h \
+ gtk/../ui/toolkit.h gtk/../common/context.h \
+ gtk/../common/../ui/toolkit.h gtk/../common/action.h \
+ gtk/../common/object.h gtk/../ui/range.h gtk/../ui/toolkit.h \
+ gtk/container.h gtk/../ui/container.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)text.o: gtk/text.c gtk/text.h gtk/../ui/text.h \
+ gtk/../ui/toolkit.h gtk/toolkit.h gtk/../ui/toolkit.h \
+ gtk/../common/context.h gtk/../common/../ui/toolkit.h \
+ gtk/../common/action.h gtk/../common/object.h gtk/container.h \
+ gtk/../ui/container.h gtk/widget.h gtk/../ui/widget.h \
+ gtk/../common/types.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)toolbar.o: gtk/toolbar.c gtk/toolbar.h gtk/../ui/toolbar.h \
+ gtk/../ui/toolkit.h gtk/../common/toolbar.h \
+ gtk/../common/../ui/toolbar.h gtk/../common/menu.h \
+ gtk/../common/../ui/menu.h gtk/../common/../ui/toolkit.h gtk/list.h \
+ gtk/../ui/list.h gtk/toolkit.h gtk/../ui/toolkit.h \
+ gtk/../common/context.h gtk/../common/../ui/toolkit.h \
+ gtk/../common/action.h gtk/../common/object.h gtk/menu.h \
+ gtk/../ui/menu.h gtk/../common/menu.h gtk/button.h gtk/../ui/button.h \
+ gtk/icon.h gtk/../ui/icons.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)toolkit.o: gtk/toolkit.c gtk/toolkit.h gtk/../ui/toolkit.h \
+ gtk/../common/context.h gtk/../common/../ui/toolkit.h \
+ gtk/../common/action.h gtk/../common/object.h gtk/toolbar.h \
+ gtk/../ui/toolbar.h gtk/../ui/toolkit.h gtk/../common/toolbar.h \
+ gtk/../common/../ui/toolbar.h gtk/../common/menu.h \
+ gtk/../common/../ui/menu.h gtk/../common/../ui/toolkit.h gtk/list.h \
+ gtk/../ui/list.h gtk/window.h gtk/icon.h gtk/../ui/icons.h \
+ gtk/../common/document.h gtk/../common/context.h \
+ gtk/../common/properties.h gtk/../common/../ui/properties.h \
+ gtk/../common/menu.h gtk/../common/threadpool.h gtk/../common/app.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)webview.o: gtk/webview.c gtk/toolkit.h gtk/../ui/toolkit.h \
+ gtk/../common/context.h gtk/../common/../ui/toolkit.h \
+ gtk/../common/action.h gtk/../common/object.h gtk/container.h \
+ gtk/../ui/container.h gtk/../ui/toolkit.h gtk/webview.h \
+ gtk/../ui/webview.h gtk/widget.h gtk/../ui/widget.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)widget.o: gtk/widget.c gtk/widget.h gtk/../ui/widget.h \
+ gtk/../ui/toolkit.h gtk/container.h gtk/../ui/toolkit.h \
+ gtk/../ui/container.h gtk/toolkit.h gtk/../common/context.h \
+ gtk/../common/../ui/toolkit.h gtk/../common/action.h \
+ gtk/../common/object.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(GTK_OBJPRE)window.o: gtk/window.c gtk/../ui/window.h \
+ gtk/../ui/toolkit.h gtk/../ui/properties.h gtk/../common/context.h \
+ gtk/../common/../ui/toolkit.h gtk/../common/action.h \
+ gtk/../common/menu.h gtk/../common/../ui/menu.h \
+ gtk/../common/../ui/toolkit.h gtk/../common/toolbar.h \
+ gtk/../common/../ui/toolbar.h gtk/../common/menu.h gtk/../common/utils.h \
+ gtk/../common/../ui/text.h gtk/menu.h gtk/../ui/menu.h gtk/toolkit.h \
+ gtk/../ui/toolkit.h gtk/../common/object.h gtk/toolbar.h \
+ gtk/../ui/toolbar.h gtk/list.h gtk/../ui/list.h gtk/container.h \
+ gtk/../ui/container.h gtk/headerbar.h gtk/button.h gtk/../ui/button.h \
+ gtk/window.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
diff --git a/ui/gtk/action.c b/ui/gtk/action.c
new file mode 100644 (file)
index 0000000..80f0a42
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2026 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "action.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+
+
+/* ------------------------------ public API ------------------------------ */
+
+void ui_add_action(UiContext *ctx, const char *name, ui_callback callback, void *userdata) {
+    uic_add_action(ctx, name, callback, userdata, NULL, NULL);
+}
+
+void ui_add_action_with_accelerator(
+        UiContext *ctx,
+        const char *name,
+        ui_callback callback,
+        void *userdata,
+        const char *accelerator,
+        const char *accelerator_text)
+{
+    uic_add_action(ctx, name, callback, userdata, accelerator, accelerator_text);
+    
+    // TODO: accelerator
+}
diff --git a/ui/gtk/action.h b/ui/gtk/action.h
new file mode 100644 (file)
index 0000000..d13d3de
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2026 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef ACTION_H
+#define ACTION_H
+
+#include "../ui/toolkit.h"
+#include "../common/action.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ACTION_H */
+
index d9acdbf38284f00bb07228232705114dbee60825..aa641bf0a008354d324b07e522a9782bc7b308d4 100644 (file)
 
 #include "button.h"
 #include "container.h"
+#include "widget.h"
 #include <cx/allocator.h>
 #include <cx/buffer.h>
 #include <cx/json.h>
 #include "../common/context.h"
 #include "../common/object.h"
+#include "../common/action.h"
 
 void ui_button_set_icon_name(GtkWidget *button, const char *icon) {
     if(!icon) {
@@ -63,6 +65,7 @@ GtkWidget* ui_create_button(
         const char *tooltip,
         ui_callback onclick,
         void *userdata,
+        const char *action,
         int event_value,
         bool activate_event)
 {
@@ -72,12 +75,13 @@ GtkWidget* ui_create_button(
         gtk_widget_set_tooltip_text(button, tooltip);
     }
     
-    if(onclick) {
+    if(onclick || action) {
         UiEventData *event = malloc(sizeof(UiEventData));
         event->obj = obj;
         event->userdata = userdata;
         event->callback = onclick;
         event->value = event_value;
+        event->action = action ? strdup(action) : NULL;
         event->customdata = NULL;
         event->customint = 0;
 
@@ -89,7 +93,7 @@ GtkWidget* ui_create_button(
         g_signal_connect(
                 button,
                 "destroy",
-                G_CALLBACK(ui_destroy_userdata),
+                G_CALLBACK(ui_destroy_eventdata),
                 event);
         if(activate_event) {
             g_signal_connect(
@@ -98,18 +102,27 @@ GtkWidget* ui_create_button(
                 G_CALLBACK(ui_button_clicked),
                 event);
         }
+        
+        if(action) {
+            uic_bind_action(obj->ctx, action, button, (ui_enablefunc)ui_set_enabled);
+            UiAction *ui_action = uic_resolve_action(obj->ctx, action);
+            if(!ui_action) {
+                ui_set_enabled(button, FALSE);
+            }
+        }
     }
     
     return button;
 }
 
 UIWIDGET ui_button_create(UiObject *obj, UiButtonArgs *args) {
-    GtkWidget *button = ui_create_button(obj, args->label, args->icon, args->tooltip, args->onclick, args->onclickdata, 0, FALSE);
+    GtkWidget *button = ui_create_button(obj, args->label, args->icon, args->tooltip, args->onclick, args->onclickdata, args->action, 0, FALSE);
     ui_set_name_and_style(button, args->name, args->style_class);
     ui_set_widget_states(obj->ctx, button, args->states);
     UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
     UiLayout layout = UI_ARGS2LAYOUT(args);
     ct->add(ct, button, &layout);
+    uic_widget_set_visibility_states(obj->ctx, button, args->visibility_states);
     return button;
 }
 
@@ -123,7 +136,13 @@ void ui_button_clicked(GtkWidget *widget, UiEventData *event) {
     e.eventdatatype = 0;
     e.intval = event->value;
     e.set = ui_get_setop();
-    event->callback(&e, event->userdata);
+    if(event->callback) {
+        event->callback(&e, event->userdata);
+    }
+    
+    if(event->action) {
+        uic_action_callback(&e, event->action);
+    }
 }
 
 void ui_button_set_label(UIWIDGET button, const char *label) {
@@ -134,6 +153,47 @@ void ui_button_set_icon(UIWIDGET button, const char *icon) {
     ui_button_set_icon_name(button, icon);
 }
 
+void ui_button_set_tooltip(UIWIDGET button, const char *tooltip) {
+    gtk_widget_set_tooltip_text(GTK_WIDGET(button), tooltip);
+}
+
+void ui_togglebutton_set_label(UIWIDGET button, const char *label) {
+    ui_button_set_label(button, label);
+}
+
+void ui_togglebutton_set_icon(UIWIDGET button, const char *icon) {
+    ui_button_set_icon(button, icon);
+}
+
+void ui_togglebutton_set_tooltip(UIWIDGET button, const char *tooltip) {
+    ui_button_set_tooltip(button, tooltip);
+}
+
+void ui_checkbox_set_label(UIWIDGET button, const char *label) {
+    ui_button_set_label(button, label);
+}
+
+void ui_checkbox_set_icon(UIWIDGET button, const char *icon) {
+    ui_button_set_icon(button, icon);
+}
+
+void ui_checkbox_set_tooltip(UIWIDGET button, const char *tooltip) {
+    ui_button_set_tooltip(button, tooltip);
+}
+
+void ui_radiobutton_set_label(UIWIDGET button, const char *label) {
+    ui_button_set_label(button, label);
+}
+
+void ui_radiobutton_set_icon(UIWIDGET button, const char *icon) {
+    ui_button_set_icon(button, icon);
+}
+
+void ui_radiobutton_set_tooltip(UIWIDGET button, const char *tooltip) {
+    ui_button_set_tooltip(button, tooltip);
+}
+
+
 int64_t ui_toggle_button_get(UiInteger *integer) {
     GtkToggleButton *button = integer->obj;
     integer->value = (int)gtk_toggle_button_get_active(button);
@@ -169,7 +229,14 @@ static void ui_toggled_callback(GtkToggleButton *widget, UiEventData *event) {
     e.eventdatatype = 0;
     e.intval = gtk_toggle_button_get_active(widget);
     e.set = ui_get_setop();
-    event->callback(&e, event->userdata);    
+    
+    if(event->callback) {
+        event->callback(&e, event->userdata);    
+    }
+    
+    if(event->action) {
+        uic_action_callback(&e, event->action);
+    }
 }
 
 static void ui_togglebutton_enable_state_callback(GtkToggleButton *widget, UiEventData *event) {
@@ -190,6 +257,7 @@ void ui_setup_togglebutton(
         UiInteger *value,
         ui_callback onchange,
         void *onchangedata,
+        const char *action,
         int enable_state)
 {
     if(label) {
@@ -200,6 +268,14 @@ void ui_setup_togglebutton(
         gtk_widget_set_tooltip_text(togglebutton, tooltip);
     }
     
+   if(action) {
+        uic_bind_action(obj->ctx, action, togglebutton, (ui_enablefunc)ui_set_enabled);
+        UiAction *ui_action = uic_resolve_action(obj->ctx, action);
+        if(!ui_action) {
+            ui_set_enabled(togglebutton, FALSE);
+        }
+    }
+    
     ui_bind_togglebutton(
             obj,
             togglebutton,
@@ -210,6 +286,7 @@ void ui_setup_togglebutton(
             (ui_toggled_func)ui_toggled_callback,
             onchange,
             onchangedata,
+            action,
             (ui_toggled_func)ui_togglebutton_enable_state_callback,
             enable_state
             );
@@ -225,6 +302,7 @@ void ui_bind_togglebutton(
         void (*toggled_callback)(void*, void*),
         ui_callback onchange,
         void *onchangedata,
+        const char *action,
         void (*enable_state_func)(void*, void*),
         int enable_state)
 {
@@ -256,11 +334,12 @@ void ui_bind_togglebutton(
                 event);
     }
     
-    if(onchange) {
+    if(onchange || action) {
         UiEventData *event = malloc(sizeof(UiEventData));
         event->obj = obj;
         event->userdata = onchangedata;
         event->callback = onchange;
+        event->action = action ? strdup(action) : NULL,
         event->value = 0;
         event->customdata = NULL;
         event->customint = 0;
@@ -273,10 +352,10 @@ void ui_bind_togglebutton(
         g_signal_connect(
                 widget,
                 "destroy",
-                G_CALLBACK(ui_destroy_userdata),
+                G_CALLBACK(ui_destroy_eventdata),
                 event);
     }
-    
+     
     if(enable_state > 0) {
         UiEventData *event = malloc(sizeof(UiEventData));
         event->obj = obj;
@@ -310,6 +389,7 @@ static UIWIDGET togglebutton_create(UiObject *obj, GtkWidget *widget, UiToggleAr
             args->value,
             args->onchange,
             args->onchangedata,
+            args->action,
             args->enable_state);
     ui_set_name_and_style(widget, args->name, args->style_class);
     ui_set_widget_states(obj->ctx, widget, args->states);
@@ -317,6 +397,7 @@ static UIWIDGET togglebutton_create(UiObject *obj, GtkWidget *widget, UiToggleAr
     UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
     UiLayout layout = UI_ARGS2LAYOUT(args);
     ct->add(ct, widget, &layout);
+    uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
     
     return widget;
 }
@@ -371,6 +452,7 @@ UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs *args) {
             (ui_toggled_func)ui_checkbox_callback,
             args->onchange,
             args->onchangedata,
+            args->action,
             (ui_toggled_func)ui_checkbox_enable_state,
             args->enable_state);
     
@@ -380,6 +462,7 @@ UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs *args) {
     UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
     UiLayout layout = UI_ARGS2LAYOUT(args);
     ct->add(ct, widget, &layout);
+    uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
     
     return widget;
 }
@@ -469,6 +552,7 @@ UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs *args) {
     UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
     UiLayout layout = UI_ARGS2LAYOUT(args);
     ct->add(ct, widget, &layout);
+    uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
     
     return widget;
 }
@@ -493,6 +577,171 @@ UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs *args) {
 
 #endif
 
+static void content_toggle_button_changed(UiContentToggleButton *button) {
+    if(button->toggled) {
+        gtk_button_set_label(GTK_BUTTON(button->widget), button->label1);
+        ui_button_set_icon_name(button->widget, button->icon1);
+        gtk_widget_set_tooltip_text(button->widget, button->tooltip1);
+    } else {
+        gtk_button_set_label(GTK_BUTTON(button->widget), button->label0);
+        ui_button_set_icon_name(button->widget, button->icon0);
+        gtk_widget_set_tooltip_text(button->widget, button->tooltip0);
+    }
+    
+    UiEvent e;
+    e.obj = button->obj;
+    e.window = button->obj->window;
+    e.document = button->obj->ctx->document;
+    e.eventdata = NULL;
+    e.eventdatatype = 0;
+    e.intval = button->toggled;
+    e.set = ui_get_setop();
+    
+    if(button->onchange) {
+        button->onchange(&e, button->onchangedata);    
+    }
+    
+    if(button->onchange_action) {
+        uic_action_callback(&e, button->onchange_action);
+    }
+}
+
+static void ui_content_toggle_button_toggled(GtkWidget *widget, UiContentToggleButton *button) {
+    button->toggled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
+    if(ui_get_setop() == 0) {
+        content_toggle_button_changed(button);
+    }
+}
+
+static void ui_content_toggle_button_clicked(GtkWidget *widget, UiContentToggleButton *button) {
+    button->toggled = !button->toggled;
+    content_toggle_button_changed(button);
+}
+
+static void ui_destroy_content_togglebutton(GtkWidget *widget, UiContentToggleButton *button) {
+    free(button->label0);
+    free(button->icon0);
+    free(button->tooltip0);
+    free(button->label1);
+    free(button->icon1);
+    free(button->tooltip1);
+    free(button->onchange_action);
+    free(button);
+}
+
+static void ui_content_togglebutton_enabled_by_state(void *data, int enabled) {
+    UiContentToggleButton *button = data;
+    if(button->toggled != enabled) {
+        button->toggled = enabled;
+        content_toggle_button_changed(button);
+    }
+}
+
+UIWIDGET ui_create_content_togglebutton(UiObject *obj, UiContentToggleArgs *args) {
+    UiContentToggleButton *button = malloc(sizeof(UiContentToggleButton));
+    memset(button, 0, sizeof(UiContentToggleButton));
+    button->obj = obj;
+    button->label0 = args->label0 ? strdup(args->label0) : NULL;
+    button->icon0 = args->icon0 ? strdup(args->icon0) : NULL;
+    button->tooltip0 = args->tooltip0 ? strdup(args->tooltip0) : NULL;
+    button->label1 = args->label1 ? strdup(args->label1) : NULL;
+    button->icon1 = args->icon1 ? strdup(args->icon1) : NULL;
+    button->tooltip1 = args->tooltip1 ? strdup(args->tooltip1) : NULL;
+    button->enable_state = args->enable_state;
+    button->var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_INTEGER);
+    button->onchange = args->onchange;
+    button->onchangedata = args->onchangedata;
+    button->onchange_action = args->action ? strdup(args->action) : NULL;
+    
+    const char *label = args->label0;
+    const char *icon = args->icon0;
+    const char *tooltip = args->tooltip0;
+    if(button->var) {
+        UiInteger *i = button->var->value;
+        i->obj = button;
+        i->get = ui_ctntogglebutton_get;
+        i->set = ui_ctntogglebutton_set;
+        
+        if(i->value) {
+            label = args->label1;
+            icon = args->label1;
+            tooltip = args->tooltip1;
+            button->toggled = 1;
+        }
+    }
+    
+    GtkWidget *widget;
+    if(args->istogglebutton) {
+        widget = gtk_toggle_button_new_with_label(label);
+        
+        g_signal_connect(
+                widget,
+                "toggled",
+                G_CALLBACK(ui_content_toggle_button_toggled),
+                button);
+    } else {
+        widget = gtk_button_new_with_label(label);
+        
+        g_signal_connect(
+                widget,
+                "clicked",
+                G_CALLBACK(ui_content_toggle_button_clicked),
+                button);
+    }
+    ui_button_set_icon_name(widget, icon);
+    gtk_widget_set_tooltip_text(widget, tooltip);
+    button->widget = widget;
+    
+    if(args->action) {
+        uic_bind_action(obj->ctx, args->action, widget, (ui_enablefunc)ui_set_enabled);
+        UiAction *ui_action = uic_resolve_action(obj->ctx, args->action);
+        if(!ui_action) {
+            ui_set_enabled(widget, FALSE);
+        }
+    }
+    
+    if(args->toggled_by_state != 0) {
+        CxList *ls = cxArrayListCreate(NULL, sizeof(int), 1);
+        cxListAdd(ls, &args->toggled_by_state);
+        uic_add_state_widget(obj->ctx, button, ui_content_togglebutton_enabled_by_state, ls);
+        cxListFree(ls);
+    }
+    
+    g_signal_connect(
+            widget,
+            "destroy",
+            G_CALLBACK(ui_destroy_content_togglebutton),
+            button);
+    
+    g_object_set_data(G_OBJECT(widget), "ui_content_togglebutton", button);
+    return widget;
+}
+
+UIWIDGET ui_content_togglebutton_create(UiObject *obj, UiContentToggleArgs *args) {
+    GtkWidget *widget = ui_create_content_togglebutton(obj, args);
+    
+    ui_set_name_and_style(widget, args->name, args->style_class);
+    ui_set_widget_states(obj->ctx, widget, args->states);
+    UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
+    UiLayout layout = UI_ARGS2LAYOUT(args);
+    ct->add(ct, widget, &layout);
+    uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
+    return widget;
+}
+
+int64_t ui_ctntogglebutton_get(UiInteger *value) {
+    UiContentToggleButton *button = value->obj;
+    value->value = button->toggled;
+    return value->value;
+}
+
+void ui_ctntogglebutton_set(UiInteger *value, int64_t i) {
+    UiContentToggleButton *button = value->obj;
+    button->toggled = i != 0;
+    value->value = button->toggled;
+    content_toggle_button_changed(button);
+}
+
 #if GTK_MAJOR_VERSION >= 4
 #define RADIOBUTTON_NEW(group, label) gtk_check_button_new_with_label(label)
 #define RADIOBUTTON_SET_GROUP(button, group) 
@@ -621,6 +870,7 @@ UIWIDGET ui_radiobutton_create(UiObject *obj, UiToggleArgs *args) {
     UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
     UiLayout layout = UI_ARGS2LAYOUT(args);
     ct->add(ct, rbutton, &layout);
+    uic_widget_set_visibility_states(obj->ctx, rbutton, args->visibility_states);
     
     return rbutton;
 }
@@ -836,16 +1086,7 @@ static void linkbutton_callback(GtkWidget *widget, UiLinkButton *data) {
 static void linkbutton_clicked(GtkWidget *widget, UiLinkButton *data) {
     linkbutton_callback(widget, data);
     if(data->link) {   
-#if GTK_CHECK_VERSION(4, 0, 0)
-        GtkUriLauncher *launcher = gtk_uri_launcher_new (data->link);
-        gtk_uri_launcher_launch (launcher, NULL, NULL, NULL, NULL);
-        g_object_unref (launcher);
-#elif GTK_CHECK_VERSION(3, 22, 0)
-        GError *error = NULL;
-        gtk_show_uri_on_window(NULL, data->link, GDK_CURRENT_TIME, &error);
-#elif
-        // TODO: call xdg-open
-#endif
+        ui_open_uri(data->link);
     }
 }
 
@@ -913,6 +1154,7 @@ UIWIDGET ui_linkbutton_create(UiObject *obj, UiLinkButtonArgs *args) {
     UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
     UiLayout layout = UI_ARGS2LAYOUT(args);
     ct->add(ct, button, &layout);
+    uic_widget_set_visibility_states(obj->ctx, button, args->visibility_states);
     
     return button;
 }
@@ -932,6 +1174,7 @@ void ui_linkbutton_set(UiString *s, const char *str) {
     if(s->value.free) {
         s->value.free(s->value.ptr);
     }
+    s->value.ptr = NULL;
 #if GTK_MAJOR_VERSION == 3
     UiLinkButton *data = s->obj;
     GtkWidget *child = gtk_bin_get_child(GTK_BIN(data->widget));
index ce94b90c7dc04259e087553a2a195d35a949f1b5..4972f35f9dde75615b8ccc65bfc6c5d81646afd2 100644 (file)
 extern "C" {
 #endif
     
+typedef struct UiContentToggleButton {
+    UiObject *obj;
+    UiVar *var;
+    GtkWidget *widget;
+    char *label0;
+    char *icon0;
+    char *tooltip0;
+    char *label1;
+    char *icon1;
+    char *tooltip1;
+    ui_callback onchange;
+    void *onchangedata;
+    char *onchange_action;
+    int toggled;
+    int enable_state;
+} UiContentToggleButton;
+    
 typedef struct UiLinkButton {
     UiObject *obj;
     GtkWidget *widget;
@@ -58,6 +75,7 @@ GtkWidget* ui_create_button(
         const char *tooltip,
         ui_callback onclick,
         void *userdata,
+        const char *action,
         int event_value,
         bool activate_event);
 
@@ -71,6 +89,7 @@ void ui_setup_togglebutton(
         UiInteger *value,
         ui_callback onchange,
         void *onchangedata,
+        const char *action,
         int enable_state);
 
 void ui_bind_togglebutton(
@@ -83,6 +102,7 @@ void ui_bind_togglebutton(
         void (*toggled_callback)(void*, void*),
         ui_callback onchange,
         void *onchangedata,
+        const char *action,
         void (*enable_state_func)(void*, void*),
         int enable_state);
     
@@ -98,9 +118,14 @@ UIWIDGET ui_radiobutton_var(UiObject *obj, char *label, UiVar *var);
 
 void ui_radio_obs(GtkToggleButton *widget, UiVarEventData *event);
 
+UIWIDGET ui_create_content_togglebutton(UiObject *obj, UiContentToggleArgs *args);
+
 int64_t ui_switch_get(UiInteger *value);
 void ui_switch_set(UiInteger *value, int64_t i);
 
+int64_t ui_ctntogglebutton_get(UiInteger *value);
+void ui_ctntogglebutton_set(UiInteger *value, int64_t i);
+
 int64_t ui_radiobutton_get(UiInteger *value);
 void ui_radiobutton_set(UiInteger *value, int64_t i);
 
index 7da333da50cdf2d75f557a1c17669d0bb3ebcf51..30960ffb5f0490793f954b5b1e800a0d7d58f29b 100644 (file)
 
 
 void ui_container_begin_close(UiObject *obj) {
-    UiContainerX *ct = obj->container_end;
+    UiContainer *ct = obj->container_end;
     ct->close = 1;
 }
 
 int ui_container_finish(UiObject *obj) {
-    UiContainerX *ct = obj->container_end;
+    UiContainer *ct = obj->container_end;
     if(ct->close) {
         ui_end_new(obj);
         return 0;
@@ -82,7 +82,7 @@ GtkWidget* ui_subcontainer_create(
 {
     GtkWidget *sub = NULL;
     GtkWidget *add = NULL;
-    UiContainerX *container = NULL;
+    UiContainer *container = NULL;
     switch(type) {
         default: {
             sub = ui_gtk_vbox_new(spacing);
@@ -125,11 +125,11 @@ void ui_custom_container_create(UiObject *obj, UIWIDGET widget, ui_addwidget_fun
     container->container.widget = widget;
     container->add = add_child;
     container->userdata = userdata;
-    uic_object_push_container(obj, (UiContainerX*)container);
+    uic_object_push_container(obj, (UiContainer*)container);
 }
 
 /* -------------------- Box Container -------------------- */
-UiContainerX* ui_box_container(UiObject *obj, GtkWidget *box, UiSubContainerType type) {
+UiContainer* ui_box_container(UiObject *obj, GtkWidget *box, UiSubContainerType type) {
     UiBoxContainer *ct = cxCalloc(
             obj->ctx->allocator,
             1,
@@ -137,7 +137,7 @@ UiContainerX* ui_box_container(UiObject *obj, GtkWidget *box, UiSubContainerType
     ct->container.widget = box;
     ct->container.add = ui_box_container_add;
     ct->type = type;
-    return (UiContainerX*)ct;
+    return (UiContainer*)ct;
 }
 
 void ui_box_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout) {
@@ -172,7 +172,7 @@ void ui_box_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *l
 #endif
 }
 
-UiContainerX* ui_grid_container(
+UiContainer* ui_grid_container(
         UiObject *obj,
         GtkWidget *grid,
         UiBool def_hexpand,
@@ -192,7 +192,7 @@ UiContainerX* ui_grid_container(
     ct->container.add = ui_grid_container_add;
     UI_GTK_V2(ct->width = 0);
     UI_GTK_V2(ct->height = 1);
-    return (UiContainerX*)ct;
+    return (UiContainer*)ct;
 }
 
 
@@ -271,14 +271,14 @@ void ui_grid_container_add(UiContainerPrivate *ct, GtkWidget *widget) {
 }
 #endif
 
-UiContainerX* ui_frame_container(UiObject *obj, GtkWidget *frame) {
+UiContainer* ui_frame_container(UiObject *obj, GtkWidget *frame) {
     UiContainerPrivate *ct = cxCalloc(
             obj->ctx->allocator,
             1,
             sizeof(UiContainerPrivate));
     ct->widget = frame;
     ct->add = ui_frame_container_add;
-    return (UiContainerX*)ct;
+    return (UiContainer*)ct;
 }
 
 void ui_frame_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout) {
@@ -286,14 +286,14 @@ void ui_frame_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout
     FRAME_SET_CHILD(ct->widget, widget);
 }
 
-UiContainerX* ui_expander_container(UiObject *obj, GtkWidget *expander) {
+UiContainer* ui_expander_container(UiObject *obj, GtkWidget *expander) {
     UiContainerPrivate *ct = cxCalloc(
             obj->ctx->allocator,
             1,
             sizeof(UiContainerPrivate));
     ct->widget = expander;
     ct->add = ui_expander_container_add;
-    return (UiContainerX*)ct;
+    return (UiContainer*)ct;
 }
 
 void ui_expander_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout) {
@@ -307,24 +307,24 @@ void ui_scrolledwindow_container_add(UiContainerPrivate *ct, GtkWidget *widget,
     SCROLLEDWINDOW_SET_CHILD(ct->widget, widget);
 }
 
-UiContainerX* ui_scrolledwindow_container(UiObject *obj, GtkWidget *scrolledwindow) {
+UiContainer* ui_scrolledwindow_container(UiObject *obj, GtkWidget *scrolledwindow) {
     UiContainerPrivate *ct = cxCalloc(
             obj->ctx->allocator,
             1,
             sizeof(UiContainerPrivate));
     ct->widget = scrolledwindow;
     ct->add = ui_scrolledwindow_container_add;
-    return (UiContainerX*)ct;
+    return (UiContainer*)ct;
 }
 
-UiContainerX* ui_tabview_container(UiObject *obj, GtkWidget *tabview) {
+UiContainer* ui_tabview_container(UiObject *obj, GtkWidget *tabview) {
     UiTabViewContainer *ct = cxCalloc(
             obj->ctx->allocator,
             1,
             sizeof(UiTabViewContainer));
     ct->container.widget = tabview;
     ct->container.add = ui_tabview_container_add;
-    return (UiContainerX*)ct;
+    return (UiContainer*)ct;
 }
 
 void ui_tabview_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout) {
@@ -390,9 +390,11 @@ UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs *args, UiSubContainerType
     ui_set_name_and_style(box, args->name, args->style_class);
     ct->add(ct, box, &layout);
     
-    UiContainerX *container = ui_box_container(obj, box, type);
+    UiContainer *container = ui_box_container(obj, box, type);
     uic_object_push_container(obj, container);
     
+    uic_widget_set_visibility_states(obj->ctx, box, args->visibility_states);
+    
     return box;
 }
 
@@ -426,9 +428,11 @@ UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) {
     ui_set_name_and_style(grid, args->name, args->style_class);
     ct->add(ct, grid, &layout);
     
-    UiContainerX *container = ui_grid_container(obj, grid, args->def_hexpand, args->def_vexpand, args->def_hfill, args->def_vfill);
+    UiContainer *container = ui_grid_container(obj, grid, args->def_hexpand, args->def_vexpand, args->def_hfill, args->def_vfill);
     uic_object_push_container(obj, container);
     
+    uic_widget_set_visibility_states(obj->ctx, grid, args->visibility_states);
+    
     return grid;
 }
 
@@ -472,10 +476,12 @@ UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args) {
     if(sub) {
         FRAME_SET_CHILD(frame, sub);
     } else {
-        UiContainerX *container = ui_frame_container(obj, frame);
+        UiContainer *container = ui_frame_container(obj, frame);
         uic_object_push_container(obj, container);
     }
     
+    uic_widget_set_visibility_states(obj->ctx, frame, args->visibility_states);
+    
     return frame;
 }
 
@@ -496,10 +502,12 @@ UIEXPORT UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs *args) {
     if(sub) {
         EXPANDER_SET_CHILD(expander, sub);
     } else {
-        UiContainerX *container = ui_expander_container(obj, expander);
+        UiContainer *container = ui_expander_container(obj, expander);
         uic_object_push_container(obj, container);
     }
     
+    uic_widget_set_visibility_states(obj->ctx, expander, args->visibility_states);
+    
     return expander;
 }
 
@@ -521,10 +529,12 @@ UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs *args) {
     if(sub) {
         SCROLLEDWINDOW_SET_CHILD(sw, sub);
     } else {
-        UiContainerX *container = ui_scrolledwindow_container(obj, sw);
+        UiContainer *container = ui_scrolledwindow_container(obj, sw);
         uic_object_push_container(obj, container);
     }
     
+    uic_widget_set_visibility_states(obj->ctx, sw, args->visibility_states);
+    
     return sw;
 }
 
@@ -733,10 +743,13 @@ typedef void (*ui_tabview_set_func)(UiInteger*, int64_t);
 UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs *args) {
     UiGtkTabView *data = malloc(sizeof(UiGtkTabView));
     memset(data, 0, sizeof(UiGtkTabView));
+    data->obj = obj;
     data->padding = args->padding;
     data->spacing = args->spacing;
     data->columnspacing = args->columnspacing;
     data->rowspacing = args->rowspacing;
+    data->onchange = args->onchange;
+    data->onchangedata = args->onchangedata;
     
     ui_tabview_get_func getfunc = NULL;
     ui_tabview_set_func setfunc = NULL;
@@ -808,14 +821,16 @@ UIWIDGET ui_tabview_create(UiObject* obj, UiTabViewArgs *args) {
     UiLayout layout = UI_ARGS2LAYOUT(args);
     ct->add(ct, widget, &layout);
     
-    UiContainerX *container = ui_tabview_container(obj, widget);
+    UiContainer *container = ui_tabview_container(obj, widget);
     uic_object_push_container(obj, container);
     
+    uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
+    
     return widget;
 }
 
 static GtkWidget* create_tab(UiObject *obj, UiGtkTabView *tabview, const char *title, int tab) {
-    UiContainerX *container;
+    UiContainer *container;
     GtkWidget *sub;
     switch(tabview->subcontainer) {
         default: {
@@ -901,7 +916,7 @@ static void hb_set_part(UiObject *obj, int part) {
             sizeof(UiHeaderbarContainer));
     memcpy(hb, ct, sizeof(UiHeaderbarContainer));
     hb->part = part;
-    uic_object_push_container(obj, (UiContainerX*)hb);
+    uic_object_push_container(obj, (UiContainer*)hb);
 }
 
 void ui_headerbar_start_create(UiObject *obj) {
@@ -924,7 +939,7 @@ UIWIDGET ui_headerbar_fallback_create(UiObject *obj, UiHeaderbarArgs *args) {
     ui_set_name_and_style(box, args->name, args->style_class);
     ct->add(ct, box, &layout);
     
-    UiContainerX *container = ui_headerbar_fallback_container(obj, box);
+    UiContainer *container = ui_headerbar_fallback_container(obj, box);
     uic_object_push_container(obj, container);
     
     return box;
@@ -934,21 +949,21 @@ static void hb_fallback_set_part(UiObject *obj, int part) {
      UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
     GtkWidget *headerbar = ct->widget;
     
-    UiContainerX *container = ui_headerbar_container(obj, headerbar);
+    UiContainer *container = ui_headerbar_container(obj, headerbar);
     uic_object_push_container(obj, container);
     
     UiHeaderbarContainer *hb = (UiHeaderbarContainer*)container;
     hb->part = part;
 }
 
-UiContainerX* ui_headerbar_fallback_container(UiObject *obj, GtkWidget *headerbar) {
+UiContainer* ui_headerbar_fallback_container(UiObject *obj, GtkWidget *headerbar) {
     UiHeaderbarContainer *ct = cxCalloc(
             obj->ctx->allocator,
             1,
             sizeof(UiHeaderbarContainer));
     ct->container.widget = headerbar;
     ct->container.add = ui_headerbar_fallback_container_add;
-    return (UiContainerX*)ct;
+    return (UiContainer*)ct;
 }
 
 void ui_headerbar_fallback_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout) {
@@ -964,20 +979,20 @@ UIWIDGET ui_headerbar_create(UiObject *obj, UiHeaderbarArgs *args) {
         return ui_headerbar_fallback_create(obj, args);
     }
     
-    UiContainerX *container = ui_headerbar_container(obj, headerbar);
+    UiContainer *container = ui_headerbar_container(obj, headerbar);
     uic_object_push_container(obj, container);
     
     return headerbar;    
 }
 
-UiContainerX* ui_headerbar_container(UiObject *obj, GtkWidget *headerbar) {
+UiContainer* ui_headerbar_container(UiObject *obj, GtkWidget *headerbar) {
     UiHeaderbarContainer *ct = cxCalloc(
             obj->ctx->allocator,
             1,
             sizeof(UiHeaderbarContainer));
     ct->container.widget = headerbar;
     ct->container.add = ui_headerbar_container_add;
-    return (UiContainerX*)ct;
+    return (UiContainer*)ct;
 }
 
 void ui_headerbar_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout) {
@@ -1020,7 +1035,7 @@ UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs *args) {
     ui_gtk_set_margin(box, args->margin, args->margin_left, args->margin_right, args->margin_top, args->margin_bottom);
     adw_toolbar_view_set_content(ADW_TOOLBAR_VIEW(sidebar_toolbar_view), box);
     
-    UiContainerX *container = ui_box_container(obj, box, UI_CONTAINER_VBOX);
+    UiContainer *container = ui_box_container(obj, box, UI_CONTAINER_VBOX);
     uic_object_push_container(obj, container);
     
     return box;
@@ -1033,7 +1048,7 @@ UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs *args) {
     ui_gtk_set_margin(box, args->margin, args->margin_left, args->margin_right, args->margin_top, args->margin_bottom);
     BOX_ADD_EXPAND(sidebar_vbox, box);
     
-    UiContainerX *container = ui_box_container(obj, box, UI_CONTAINER_VBOX);
+    UiContainer *container = ui_box_container(obj, box, UI_CONTAINER_VBOX);
     uic_object_push_container(obj, container);
     
     return box;
@@ -1053,7 +1068,7 @@ static UIWIDGET splitwindow_panel(UiObject *obj, GtkWidget *pbox, UiSidebarArgs
     ui_gtk_set_margin(box, args->margin, args->margin_left, args->margin_right, args->margin_top, args->margin_bottom);
     BOX_ADD_EXPAND(pbox, box);
     
-    UiContainerX *container = ui_box_container(obj, box, UI_CONTAINER_VBOX);
+    UiContainer *container = ui_box_container(obj, box, UI_CONTAINER_VBOX);
     uic_object_push_container(obj, container);
     
     return box;
@@ -1120,7 +1135,7 @@ static UIWIDGET splitpane_create(UiObject *obj, UiOrientation orientation, UiSpl
     }
     
     UiSplitPane *splitpane = ui_create_splitpane_data(pane0, orientation, max, args->initial_position);
-    UiContainerX *container = ui_splitpane_container(obj, pane0, splitpane);
+    UiContainer *container = ui_splitpane_container(obj, pane0, splitpane);
     uic_object_push_container(obj, container);
     
     g_object_set_data(G_OBJECT(pane0), "ui_splitpane", splitpane);
@@ -1157,12 +1172,12 @@ UiSplitPane* ui_create_splitpane_data(GtkWidget *pane, UiOrientation orientation
     return ct;
 }
 
-UiContainerX* ui_splitpane_container(UiObject *obj, GtkWidget *pane, UiSplitPane *data) {
+UiContainer* ui_splitpane_container(UiObject *obj, GtkWidget *pane, UiSplitPane *data) {
     UiSplitPaneContainer *ct = ui_calloc(obj->ctx, 1, sizeof(UiSplitPaneContainer));
     ct->container.widget = pane;
     ct->container.add = ui_splitpane_container_add;
     ct->splitpane = data;
-    return (UiContainerX*)ct;
+    return (UiContainer*)ct;
 }
 
 void ui_splitpane_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout) {
index a5e46b2febf605ee407484900fb7342def5f0bfb..352b50ea01cf6f729eea6aeb96a2f87b8dfe07e2 100644 (file)
@@ -50,7 +50,7 @@ typedef struct UiDocumentView UiDocumentView;
 
 typedef struct UiContainerPrivate UiContainerPrivate;
 struct UiContainerPrivate {
-    UiContainerX container;
+    UiContainer container;
     GtkWidget *widget;
     UIMENU menu;
     
@@ -160,11 +160,11 @@ GtkWidget* ui_subcontainer_create(
 GtkWidget* ui_gtk_set_margin(GtkWidget *widget, int margin, int margin_left, int margin_right, int margin_top, int margin_bottom);
 UIWIDGET ui_box_create(UiObject *obj, UiContainerArgs *args, UiSubContainerType type);
 
-UiContainerX* ui_box_container(UiObject *obj, GtkWidget *box, UiSubContainerType type);
+UiContainer* ui_box_container(UiObject *obj, GtkWidget *box, UiSubContainerType type);
 void ui_box_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout);
 
 GtkWidget* ui_create_grid_widget(int colspacing, int rowspacing);
-UiContainerX* ui_grid_container(
+UiContainer* ui_grid_container(
         UiObject *obj,
         GtkWidget *grid,
         UiBool def_hexpand,
@@ -173,20 +173,20 @@ UiContainerX* ui_grid_container(
         UiBool def_vfill);
 void ui_grid_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout);
 
-UiContainerX* ui_frame_container(UiObject *obj, GtkWidget *frame);
+UiContainer* ui_frame_container(UiObject *obj, GtkWidget *frame);
 void ui_frame_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout);
 
-UiContainerX* ui_expander_container(UiObject *obj, GtkWidget *expander);
+UiContainer* ui_expander_container(UiObject *obj, GtkWidget *expander);
 void ui_expander_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout);
 
-UiContainerX* ui_scrolledwindow_container(UiObject *obj, GtkWidget *scrolledwindow);
+UiContainer* ui_scrolledwindow_container(UiObject *obj, GtkWidget *scrolledwindow);
 void ui_scrolledwindow_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout);
 
-UiContainerX* ui_tabview_container(UiObject *obj, GtkWidget *tabview);
+UiContainer* ui_tabview_container(UiObject *obj, GtkWidget *tabview);
 void ui_tabview_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout);
 
 UiSplitPane* ui_create_splitpane_data(GtkWidget *pane, UiOrientation orientation, int max, int init);
-UiContainerX* ui_splitpane_container(UiObject *obj, GtkWidget *pane, UiSplitPane *data);
+UiContainer* ui_splitpane_container(UiObject *obj, GtkWidget *pane, UiSplitPane *data);
 void ui_splitpane_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout);
 
 int64_t ui_splitpane_get(UiInteger *i);
@@ -197,11 +197,11 @@ UiGtkTabView* ui_widget_get_tabview_data(UIWIDGET tabview);
 void ui_gtk_notebook_select_tab(GtkWidget *widget, int tab);
 
 #if GTK_CHECK_VERSION(3, 10, 0)
-UiContainerX* ui_headerbar_container(UiObject *obj, GtkWidget *headerbar);
+UiContainer* ui_headerbar_container(UiObject *obj, GtkWidget *headerbar);
 void ui_headerbar_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout);
 #endif
 
-UiContainerX* ui_headerbar_fallback_container(UiObject *obj, GtkWidget *headerbar);
+UiContainer* ui_headerbar_fallback_container(UiObject *obj, GtkWidget *headerbar);
 void ui_headerbar_fallback_container_add(UiContainerPrivate *ct, GtkWidget *widget, UiLayout *layout);
 
 #ifdef __cplusplus
index 1f8c39e1a32104d73638e17975cd07d2a1a54814..1a4073c089b5c98fa64e6e5b26386d153c490290 100644 (file)
@@ -115,6 +115,8 @@ UIWIDGET ui_label_create(UiObject *obj, UiLabelArgs *args) {
     UiLayout layout = UI_ARGS2LAYOUT(args);
     ct->add(ct, widget, &layout);
     
+    uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
+    
     return widget;
 }
 
@@ -205,6 +207,8 @@ UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs *args) {
     UiLayout layout = UI_ARGS2LAYOUT(args);
     ct->add(ct, progressbar, &layout);
     
+    uic_widget_set_visibility_states(obj->ctx, progressbar, args->visibility_states);
+    
     return progressbar;
 }
 
@@ -246,6 +250,8 @@ UIWIDGET ui_progressspinner_create(UiObject* obj, UiProgressbarSpinnerArgs *args
     UiLayout layout = UI_ARGS2LAYOUT(args);
     ct->add(ct, spinner, &layout);
     
+    uic_widget_set_visibility_states(obj->ctx, spinner, args->visibility_states);
+    
     return spinner;
 }
 
index ef1d9c7e151fa79cf0203d2906eb32dab19031b0..a8ba5356908836fcf80ad9d986eddab2b6a0863d 100644 (file)
@@ -30,6 +30,9 @@
 
 #include "button.h"
 #include "menu.h"
+#include "../ui/widget.h"
+
+#include <cx/array_list.h>
 
 #include "../ui/properties.h"
 
@@ -66,53 +69,66 @@ void ui_fill_headerbar(UiObject *obj, GtkWidget *sidebar_headerbar, GtkWidget *m
     }
     
     // main toolbar
-    ui_headerbar_add_items(obj, main_headerbar, left_defaults, UI_TOOLBAR_LEFT);
-    ui_headerbar_add_items(obj, main_headerbar, center_defaults, UI_TOOLBAR_CENTER);
+    ui_headerbar_add_items(obj, main_headerbar, left_defaults, UI_TOOLBAR_LEFT, NULL);
+    ui_headerbar_add_items(obj, main_headerbar, center_defaults, UI_TOOLBAR_CENTER, NULL);
     
     if(appmenu && appmenu_pos == UI_TOOLBAR_RIGHT) {
         ui_add_headerbar_menu(main_headerbar, NULL, appmenu, obj, UI_TOOLBAR_RIGHT);
     }
-    ui_headerbar_add_items(obj, main_headerbar, right_defaults, UI_TOOLBAR_RIGHT);
+    ui_headerbar_add_items(obj, main_headerbar, right_defaults, UI_TOOLBAR_RIGHT, NULL);
     
     // sidebar
     if(sidebar_headerbar) {
         // ui_headerbar_add_items pos parameter uses only UI_TOOLBAR_LEFT, UI_TOOLBAR_CENTER, UI_TOOLBAR_RIGHT
-        ui_headerbar_add_items(obj, sidebar_headerbar, sidebar_left_defaults, UI_TOOLBAR_LEFT);
+        ui_headerbar_add_items(obj, sidebar_headerbar, sidebar_left_defaults, UI_TOOLBAR_LEFT, NULL);
 
         if(appmenu && appmenu_pos == UI_TOOLBAR_SIDEBAR_RIGHT) {
             ui_add_headerbar_menu(sidebar_headerbar, NULL, appmenu, obj, UI_TOOLBAR_RIGHT);
         }
-        ui_headerbar_add_items(obj, sidebar_headerbar, sidebar_right_defaults, UI_TOOLBAR_RIGHT);
+        ui_headerbar_add_items(obj, sidebar_headerbar, sidebar_right_defaults, UI_TOOLBAR_RIGHT, NULL);
     }
     
     // right panel
     if(right_headerbar) {
-        ui_headerbar_add_items(obj, right_headerbar, rightpanel_left_defaults, UI_TOOLBAR_LEFT);
-        ui_headerbar_add_items(obj, right_headerbar, rightpanel_center_defaults, UI_TOOLBAR_CENTER);
+        // also add central toolbar items, in case the central pane is hidden
+        CxList *backup_toolbar_widgets = cxArrayListCreate(obj->ctx->allocator, CX_STORE_POINTERS, 16);
+        ui_headerbar_add_items(obj, right_headerbar, left_defaults, UI_TOOLBAR_LEFT, backup_toolbar_widgets);
+        ui_headerbar_add_items(obj, right_headerbar, center_defaults, UI_TOOLBAR_LEFT, backup_toolbar_widgets);
+        ui_headerbar_add_items(obj, right_headerbar, right_defaults, UI_TOOLBAR_LEFT, backup_toolbar_widgets);
+        CxIterator i = cxListIterator(backup_toolbar_widgets);
+        cx_foreach(GtkWidget *, w, i) {
+            ui_set_visible(w, FALSE);
+        }
+        g_object_set_data(G_OBJECT(obj->widget), "ui_toolbar_center_backup", backup_toolbar_widgets);
+        
+        // main items for the right panel
+        ui_headerbar_add_items(obj, right_headerbar, rightpanel_left_defaults, UI_TOOLBAR_LEFT, NULL);
+        ui_headerbar_add_items(obj, right_headerbar, rightpanel_center_defaults, UI_TOOLBAR_CENTER, NULL);
 
         if(appmenu && appmenu_pos == UI_TOOLBAR_RIGHTPANEL_RIGHT) {
             ui_add_headerbar_menu(right_headerbar, NULL, appmenu, obj, UI_TOOLBAR_RIGHT);
         }
-        ui_headerbar_add_items(obj, right_headerbar, rightpanel_right_defaults, UI_TOOLBAR_RIGHT);
+        ui_headerbar_add_items(obj, right_headerbar, rightpanel_right_defaults, UI_TOOLBAR_RIGHT, NULL);
     }
 }
 
-static void create_item(UiObject *obj, GtkWidget *headerbar, GtkWidget *box, UiToolbarItemI *i, enum UiToolbarPos pos) {
+static GtkWidget* create_item(UiObject *obj, GtkWidget *headerbar, GtkWidget *box, UiToolbarItemI *i, enum UiToolbarPos pos) {
     switch(i->type) {
         case UI_TOOLBAR_ITEM: {
-            ui_add_headerbar_item(headerbar, box, (UiToolbarItem*)i, obj, pos);
-            break;
+            return ui_add_headerbar_item(headerbar, box, (UiToolbarItem*)i, obj, pos);
         }
         case UI_TOOLBAR_TOGGLEITEM: {
-            ui_add_headerbar_toggleitem(headerbar, box, (UiToolbarToggleItem*)i, obj, pos);
-            break;
+            return ui_add_headerbar_toggleitem(headerbar, box, (UiToolbarToggleItem*)i, obj, pos);
+        }
+        case UI_TOOLBAR_CONTENT_TOGGLEITEM: {
+            return ui_add_headerbar_content_toggleitem(headerbar, box, (UiToolbarContentToggleItem*)i, obj, pos);
         }
         case UI_TOOLBAR_MENU: {
-            ui_add_headerbar_menu(headerbar, box, (UiToolbarMenuItem*)i, obj, pos);
-            break;
+            return ui_add_headerbar_menu(headerbar, box, (UiToolbarMenuItem*)i, obj, pos);
         }
         default: fprintf(stderr, "toolbar item type unimplemented: %d\n", (int)i->type);
     }
+    return NULL;
 }
 
 static void headerbar_add(GtkWidget *headerbar, GtkWidget *box, GtkWidget *item, enum UiToolbarPos pos) {
@@ -137,12 +153,15 @@ static void headerbar_add(GtkWidget *headerbar, GtkWidget *box, GtkWidget *item,
     }
 }
 
-void ui_headerbar_add_items(UiObject *obj, GtkWidget *headerbar, CxList *items, enum UiToolbarPos pos) {
+void ui_headerbar_add_items(UiObject *obj, GtkWidget *headerbar, CxList *items, enum UiToolbarPos pos, CxList *out_items) {
     GtkWidget *box = NULL;
     
     if(pos == UI_TOOLBAR_CENTER && cxListSize(items) > 0) {
         box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
         UI_HEADERBAR_SET_TITLE_WIDGET(headerbar, box);
+        if(out_items) {
+            cxListAdd(out_items, box);
+        }
     }
     
     CxIterator i = pos == UI_TOOLBAR_RIGHT ? cxListBackwardsIterator(items) : cxListIterator(items);
@@ -152,25 +171,29 @@ void ui_headerbar_add_items(UiObject *obj, GtkWidget *headerbar, CxList *items,
             fprintf(stderr, "unknown toolbar item: %s\n", def);
             continue;
         }
-        create_item(obj, headerbar, box, item, pos);
+        GtkWidget *item_widget = create_item(obj, headerbar, box, item, pos);
+        if(out_items && !box) {
+            cxListAdd(out_items, item_widget);
+        }
     }
 }
 
-void ui_add_headerbar_item(
+GtkWidget* ui_add_headerbar_item(
         GtkWidget *headerbar,
         GtkWidget *box,
         UiToolbarItem *item,
         UiObject *obj,
         enum UiToolbarPos pos)
 {
-    GtkWidget *button = ui_create_button(obj, item->args.label, item->args.icon, item->args.tooltip, item->args.onclick, item->args.onclickdata, 0, FALSE);
+    GtkWidget *button = ui_create_button(obj, item->args.label, item->args.icon, item->args.tooltip, item->args.onclick, item->args.onclickdata, item->args.action, 0, FALSE);
     ui_set_widget_states(obj->ctx, button, item->args.states);
     ui_set_widget_visibility_states(obj->ctx, button, item->args.visibility_states);
     WIDGET_ADD_CSS_CLASS(button, "flat");
     headerbar_add(headerbar, box, button, pos);
+    return button;
 }
 
-void ui_add_headerbar_toggleitem(
+GtkWidget* ui_add_headerbar_toggleitem(
         GtkWidget *headerbar,
         GtkWidget *box,
         UiToolbarToggleItem *item,
@@ -181,11 +204,39 @@ void ui_add_headerbar_toggleitem(
     ui_set_widget_states(obj->ctx, button, item->args.states);
     ui_set_widget_visibility_states(obj->ctx, button, item->args.visibility_states);
     WIDGET_ADD_CSS_CLASS(button, "flat");
-    ui_setup_togglebutton(obj, button, item->args.label, item->args.icon, item->args.tooltip, item->args.varname, NULL, item->args.onchange, item->args.onchangedata, 0);
+    ui_setup_togglebutton(obj, button, item->args.label, item->args.icon, item->args.tooltip, item->args.varname, NULL, item->args.onchange, item->args.onchangedata, item->args.action, 0);
     headerbar_add(headerbar, box, button, pos);
+    return button;
 }
 
-void ui_add_headerbar_menu(
+GtkWidget* ui_add_headerbar_content_toggleitem(
+        GtkWidget *headerbar,
+        GtkWidget *box,
+        UiToolbarContentToggleItem *item,
+        UiObject *obj,
+        enum UiToolbarPos pos)
+{
+    UiContentToggleArgs args = { 0 };
+    args.label0 = item->args.label0;
+    args.icon0 = item->args.icon0;
+    args.tooltip0 = item->args.tooltip0;
+    args.label1 = item->args.label1;
+    args.icon1 = item->args.icon1;
+    args.tooltip1 = item->args.tooltip1;
+    args.varname = item->args.varname;
+    args.onchange = item->args.onchange;
+    args.onchangedata = item->args.onchangedata;
+    args.action = item->args.action;
+    args.istogglebutton = item->args.istogglebutton;
+    args.toggled_by_state = item->args.toggled_by_state;
+    
+    GtkWidget *button = ui_create_content_togglebutton(obj, &args);
+    WIDGET_ADD_CSS_CLASS(button, "flat");
+    headerbar_add(headerbar, box, button, pos);
+    return button;
+}
+
+GtkWidget* ui_add_headerbar_menu(
         GtkWidget *headerbar,
         GtkWidget *box,
         UiToolbarMenuItem *item,
@@ -222,6 +273,8 @@ void ui_add_headerbar_menu(
 #endif
     
     headerbar_add(headerbar, box, menubutton, pos);
+    
+    return menubutton;
 }
     
 #endif // GTK_CHECK_VERSION(3, 10, 0)
index d3786c8cd15972664980a1eff2c84acc84d7b6c0..50e877b15409e9871200c633bf753e2ac57a1e55 100644 (file)
@@ -65,23 +65,30 @@ extern "C" {
     
 void ui_fill_headerbar(UiObject *obj, GtkWidget *sidebar_headerbar, GtkWidget *main_headerbar, GtkWidget *right_headerbar);
 
-void ui_headerbar_add_items(UiObject *obj, GtkWidget *headerbar, CxList *items, enum UiToolbarPos pos);
+void ui_headerbar_add_items(UiObject *obj, GtkWidget *headerbar, CxList *items, enum UiToolbarPos pos, CxList *out_items);
 
-void ui_add_headerbar_item(
+GtkWidget* ui_add_headerbar_item(
         GtkWidget *headerbar,
         GtkWidget *box,
         UiToolbarItem *item,
         UiObject *obj,
         enum UiToolbarPos pos);
 
-void ui_add_headerbar_toggleitem(
+GtkWidget* ui_add_headerbar_toggleitem(
         GtkWidget *headerbar,
         GtkWidget *box,
         UiToolbarToggleItem *item,
         UiObject *obj,
         enum UiToolbarPos pos);
 
-void ui_add_headerbar_menu(
+GtkWidget* ui_add_headerbar_content_toggleitem(
+        GtkWidget *headerbar,
+        GtkWidget *box,
+        UiToolbarContentToggleItem *item,
+        UiObject *obj,
+        enum UiToolbarPos pos);
+
+GtkWidget* ui_add_headerbar_menu(
         GtkWidget *headerbar,
         GtkWidget *box,
         UiToolbarMenuItem *item,
index 16568eed5028fc013aa6f8c1b9287c60a1d740b1..1dfd52fcaa62b27c296683b088b9b3c0f7474bdb 100644 (file)
@@ -123,6 +123,8 @@ UiIcon* ui_fileicon(size_t size) {
     char *path = g_file_get_path(file);
     if(!path) {
         icon = ui_icon("application-x-generic", size);
+    } else {
+        g_free(path);
     }
 #else
     if(!icon) {
@@ -143,6 +145,7 @@ GdkPixbuf* ui_icon_pixbuf(UiIcon *icon) {
         GError *error = NULL;
         char *path = g_file_get_path(file);
         icon->pixbuf = gdk_pixbuf_new_from_file(path, &error);
+        g_free(path);
     }
     return icon->pixbuf;
 }
index e8b649cdc261c09361aeda5a4d40a03786c44dea..14f8aecf3fafab57ec6b360c9013eceb804c8bad 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "../common/context.h"
 #include "../common/object.h"
+#include "../common/action.h"
 #include "container.h"
 
 #include <cx/array_list.h>
@@ -83,14 +84,19 @@ static UiListView* create_listview(UiObject *obj, UiListArgs *args) {
     tableview->multiselection = args->multiselection;
     tableview->onactivate = args->onactivate;
     tableview->onactivatedata = args->onactivatedata;
+    tableview->onactivate_action = args->onactivate_action ? strdup(args->onactivate_action) : NULL;
     tableview->onselection = args->onselection;
     tableview->onselectiondata = args->onselectiondata;
+    tableview->onselection_action = args->onselection_action ? strdup(args->onselection_action) : NULL;
     tableview->ondragstart = args->ondragstart;
     tableview->ondragstartdata = args->ondragstartdata;
+    tableview->ondragstart_action = args->ondragstart_action ? strdup(args->ondragstart_action) : NULL;
     tableview->ondragcomplete = args->ondragcomplete;
     tableview->ondragcompletedata = args->ondragcompletedata;
+    tableview->ondragcomplete_action = args->ondragcomplete_action ? strdup(args->ondragcomplete_action) : NULL;
     tableview->ondrop = args->ondrop;
     tableview->ondropdata = args->ondropdata;
+    tableview->ondrop_action = args->ondrop_action ? strdup(args->ondrop_action) : NULL;
     tableview->selection.count = 0;
     tableview->selection.rows = NULL;
     tableview->current_row = -1;
@@ -254,7 +260,7 @@ static void column_factory_setup(GtkListItemFactory *factory, GtkListItem *item,
     } else if(type == UI_BOOL_EDITABLE) {
         GtkWidget *checkbox = gtk_check_button_new();
         gtk_list_item_set_child(item, checkbox);
-    }else {
+    } else {
         GtkWidget *label = gtk_label_new(NULL);
         gtk_label_set_xalign(GTK_LABEL(label), 0);
         gtk_list_item_set_child(item, label);
@@ -345,6 +351,7 @@ static void column_factory_bind(GtkListItemFactory *unused, GtkListItem *item, g
         }
         case UI_STRING: {
             gtk_label_set_label(GTK_LABEL(child), data);
+            gtk_label_set_ellipsize(GTK_LABEL(child), PANGO_ELLIPSIZE_END);
             if(freevalue) {
                 free(data);
             }
@@ -508,7 +515,7 @@ UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args) {
     }
     
     // event handling
-    if(args->onactivate) {
+    if(args->onactivate || args->onactivate_action) {
         // columnview and listview can use the same callback function, because
         // the first parameter (which is technically a different pointer type)
         // is ignored
@@ -661,6 +668,9 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) {
     
     GtkSelectionModel *selection_model = create_selection_model(tableview, ls, args->multiselection);
     GtkWidget *view = gtk_column_view_new(GTK_SELECTION_MODEL(selection_model));
+    if(args->hide_header) {
+        gtk_widget_set_visible(gtk_widget_get_first_child(view), FALSE);
+    }
     
     UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST);
     
@@ -715,7 +725,7 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) {
     }
     
     // event handling
-    if(args->onactivate) {
+    if(args->onactivate || args->onactivate_action) {
         g_signal_connect(view, "activate", G_CALLBACK(ui_columnview_activate), tableview);
     }
     if(args->contextmenu) {
@@ -803,7 +813,7 @@ static UiListSelection selectionmodel_get_selection(GtkSelectionModel *model) {
     return sel;
 }
 
-static void listview_event(ui_callback cb, void *cbdata, UiListView *view) {
+static void listview_event(ui_callback cb, void *cbdata, const char *action, UiListView *view) {
     UiEvent event;
     event.obj = view->obj;
     event.document = event.obj->ctx->document;
@@ -815,6 +825,10 @@ static void listview_event(ui_callback cb, void *cbdata, UiListView *view) {
     if(cb) {
         cb(&event, cbdata);
     }
+    
+    if(action) {
+        uic_action_callback(&event, action);
+    }
 }
 
 static void listview_update_selection(UiListView *view) {
@@ -865,13 +879,15 @@ void ui_columnview_activate(void *ignore, guint position, gpointer userdata) {
     if(view->selection.count == 0) {
         listview_update_selection(view);
     }
-    listview_event(view->onactivate, view->onactivatedata, view);
+    listview_event(view->onactivate, view->onactivatedata, view->onactivate_action, view);
 }
 
 void ui_listview_selection_changed(GtkSelectionModel* self, guint position, guint n_items, gpointer userdata) {
     UiListView *view = userdata;
     listview_update_selection(view);
-    listview_event(view->onselection, view->onselectiondata, view);
+    if(ui_selection_events_is_enabled()) {
+        listview_event(view->onselection, view->onselectiondata, view->onselection_action, view);
+    }
 }
 
 void ui_dropdown_activate(GtkDropDown* self, gpointer userdata) {
@@ -922,6 +938,9 @@ void ui_listview_update2(UiList *list, int i) {
     if(i < 0) {
         cxMapClear(view->bound_rows);
         ui_update_liststore(view->liststore, list);
+        free(view->selection.rows);
+        view->selection.rows = NULL;
+        view->selection.count = 0;
     } else {
         void *value = list->get(list, i);
         if(value) {
@@ -1240,6 +1259,11 @@ static GtkListStore* create_list_store(UiListView *listview, UiList *list) {
     return store;
 }
 
+static void ui_destroy_tree_eventdata(GtkWidget *object, UiTreeEventData *data) {
+    free(data->activate_action);
+    free(data->selection_action);
+    free(data);
+}
 
 UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args) {
     // create treeview
@@ -1297,22 +1321,23 @@ UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args) {
     event->obj = obj;
     event->activate = args->onactivate;
     event->activatedata = args->onactivatedata;
+    event->activate_action = args->onactivate_action ? strdup(args->onactivate_action) : NULL;
     event->selection = args->onselection;
     event->selectiondata = args->onselectiondata;
+    event->selection_action = args->onselection_action ? strdup(args->onselection_action) : NULL;
     g_signal_connect(
             view,
             "destroy",
-            G_CALLBACK(ui_destroy_userdata),
+            G_CALLBACK(ui_destroy_tree_eventdata),
             event);
-    
-    if(args->onactivate) {
+    if(args->onactivate || args->onactivate_action) {
         g_signal_connect(
                 view,
                 "row-activated",
                 G_CALLBACK(ui_listview_activate_event),
                 event);
     }
-    if(args->onselection) {
+    if(args->onselection || args->onselection_action) {
         GtkTreeSelection *selection = gtk_tree_view_get_selection(
                 GTK_TREE_VIEW(view));
         g_signal_connect(
@@ -1385,6 +1410,9 @@ static void table_cell_edited(
 UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) {
     // create treeview
     GtkWidget *view = gtk_tree_view_new();
+    if(args->hide_header) {
+        gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE);
+    }
     
     UiModel *model = args->model;
     int columns = model ? model->columns : 0;
@@ -1521,20 +1549,27 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) {
     list->obj = tableview;
     
     // add callback
-    UiTreeEventData *event = ui_malloc(obj->ctx, sizeof(UiTreeEventData));
+    UiTreeEventData *event = malloc(sizeof(UiTreeEventData));
     event->obj = obj;
     event->activate = args->onactivate;
-    event->selection = args->onselection;
     event->activatedata = args->onactivatedata;
+    event->activate_action = args->onactivate_action ? strdup(args->onactivate_action) : NULL;
+    event->selection = args->onselection;
     event->selectiondata = args->onselectiondata;
-    if(args->onactivate) {
+    event->selection_action = args->onselection_action ? strdup(args->onselection_action) : NULL;
+    g_signal_connect(
+            view,
+            "destroy",
+            G_CALLBACK(ui_destroy_tree_eventdata),
+            event);
+    if(args->onactivate || args->onactivate_action) {
         g_signal_connect(
                 view,
                 "row-activated",
                 G_CALLBACK(ui_listview_activate_event),
                 event);
     }
-    if(args->onselection) {
+    if(args->onselection || args->onselection_action) {
         GtkTreeSelection *selection = gtk_tree_view_get_selection(
                 GTK_TREE_VIEW(view));
         g_signal_connect(
@@ -1543,8 +1578,6 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) {
                 G_CALLBACK(ui_listview_selection_event),
                 event);
     }
-    // TODO: destroy callback
-    
     
     if(args->ondragstart) {
         ui_listview_add_dnd(tableview, args);
@@ -1776,19 +1809,28 @@ void ui_listview_activate_event(
     e.window = event->obj->window;
     e.document = event->obj->ctx->document;
     e.eventdata = &selection;
+    e.eventdatatype = UI_EVENT_DATA_LIST_SELECTION;
     e.intval = selection.count > 0 ? selection.rows[0] : -1;
     e.set = ui_get_setop();
-    event->activate(&e, event->activatedata);
     
-    if(selection.count > 0) {
-        free(selection.rows);
+    if(event->activate) {
+        event->activate(&e, event->activatedata);
+    }
+    if(event->activate_action) {
+        uic_action_callback(&e, event->activate_action);
     }
+    
+    free(selection.rows);
 }
 
 void ui_listview_selection_event(
         GtkTreeSelection *treeselection,
         UiTreeEventData *event)
 {
+    if(!ui_selection_events_is_enabled()) {
+        return;
+    }
+    
     UiListSelection selection = ui_listview_get_selection(treeselection, event);
     
     UiEvent e;
@@ -1796,13 +1838,17 @@ void ui_listview_selection_event(
     e.window = event->obj->window;
     e.document = event->obj->ctx->document;
     e.eventdata = &selection;
+    e.eventdatatype = UI_EVENT_DATA_LIST_SELECTION;
     e.intval = selection.count > 0 ? selection.rows[0] : -1;
     e.set = ui_get_setop();
-    event->selection(&e, event->selectiondata);
-    
-    if(selection.count > 0) {
-        free(selection.rows);
+    if(event->selection) {
+        event->selection(&e, event->selectiondata);
     }
+    if(event->selection_action) {
+        uic_action_callback(&e, event->selection_action);
+    }
+    
+    free(selection.rows);
 }
 
 UiListSelection ui_listview_get_selection(
@@ -2159,6 +2205,11 @@ void ui_table_dragdest_a(UIWIDGET tablewidget, int actions, char **targets, int
 */
 
 void ui_listview_destroy(GtkWidget *w, UiListView *v) {
+    free(v->onactivate_action);
+    free(v->onselection_action);
+    free(v->ondragstart_action);
+    free(v->ondragcomplete_action);
+    free(v->ondrop_action);
     //gtk_tree_view_set_model(GTK_TREE_VIEW(w), NULL);
     if(v->var) {
         ui_destroy_boundvar(v->obj->ctx, v->var);
index e7beb0e79e2861bbcef9e316b04513a3b6b7baec..69f30e4d8f2c2d379e09dcc73cf25a22f754f42d 100644 (file)
@@ -81,14 +81,19 @@ struct UiListView {
 #endif
     ui_callback       onactivate;
     void              *onactivatedata;
+    char              *onactivate_action;
     ui_callback       onselection;
     void              *onselectiondata;
+    char              *onselection_action;
     ui_callback       ondragstart;
     void              *ondragstartdata;
+    char              *ondragstart_action;
     ui_callback       ondragcomplete;
     void              *ondragcompletedata;
+    char              *ondragcomplete_action;
     ui_callback       ondrop;
     void              *ondropdata;
+    char              *ondrop_action;
     ui_list_savefunc  onsave;
     void              *onsavedata;
     UiListSelection   selection;
@@ -101,6 +106,8 @@ typedef struct UiTreeEventData {
     ui_callback selection;
     void        *activatedata;
     void        *selectiondata;
+    char        *activate_action;
+    char        *selection_action;
 } UiTreeEventData;
 
 typedef struct UiListBox UiListBox;
index 8bfbbbfe493608bc5617ea9741f9dbff59be66c9..5ce909d057c9dfb12ea6348cbf434b80787f68c7 100644 (file)
@@ -37,6 +37,7 @@
 #include "../common/context.h"
 #include "../common/menu.h"
 #include "../common/types.h"
+#include "../common/action.h"
 #include "../ui/properties.h"
 #include "../ui/window.h"
 #include "container.h"
@@ -276,6 +277,7 @@ void add_menuitem_list_widget(GtkWidget *p, int index, UiMenuItemI *item, UiObje
     ls->index = index;
     ls->oldcount = 0;
     ls->getvalue = il->getvalue;
+    ls->getvaluedata = il->getvaluedata;
     
     UiVar* var = uic_create_var(ui_global_context(), il->varname, UI_VAR_LIST);
     //UiVar* var = uic_create_var(obj->ctx, il->varname, UI_VAR_LIST);
@@ -339,10 +341,13 @@ void ui_update_menuitem_list(UiActiveMenuItemList *list) {
         gtk_widget_show(widget);
     }
     
-    ui_getvaluefunc getvalue = list->getvalue;
+    ui_getvaluefunc2 getvalue = list->getvalue;
+    void *getvaluedata = list->getvaluedata;
     int i = 1;
+    int row = 0;
     while(elm) {
-        char *label = (char*) (getvalue ? getvalue(elm, 0) : elm);
+        UiBool freeResult = FALSE;
+        char *label = (char*) (getvalue ? getvalue(ls, elm, row, 0, getvaluedata, &freeResult) : elm);
         
         GtkWidget *widget = gtk_menu_item_new_with_label(label);
         gtk_menu_shell_insert(list->menu, widget, list->index + i);
@@ -371,6 +376,11 @@ void ui_update_menuitem_list(UiActiveMenuItemList *list) {
         
         elm = ui_list_next(ls);
         i++;
+        row++;
+        
+        if(freeResult) {
+            free(label);
+        }
     }
     
     list->oldcount = i;
@@ -590,7 +600,15 @@ void ui_gmenu_add_menuitem(GMenu *parent, int index, UiMenuItemI *item, UiObject
         cxListFree(groups);
     }
     
-    if(i->callback != NULL) {
+    if(i->action) {
+        uic_bind_action(obj->ctx, i->action, action, (ui_enablefunc)action_enable);
+        UiAction *ui_action = uic_resolve_action(obj->ctx, i->action);
+        if(!ui_action) {
+            action_enable(action, FALSE);
+        }
+    }
+     
+    if(i->callback != NULL || i->action) {
         UiEventData *event = malloc(sizeof(UiEventData));
         event->obj = obj;
         event->userdata = i->userdata;
@@ -598,6 +616,7 @@ void ui_gmenu_add_menuitem(GMenu *parent, int index, UiMenuItemI *item, UiObject
         event->value = 0;
         event->customdata = NULL;
         event->customint = 0;
+        event->action = i->action ? strdup(i->action) : NULL;
 
         g_signal_connect(
                 action,
@@ -607,13 +626,13 @@ void ui_gmenu_add_menuitem(GMenu *parent, int index, UiMenuItemI *item, UiObject
         g_signal_connect(
                 obj->widget,
                 "destroy",
-                G_CALLBACK(ui_destroy_userdata),
+                G_CALLBACK(ui_destroy_eventdata),
                 event);
     }
     
     char action_name[32];
     snprintf(action_name, 32, "win.%s", item->id);
-    
+     
     g_menu_append(parent, i->label, action_name);
 }
 
@@ -658,7 +677,7 @@ static void stateful_action_notify_group(UiMenuRadioGroup *group, UiInteger *i)
     
     CxIterator iter = cxListIterator(group->callbacks);
     cx_foreach(UiCallbackData *, cb, iter) {
-        event.intval = intval == iter.index;
+        event.intval = intval-1 == iter.index;
         if(cb->callback) {
             cb->callback(&event, cb->userdata);
         }
@@ -782,7 +801,7 @@ void ui_gmenu_add_radioitem(GMenu *parent, int index, UiMenuItemI *item, UiObjec
     cxListAdd(group->callbacks, &cb);
     
     
-    cxmutstr action_name = cx_asprintf("win.%s::%d", i->varname, (int)item_index);
+    cxmutstr action_name = cx_asprintf("win.%s::%d", i->varname, (int)item_index+1);
     g_menu_append(parent, i->label, action_name.ptr);
     free(action_name.ptr);
 }
@@ -815,6 +834,7 @@ void ui_gmenu_add_menuitem_list(GMenu *p, int index, UiMenuItemI *item, UiObject
     ls->index = index;
     ls->oldcount = 0;
     ls->getvalue = il->getvalue;
+    ls->getvaluedata = il->getvalue;
     
     GSimpleAction *action = g_simple_action_new(item->id, g_variant_type_new("i"));
     g_action_map_add_action(obj->ctx->action_map, G_ACTION(action));
@@ -888,7 +908,12 @@ void ui_activate_event_wrapper(GSimpleAction* self, GVariant* parameter, UiEvent
         evt.eventdatatype = uic_get_tmp_eventdata_type();
     }
     evt.intval = intval;
-    event->callback(&evt, event->userdata);
+    if(event->callback) {
+        event->callback(&evt, event->userdata);
+    }
+    if(event->action) {
+        uic_action_callback(&evt, event->action);
+    }
     uic_set_tmp_eventdata(NULL, 0);
 }
 
@@ -928,11 +953,13 @@ void ui_update_gmenu_item_list(UiActiveGMenuItemList *list) {
     UiList *ls = list->var->value;
     
     // add list items
-    ui_getvaluefunc getvalue = list->getvalue;
+    ui_getvaluefunc2 getvalue = list->getvalue;
+    void *getvaluedata = list->getvaluedata;
     int i = 0;
     void* elm = ui_list_first(ls);
     while(elm) {
-        char *label = (char*) (getvalue ? getvalue(elm, 0) : elm);
+        UiBool freeResult = FALSE;
+        char *label = (char*) (getvalue ? getvalue(ls, elm, i, 0, getvaluedata, &freeResult) : elm);
         
         GMenuItem *item = g_menu_item_new(label, NULL);
         GVariant *v = g_variant_new("i", i);
@@ -942,6 +969,10 @@ void ui_update_gmenu_item_list(UiActiveGMenuItemList *list) {
         
         elm = ui_list_next(ls);
         i++;
+        
+        if(freeResult) {
+            free(label);
+        }
     }
     
     list->oldcount = i;
index 4cfa419d81e176d30f12b3612d1767043165e95a..d113f336f1b193a317aa27cef715803b583004c3 100644 (file)
@@ -56,7 +56,8 @@ struct UiActiveMenuItemList {
     int              index;
     int              oldcount;
     UiVar            *var;
-    ui_getvaluefunc  getvalue;
+    ui_getvaluefunc2 getvalue;
+    void             *getvaluedata;
     ui_callback      callback;
     void             *userdata;
 };
@@ -95,7 +96,8 @@ struct UiActiveGMenuItemList {
     int              index;
     int              oldcount;
     UiVar            *var;
-    ui_getvaluefunc  getvalue;
+    ui_getvaluefunc2 getvalue;
+    void             *getvaluedata;
     ui_callback      callback;
     void             *userdata;
 };
index abad5a0679c8ab7a816f25b1260ab08ae5bbcffe..1c7964601c6637a9839c0348835efc036886e885 100644 (file)
@@ -48,6 +48,7 @@ GTKOBJ += dnd.o
 GTKOBJ += headerbar.o
 GTKOBJ += webview.o
 GTKOBJ += widget.o
+GTKOBJ += action.o
 
 TOOLKITOBJS += $(GTKOBJ:%=$(GTK_OBJPRE)%)
 TOOLKITSOURCE += $(GTKOBJ:%.o=gtk/%.c)
index 0bcd54df3e4c3eb071e718be050bf731c6f20512..4ce3a40565a91e9802eabfc105885660112696c1 100644 (file)
@@ -54,9 +54,9 @@ static void selection_handler(
         int sel = gtk_text_buffer_get_selection_bounds (buf, &begin, &end);
         if(sel != textview->last_selection_state) {
             if(sel) {
-                ui_set_state(textview->ctx, UI_GROUP_SELECTION);
+                ui_set_state(textview->ctx, UI_STATE_SELECTION);
             } else {
-                ui_unset_state(textview->ctx, UI_GROUP_SELECTION);
+                ui_unset_state(textview->ctx, UI_STATE_SELECTION);
             }
         }
         textview->last_selection_state = sel;
@@ -102,6 +102,17 @@ static GtkTextBuffer* create_textbuffer(UiTextArea *textarea) {
                 "changed",
                 G_CALLBACK(ui_textbuf_changed),
                 textarea);
+        
+        g_signal_connect(
+                buf,
+                "insert-text",
+                G_CALLBACK(ui_textbuf_change_insert),
+                textarea);
+        g_signal_connect(
+                buf,
+                "delete-range",
+                G_CALLBACK(ui_textbuf_change_delete),
+                textarea); 
     } else {
         fprintf(stderr, "Error: create_textbuffer: textarea == NULL\n");
     }
@@ -129,8 +140,13 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) {
     uitext->last_selection_state = 0;
     uitext->onchange = args->onchange;
     uitext->onchangedata = args->onchangedata;
+    uitext->onchange_action = args->onchange_action ? strdup(args->onchange_action) : NULL;
+    uitext->ontextchanged = args->ontextchanged;
+    uitext->ontextchangeddata = args->ontextchangeddata;
+    uitext->ontextchanged_action = args->ontextchanged_action ? strdup(args->ontextchanged_action) : NULL;
     
     g_object_set_data(G_OBJECT(text_area), "ui_textarea", uitext);
+    g_object_set_data(G_OBJECT(text_area), "ui_textarea_widget", text_area);
     
     g_signal_connect(
                 text_area,
@@ -144,6 +160,7 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) {
             GTK_POLICY_AUTOMATIC,
             GTK_POLICY_AUTOMATIC); // GTK_POLICY_ALWAYS  
     SCROLLEDWINDOW_SET_CHILD(scroll_area, text_area);
+    g_object_set_data(G_OBJECT(scroll_area), "ui_textarea_widget", text_area);
     
     ui_widget_size_request(scroll_area, args->width, args->height);
     
@@ -160,6 +177,7 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) {
     UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
     UiLayout layout = UI_ARGS2LAYOUT(args);
     ct->add(ct, scroll_area, &layout);
+    uic_widget_set_visibility_states(obj->ctx, scroll_area, args->visibility_states);
     
     // bind value
     if(var) {
@@ -174,6 +192,11 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) {
                 value->value.free(value->value.ptr);
             }
         }
+        
+        if(value->readonly) {
+            gtk_text_view_set_editable(GTK_TEXT_VIEW(text_area), FALSE);
+        }
+        
         gtk_text_view_set_buffer(GTK_TEXT_VIEW(text_area), buf);
         value->obj = text_area;
         value->save = ui_textarea_save;
@@ -183,11 +206,15 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) {
         value->set = ui_textarea_set;
         value->getsubstr = ui_textarea_getsubstr;
         value->insert = ui_textarea_insert;
+        value->replace = ui_textarea_replace;
         value->setposition = ui_textarea_setposition;
         value->position = ui_textarea_position;
+        value->showposition = ui_textarea_showposition;
+        value->setselection = ui_textarea_setselection;
         value->selection = ui_textarea_selection;
         value->length = ui_textarea_length;
         value->remove = ui_textarea_remove;
+        value->setreadonly = ui_textarea_setreadonly;
         value->data1 = buf;
         value->data2 = NULL;
         value->datatype == UI_TEXT_TYPE_BUFFER;
@@ -206,11 +233,107 @@ void ui_textarea_destroy(GtkWidget *object, UiTextArea *textarea) {
     if(textarea->var) {
         ui_destroy_boundvar(textarea->ctx, textarea->var);
     }
+    free(textarea->onchange_action);
+    free(textarea->ontextchanged_action);
     free(textarea);
 }
 
+void ui_textarea_scroll_to(UIWIDGET textarea, int pos) {
+    GtkWidget *widget = ui_textarea_gettextwidget(textarea);
+    if(!widget) {
+        fprintf(stderr, "Error: ui_textarea_scroll_to: widget is not a textarea\n");
+        return;
+    }
+    GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
+    
+    GtkTextIter offset;
+    gtk_text_buffer_get_iter_at_offset(buf, &offset, pos);
+    
+    gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(widget), &offset, 0.2, FALSE, 0, 0);
+}
+
+void ui_textarea_focus(UIWIDGET textarea) {
+    GtkWidget *widget = ui_textarea_gettextwidget(textarea);
+    if(!widget) {
+        fprintf(stderr, "Error: ui_textarea_focus: widget is not a textarea\n");
+        return;
+    }
+    gtk_widget_grab_focus(widget);
+}
+
+void ui_textarea_set_selection(UIWIDGET textarea, int begin, int end) {
+    GtkWidget *widget = ui_textarea_gettextwidget(textarea);
+    if(!widget) {
+        fprintf(stderr, "Error: ui_textarea_set_selection: widget is not a textarea\n");
+        return;
+    }
+    
+    GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
+    GtkTextIter ib;
+    GtkTextIter ie;
+    gtk_text_buffer_get_iter_at_offset(buf, &ib, begin);
+    gtk_text_buffer_get_iter_at_offset(buf, &ie, end);
+    gtk_text_buffer_select_range(buf, &ib, &ie);
+}
+
+void ui_textarea_select_all(UIWIDGET textarea) {
+    GtkWidget *widget = ui_textarea_gettextwidget(textarea);
+    if(!widget) {
+        fprintf(stderr, "Error: ui_textarea_select_all: widget is not a textarea\n");
+        return;
+    }
+    GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
+    GtkTextIter start;
+    GtkTextIter end;
+    gtk_text_buffer_get_bounds(buf, &start, &end);
+    gtk_text_buffer_select_range(buf, &start, &end);
+}
+
+void ui_textarea_set_editable(UIWIDGET textarea, UiBool editable) {
+    GtkWidget *widget = ui_textarea_gettextwidget(textarea);
+    if(!widget) {
+        fprintf(stderr, "Error: ui_textarea_set_editable: widget is not a textarea\n");
+        return;
+    }
+    gtk_text_view_set_editable(GTK_TEXT_VIEW(widget), editable);
+}
+
+UiBool ui_textarea_is_editable(UIWIDGET textarea) {
+    GtkWidget *widget = ui_textarea_gettextwidget(textarea);
+    if(!widget) {
+        fprintf(stderr, "Error: ui_textarea_is_editable: widget is not a textarea\n");
+        return 0;
+    }
+    return gtk_text_view_get_editable(GTK_TEXT_VIEW(widget));
+}
+
+void ui_textarea_set_position(UIWIDGET textarea, int pos) {
+    GtkWidget *widget = ui_textarea_gettextwidget(textarea);
+    if(!widget) {
+        fprintf(stderr, "Error: ui_textarea_set_position: widget is not a textarea\n");
+        return;
+    }
+    GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
+    GtkTextIter iter;
+    gtk_text_buffer_get_iter_at_offset(buf, &iter, pos);
+    gtk_text_buffer_place_cursor(buf, &iter);
+}
+
+int ui_textarea_get_position(UIWIDGET textarea) {
+    GtkWidget *widget = ui_textarea_gettextwidget(textarea);
+    if(!widget) {
+        fprintf(stderr, "Error: ui_textarea_get_position: widget is not a textarea\n");
+        return 0;
+    }
+    GtkTextBuffer *buf = gtk_text_view_get_buffer(GTK_TEXT_VIEW(widget));
+    GtkTextIter begin;
+    GtkTextIter end;
+    gtk_text_buffer_get_selection_bounds(buf, &begin, &end);
+    return gtk_text_iter_get_offset(&begin);
+}
+
 UIWIDGET ui_textarea_gettextwidget(UIWIDGET textarea) {
-    return SCROLLEDWINDOW_GET_CHILD(textarea);
+    return g_object_get_data(G_OBJECT(textarea), "ui_textarea_widget");
 }
 
 void ui_textarea_save(UiText *text) {
@@ -224,6 +347,7 @@ void ui_textarea_restore(UiText *text) {
         text->datatype = UI_TEXT_TYPE_BUFFER;
     }
     gtk_text_view_set_buffer(GTK_TEXT_VIEW(textarea), text->data1);
+    gtk_text_view_set_editable(GTK_TEXT_VIEW(textarea), !text->readonly);
 }
 
 void ui_textarea_text_destroy(UiText *text) {
@@ -269,7 +393,7 @@ char* ui_textarea_getsubstr(UiText *text, int begin, int end) {
     return str;
 }
 
-void ui_textarea_insert(UiText *text, int pos, char *str) {
+void ui_textarea_insert(UiText *text, int pos, const char *str) {
     GtkTextIter offset;
     gtk_text_buffer_get_iter_at_offset(text->data1, &offset, pos);
     gtk_text_buffer_insert(text->data1, &offset, str, -1);
@@ -280,6 +404,20 @@ void ui_textarea_insert(UiText *text, int pos, char *str) {
     text->value.free = NULL;
 }
 
+void ui_textarea_replace(UiText *text, int begin, int end, const char *replacement) {
+    GtkTextBuffer *buffer = text->data1;
+    GtkTextIter begin_offset;
+    GtkTextIter end_offset;
+    gtk_text_buffer_get_iter_at_offset(buffer, &begin_offset, begin);
+    gtk_text_buffer_get_iter_at_offset(buffer, &end_offset, end);
+    gtk_text_buffer_begin_user_action(buffer);
+    gtk_text_buffer_delete(buffer, &begin_offset, &end_offset);
+    if(replacement) {
+        gtk_text_buffer_insert(buffer, &begin_offset, replacement, -1);
+    }
+    gtk_text_buffer_end_user_action(buffer);
+}
+
 void ui_textarea_setposition(UiText *text, int pos) {
     GtkTextIter iter;
     gtk_text_buffer_get_iter_at_offset(text->data1, &iter, pos);
@@ -294,6 +432,21 @@ int ui_textarea_position(UiText *text) {
     return text->pos;
 }
 
+void ui_textarea_showposition(UiText *text, int pos) {
+    if(text->obj) {
+        ui_textarea_scroll_to(text->obj, pos);
+    }
+}
+
+void ui_textarea_setselection(UiText *text, int begin, int end) {
+    GtkTextBuffer *buf = text->data1;
+    GtkTextIter ib;
+    GtkTextIter ie;
+    gtk_text_buffer_get_iter_at_offset(text->data1, &ib, begin);
+    gtk_text_buffer_get_iter_at_offset(text->data1, &ie, end);
+    gtk_text_buffer_select_range(buf, &ib, &ie);
+}
+
 void ui_textarea_selection(UiText *text, int *begin, int *end) {
     GtkTextIter b;
     GtkTextIter e;
@@ -319,11 +472,72 @@ void ui_textarea_remove(UiText *text, int begin, int end) {
     gtk_text_buffer_delete(buf, &ib, &ie);
 }
 
+void ui_textarea_setreadonly(UiText *text, int readonly) {
+    if(text->obj) {
+        gtk_text_view_set_editable(GTK_TEXT_VIEW(text->obj), !readonly);
+    }
+    text->readonly = readonly;
+}
+
 void ui_textarea_realize_event(GtkWidget *widget, gpointer data) {
     gtk_widget_grab_focus(widget);
 }
 
 
+static void textbuf_change_event(UiTextArea *textarea, UiTextChangeEventData *data) {
+    if(!ui_onchange_events_is_enabled()) {
+        return;
+    }
+    
+    UiEvent e;
+    e.obj = textarea->obj;
+    e.window = e.obj->window;
+    e.document = textarea->ctx->document;
+    e.eventdata = data;
+    e.eventdatatype = UI_EVENT_DATA_TEXT_CHANGED;
+    e.intval = 0;
+    e.set = ui_get_setop();
+    
+    if(textarea->onchange) {
+        textarea->onchange(&e, textarea->onchangedata);
+    }
+    
+    if(textarea->onchange_action) {
+        uic_action_callback(&e, textarea->onchange_action);
+    }
+}
+
+void ui_textbuf_change_insert(
+        GtkTextBuffer *textbuffer,
+        GtkTextIter *location,
+        char *text,
+        int length,
+        UiTextArea *textarea)
+{
+    UiTextChangeEventData event;
+    event.type = UI_TEXT_INSERT;
+    event.begin = gtk_text_iter_get_offset(location);
+    event.end = event.begin + length;
+    event.text = text;
+    event.length = length;
+    textbuf_change_event(textarea, &event);
+}
+
+void ui_textbuf_change_delete(
+        GtkTextBuffer *self,
+        const GtkTextIter *start,
+        const GtkTextIter *end,
+        UiTextArea *textarea)
+{
+    UiTextChangeEventData event;
+    event.type = UI_TEXT_DELETE;
+    event.begin = gtk_text_iter_get_offset(start);
+    event.end = gtk_text_iter_get_offset(end);
+    event.text = NULL;
+    event.length = 0;
+    textbuf_change_event(textarea, &event);
+}
+
 
 void ui_textbuf_changed(GtkTextBuffer *textbuffer, UiTextArea *textarea) {
     if(!ui_onchange_events_is_enabled()) {
@@ -341,8 +555,12 @@ void ui_textbuf_changed(GtkTextBuffer *textbuffer, UiTextArea *textarea) {
     e.intval = 0;
     e.set = ui_get_setop();
     
-    if(textarea->onchange) {
-        textarea->onchange(&e, textarea->onchangedata);
+    if(textarea->ontextchanged) {
+        textarea->ontextchanged(&e, textarea->ontextchangeddata);
+    }
+    
+    if(textarea->ontextchanged_action) {
+        uic_action_callback(&e, textarea->ontextchanged_action);
     }
     
     if(value->observers) {
@@ -436,6 +654,7 @@ void ui_textbuf_delete(
     if(!value->data2) {
         value->data2 = ui_create_undomgr();
     }
+    GtkTextBuffer *buf = value->data1;
     UiUndoMgr *mgr = value->data2;
     if(!mgr->event) {
         return;
@@ -455,7 +674,7 @@ void ui_textbuf_delete(
         }
     }
     
-    char *text = gtk_text_buffer_get_text(value->obj, start, end, FALSE);
+    char *text = gtk_text_buffer_get_text(buf, start, end, FALSE);
     
     UiTextBufOp *op = malloc(sizeof(UiTextBufOp));
     op->prev = NULL;
@@ -531,6 +750,7 @@ int ui_check_insertstr(char *oldstr, int oldlen, char *newstr, int newlen) {
 }
 
 void ui_text_undo(UiText *value) {
+    GtkTextBuffer *buf = value->data1;
     UiUndoMgr *mgr = value->data2;
     
     if(mgr->cur) {
@@ -540,17 +760,17 @@ void ui_text_undo(UiText *value) {
             case UI_TEXTBUF_INSERT: {
                 GtkTextIter begin;
                 GtkTextIter end;
-                gtk_text_buffer_get_iter_at_offset(value->obj, &begin, op->start);
-                gtk_text_buffer_get_iter_at_offset(value->obj, &end, op->end);
-                gtk_text_buffer_delete(value->obj, &begin, &end);
+                gtk_text_buffer_get_iter_at_offset(buf, &begin, op->start);
+                gtk_text_buffer_get_iter_at_offset(buf, &end, op->end);
+                gtk_text_buffer_delete(buf, &begin, &end);
                 break;
             }
             case UI_TEXTBUF_DELETE: {
                 GtkTextIter begin;
                 GtkTextIter end;
-                gtk_text_buffer_get_iter_at_offset(value->obj, &begin, op->start);
-                gtk_text_buffer_get_iter_at_offset(value->obj, &end, op->end);
-                gtk_text_buffer_insert(value->obj, &begin, op->text, op->len);
+                gtk_text_buffer_get_iter_at_offset(buf, &begin, op->start);
+                gtk_text_buffer_get_iter_at_offset(buf, &end, op->end);
+                gtk_text_buffer_insert(buf, &begin, op->text, op->len);
                 break;
             }
         }
@@ -560,6 +780,7 @@ void ui_text_undo(UiText *value) {
 }
 
 void ui_text_redo(UiText *value) {
+    GtkTextBuffer *buf = value->data1;
     UiUndoMgr *mgr = value->data2;
     
     UiTextBufOp *elm = NULL;
@@ -578,17 +799,17 @@ void ui_text_redo(UiText *value) {
             case UI_TEXTBUF_INSERT: {
                 GtkTextIter begin;
                 GtkTextIter end;
-                gtk_text_buffer_get_iter_at_offset(value->obj, &begin, op->start);
-                gtk_text_buffer_get_iter_at_offset(value->obj, &end, op->end);
-                gtk_text_buffer_insert(value->obj, &begin, op->text, op->len);
+                gtk_text_buffer_get_iter_at_offset(buf, &begin, op->start);
+                gtk_text_buffer_get_iter_at_offset(buf, &end, op->end);
+                gtk_text_buffer_insert(buf, &begin, op->text, op->len);
                 break;
             }
             case UI_TEXTBUF_DELETE: {
                 GtkTextIter begin;
                 GtkTextIter end;
-                gtk_text_buffer_get_iter_at_offset(value->obj, &begin, op->start);
-                gtk_text_buffer_get_iter_at_offset(value->obj, &end, op->end);
-                gtk_text_buffer_delete(value->obj, &begin, &end);
+                gtk_text_buffer_get_iter_at_offset(buf, &begin, op->start);
+                gtk_text_buffer_get_iter_at_offset(buf, &end, op->end);
+                gtk_text_buffer_delete(buf, &begin, &end);
                 break;
             }
         }
@@ -614,6 +835,8 @@ static UIWIDGET create_textfield(UiObject *obj, UiBool frameless, UiBool passwor
     uitext->onchangedata = args->onchangedata;
     uitext->onactivate = args->onactivate;
     uitext->onactivatedata = args->onactivatedata;
+    uitext->onactivate_action = args->onactivate_action ? strdup(args->onactivate_action) : NULL;
+    uitext->onchange_action = args->onchange_action ? strdup(args->onchange_action) : NULL;
     
     g_signal_connect(
                 textfield,
@@ -639,6 +862,7 @@ static UIWIDGET create_textfield(UiObject *obj, UiBool frameless, UiBool passwor
     UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
     UiLayout layout = UI_ARGS2LAYOUT(args);
     ct->add(ct, textfield, &layout);
+    uic_widget_set_visibility_states(obj->ctx, textfield, args->visibility_states);
     
     if(var) {
         UiString *value = var->value;
@@ -656,7 +880,7 @@ static UIWIDGET create_textfield(UiObject *obj, UiBool frameless, UiBool passwor
         value->obj = GTK_ENTRY(textfield);
     }
     
-    if(args->onchange || var) {
+    if(args->onchange || args->onchange_action || var) {
         g_signal_connect(
                 textfield,
                 "changed",
@@ -664,7 +888,7 @@ static UIWIDGET create_textfield(UiObject *obj, UiBool frameless, UiBool passwor
                 uitext);
     }
     
-    if(args->onactivate) {
+    if(args->onactivate || args->onactivate_action) {
         g_signal_connect(
                 textfield,
                 "activate",
@@ -687,8 +911,45 @@ UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs *args) {
     return create_textfield(obj, FALSE, TRUE, args);
 }
 
+void ui_textfield_focus(UIWIDGET textfield) {
+    gtk_widget_grab_focus(textfield);
+}
+
+void ui_textfield_focus_without_selecting(UIWIDGET textfield) {
+#if GTK_CHECK_VERSION(3, 16, 0)
+    gtk_entry_grab_focus_without_selecting(GTK_ENTRY(textfield));
+#else
+    gtk_widget_grab_focus(textfield);
+#endif
+}
+
+void ui_textfield_set_selection(UIWIDGET textfield, int begin, int end) {
+    ENTRY_SET_SELECTION(textfield, begin, end);
+}
+
+void ui_textfield_select_all(UIWIDGET textfield) {
+    ENTRY_SET_SELECTION(textfield, 0, -1);
+}
+
+void ui_textfield_set_editable(UIWIDGET textfield, UiBool editable) {
+    ENTRY_SET_EDITABLE(textfield, editable);
+}
+
+UiBool ui_textfield_is_editable(UIWIDGET textfield) {
+    ENTRY_IS_EDITABLE(textfield);
+}
+
+void ui_textfield_set_position(UIWIDGET textfield, int pos) {
+    ENTRY_SET_POSITION(textfield, pos);
+}
+
+int ui_textfield_get_position(UIWIDGET textfield) {
+    return ENTRY_GET_POSITION(textfield);
+}
 
 void ui_textfield_destroy(GtkWidget *object, UiTextField *textfield) {
+    free(textfield->onactivate_action);
+    free(textfield->onchange_action);
     free(textfield);
 }
 
@@ -704,7 +965,7 @@ void ui_textfield_changed(GtkEditable *editable, UiTextField *textfield) {
     e.window = e.obj->window;
     e.document = textfield->obj->ctx->document;
     e.eventdata = value;
-    e.eventdatatype = value ? UI_EVENT_DATA_TEXT_VALUE : 0;
+    e.eventdatatype = value ? UI_EVENT_DATA_STRING_VALUE : 0;
     e.intval = 0;
     e.set = ui_get_setop();
     
@@ -715,22 +976,31 @@ void ui_textfield_changed(GtkEditable *editable, UiTextField *textfield) {
     if(textfield->var) {
         ui_notify_evt(value->observers, &e);
     }
+    
+    if(textfield->onchange_action) {
+        uic_action_callback(&e, textfield->onchange_action);
+    }
 }
 
 void ui_textfield_activate(GtkEntry* self, UiTextField *textfield) {
-    if(textfield->onactivate) {
-        UiString *value = textfield->var ? textfield->var->value : NULL;
+    UiString *value = textfield->var ? textfield->var->value : NULL;
         
-        UiEvent e;
-        e.obj = textfield->obj;
-        e.window = e.obj->window;
-        e.document = textfield->obj->ctx->document;
-        e.eventdata = value;
-        e.eventdatatype = value ? UI_EVENT_DATA_TEXT_VALUE : 0;
-        e.intval = 0;
-        e.set = ui_get_setop();
+    UiEvent e;
+    e.obj = textfield->obj;
+    e.window = e.obj->window;
+    e.document = textfield->obj->ctx->document;
+    e.eventdata = value;
+    e.eventdatatype = value ? UI_EVENT_DATA_TEXT_VALUE : 0;
+    e.intval = 0;
+    e.set = ui_get_setop();
+    
+    if(textfield->onactivate) {
         textfield->onactivate(&e, textfield->onactivatedata);
     }
+    
+    if(textfield->onactivate_action) {
+        uic_action_callback(&e, textfield->onactivate_action);
+    }
 }
 
 char* ui_textfield_get(UiString *str) {
@@ -964,6 +1234,7 @@ UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs *args) {
     UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
     UiLayout layout = UI_ARGS2LAYOUT(args);
     ct->add(ct, pathtf->stack, &layout);
+    uic_widget_set_visibility_states(obj->ctx, pathtf->stack, args->visibility_states);
     
     pathtf->entry_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
     pathtf->entry = gtk_entry_new();
@@ -1139,6 +1410,7 @@ UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs *args) {
     UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
     UiLayout layout = UI_ARGS2LAYOUT(args);
     ct->add(ct, eventbox, &layout);
+    uic_widget_set_visibility_states(obj->ctx, eventbox, args->visibility_states);
     
     // hbox as parent for the GtkEntry and GtkButtonBox
     GtkWidget *hbox = ui_gtk_hbox_new(0);
index b7fbda499a8a2267190825bec206524eeeea1ea8..cb12ea1d788d25c571f185e6f0810b8d05a9b86a 100644 (file)
@@ -67,6 +67,10 @@ typedef struct UiTextArea {
     int         last_selection_state;
     ui_callback onchange;
     void        *onchangedata;
+    char        *onchange_action;
+    ui_callback ontextchanged;
+    void        *ontextchangeddata;
+    char        *ontextchanged_action;
 } UiTextArea;
 
 typedef struct UiTextField {
@@ -76,6 +80,8 @@ typedef struct UiTextField {
     void        *onchangedata;
     ui_callback onactivate;
     void        *onactivatedata;
+    char        *onactivate_action;
+    char        *onchange_action;
 } UiTextField;
 
 typedef struct UiPathTextField {
@@ -117,14 +123,31 @@ 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_insert(UiText *text, int pos, const char *str);
+void ui_textarea_replace(UiText *text, int begin, int end, const char *replacement);
 void ui_textarea_setposition(UiText *text, int pos);
 int ui_textarea_position(UiText *text);
+void ui_textarea_showposition(UiText *text, int pos);
+void ui_textarea_setselection(UiText *text, int begin, int end);
 void ui_textarea_selection(UiText *text, int *begin, int *end);
 int ui_textarea_length(UiText *text);
 void ui_textarea_remove(UiText *text, int begin, int end);
+void ui_textarea_setreadonly(UiText *text, int readonly);
 
 void ui_textarea_realize_event(GtkWidget *widget, gpointer data);
+//void ui_textbuf_changed(GtkTextBuffer *textbuffer, UiTextArea *textarea);
+void ui_textbuf_change_insert(
+        GtkTextBuffer *textbuffer,
+        GtkTextIter *location,
+        char *text,
+        int length,
+        UiTextArea *textarea);
+void ui_textbuf_change_delete(
+        GtkTextBuffer *self,
+        const GtkTextIter *start,
+        const GtkTextIter *end,
+        UiTextArea *textarea);
+
 void ui_textbuf_changed(GtkTextBuffer *textbuffer, UiTextArea *textarea);
 
 void ui_textbuf_insert(
index 33efbcd274eb1cbf575094b90985dfe84b2e7a13..1f6cc19f680161ab2405220bdef55889236e2514 100644 (file)
@@ -140,13 +140,14 @@ void add_toolitem_widget(GtkToolbar *tb, UiToolbarItem *item, UiObject *obj) {
     
     ui_set_widget_nstates(obj->ctx, GTK_WIDGET(button), item->args.states, item->nstates);
     
-    if(item->args.onclick) {
+    if(item->args.onclick || item->args.action) {
         UiEventData *event = cxMalloc(
                 obj->ctx->allocator,
                 sizeof(UiEventData));
         event->obj = obj;
         event->callback = item->args.onclick;
         event->userdata = item->args.onclickdata;
+        event->action = item->args.action ? ui_strdup(obj->ctx, item->args.action) : NULL;
         event->customdata = NULL;
         event->customint = 0;
         event->value = 0;
@@ -202,6 +203,7 @@ void add_toolitem_toggle_widget(GtkToolbar *tb, UiToolbarToggleItem *item, UiObj
     event->obj = obj;
     event->callback = item->args.onchange;
     event->userdata = item->args.onchangedata;
+    event->action = item->args.action ? ui_strdup(obj->ctx, item->args.action) : NULL;;
     event->var = var;
 
     g_signal_connect(
@@ -239,6 +241,10 @@ void ui_tool_button_toggled(GtkToggleToolButton *widget, UiVarEventData *event)
     if(i) {
         ui_notify_evt(i->observers, &e);
     }
+    
+    if(event->action) {
+        uic_action_callback(&e, event->action);
+    }
 }
 
 int64_t ui_tool_toggle_button_get(UiInteger *integer) {
index 7534c63ec6caea97858e57f237de3dcc37da755b..659e9cbc84474c7b86221359174894e2700fe2d0 100644 (file)
@@ -42,68 +42,6 @@ extern "C" {
 
 #if UI_GTK2 || UI_GTK3
     
-typedef struct UiToolItemI      UiToolItemI;
-typedef struct UiToolItem       UiToolItem;
-typedef struct UiStToolItem     UiStToolItem;
-typedef struct UiToggleToolItem UiToggleToolItem;
-
-typedef struct UiToolbarComboBox   UiToolbarComboBox;
-typedef struct UiToolbarComboBoxNV UiToolbarComboBoxNV;
-
-typedef void(*ui_toolbar_add_f)(GtkToolbar*, UiToolItemI*, UiObject*);
-
-struct UiToolItemI {
-    ui_toolbar_add_f  add_to;
-};
-
-struct UiToolItem {
-    UiToolItemI    item;
-    const char     *label;
-    const char     *image;
-    ui_callback    callback;
-    void           *userdata;
-    const char     *varname;
-    CxList         *groups;
-    int            isimportant;
-};
-
-struct UiStToolItem {
-    UiToolItemI    item;
-    const char     *stockid;
-    ui_callback    callback;
-    void           *userdata;
-    const char     *varname;
-    CxList         *groups;
-    int            isimportant;
-};
-
-struct UiToggleToolItem {
-    UiToolItemI    item;
-    const char     *label;
-    const char     *image;
-    const char     *stockid;
-    UiInteger      *value;
-    const char     *var;
-    CxList         *groups;
-    int            isimportant;
-};
-
-struct UiToolbarComboBox {
-    UiToolItemI         item;
-    UiVar               *var;
-    ui_getvaluefunc getvalue;
-    ui_callback         callback;
-    void                *userdata;
-};
-
-struct UiToolbarComboBoxNV {
-    UiToolItemI         item;
-    char                *listname;
-    ui_getvaluefunc     getvalue;
-    ui_callback         callback;
-    void                *userdata;
-};
-
 
 void ui_toolitem_vstgr(
         char *name,
index 10cba07f253f00e366c6ba1cc94c5b12b9a535de..dbdde0a91164fbdcc36a09352bc3ce1380478a29 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "toolkit.h"
 #include "toolbar.h"
+#include "window.h"
 #include "icon.h"
 #include "../common/document.h"
 #include "../common/properties.h"
@@ -61,8 +62,11 @@ static int scale_factor = 1;
 
 static UiBool        exit_on_shutdown;
 
+// NOOP on most platforms, expect macos
+void ui_set_main_thread_error_msg(const char *msg) {}
+
 UIEXPORT void ui_init(const char *appname, int argc, char **argv) {
-    application_name = appname;
+    application_name = appname ? strdup(appname) : NULL;
     uic_init_global_context();
     
 #if GTK_MAJOR_VERSION >= 4
@@ -76,6 +80,7 @@ UIEXPORT void ui_init(const char *appname, int argc, char **argv) {
     uic_toolbar_init();
     ui_image_init();
     uic_load_app_properties();
+    uic_init_threads();
     
 #if GTK_MAJOR_VERSION >= 4
     scale_factor = 1; // TODO
@@ -133,6 +138,24 @@ void ui_main() {
     }
 }
 
+
+void ui_app_ref(void) {
+#ifdef UI_APPLICATION
+    g_application_hold(G_APPLICATION(app));
+#else
+    // TODO
+#endif
+}
+
+void ui_app_unref(void) {
+#ifdef UI_APPLICATION
+    g_application_release(G_APPLICATION(app));
+#else
+    // TODO
+#endif
+}
+
+
 #ifndef UI_GTK2
 void ui_app_quit() {
     g_application_quit(G_APPLICATION(app)); // TODO: fix, does not work
@@ -144,27 +167,24 @@ GtkApplication* ui_get_application() {
 #endif
 
 void ui_show(UiObject *obj) {
-    gboolean visible = gtk_widget_is_visible(obj->widget);
-    
-    uic_check_state_widgets(obj->ctx);
+    gboolean visible = FALSE;
+    if(obj->widget) {
+        visible = gtk_widget_is_visible(obj->widget);
 #if GTK_MAJOR_VERSION >= 4
-    gtk_window_present(GTK_WINDOW(obj->widget));
+        gtk_window_present(GTK_WINDOW(obj->widget));
 #elif GTK_MAJOR_VERSION <= 3
-    gtk_widget_show_all(obj->widget);
+        gtk_widget_show_all(obj->widget);
 #endif
-    
+    }
+    uic_check_state_widgets(obj->ctx);
+      
     if(!visible) {
         obj->ref++;
     }
 }
 
 void ui_close(UiObject *obj) {
-    uic_context_prepare_close(obj->ctx);
-#if GTK_CHECK_VERSION(4, 0, 0)
-    gtk_window_close(GTK_WINDOW(obj->widget));
-#else
-    gtk_widget_destroy(obj->widget);
-#endif
+    ui_window_close_request(obj);
 }
 
 
@@ -203,6 +223,11 @@ static gboolean ui_idle_func(void *data) {
 }
 
 void ui_call_mainthread(ui_threadfunc tf, void* td) {
+    if(uic_mainthread_calls_is_buffered()) {
+        uic_add_buffered_mainthread_call(tf, td);
+        return;
+    }
+    
     UiJob *job = malloc(sizeof(UiJob));
     job->job_func = tf;
     job->job_data = td;
@@ -234,7 +259,7 @@ void ui_set_show_all(UIWIDGET widget, int value) {
 #endif
 }
 
-void ui_set_visible(UIWIDGET widget, UiBool visible) {
+void ui_set_visible(UIWIDGET widget, int visible) {
 #if GTK_MAJOR_VERSION >= 4
     gtk_widget_set_visible(widget, visible);
 #else
@@ -282,6 +307,11 @@ void ui_destroy_userdata(GtkWidget *object, void *userdata) {
     free(userdata);
 }
 
+void ui_destroy_eventdata(GtkWidget *object, UiEventData *data) {
+    free(data->action);
+    free(data);
+}
+
 void ui_destroy_vardata(GtkWidget *unused, UiVarEventData *data) {
     if(data->var) {
         ui_destroy_boundvar(data->obj->ctx, data->var);
@@ -536,3 +566,16 @@ void ui_set_widget_nvisibility_states(UiContext *ctx, GtkWidget *widget, const i
         ui_set_visible(widget, FALSE);
     }
 }
+
+void ui_open_uri(const char *uri) {
+#if GTK_CHECK_VERSION(4, 0, 0)
+    GtkUriLauncher *launcher = gtk_uri_launcher_new(uri);
+    gtk_uri_launcher_launch(launcher, NULL, NULL, NULL, NULL);
+    g_object_unref(launcher);
+#elif GTK_CHECK_VERSION(3, 22, 0)
+    GError *error = NULL;
+    gtk_show_uri_on_window(NULL, uri, GDK_CURRENT_TIME, &error);
+#elif
+    // TODO: call xdg-open
+#endif
+}
index 0e421b9c996906306e14664b32f5c8ec396634a4..432bebb9dad1e766f0678c86abcbc67f3ec46be7 100644 (file)
@@ -65,6 +65,11 @@ extern "C" {
 #define BOX_REMOVE(box, child) gtk_box_remove(GTK_BOX(box), child)
 #define ENTRY_SET_TEXT(entry, text) gtk_editable_set_text(GTK_EDITABLE(entry), text)
 #define ENTRY_GET_TEXT(entry) gtk_editable_get_text(GTK_EDITABLE(entry))
+#define ENTRY_SET_SELECTION(entry, begin, end) gtk_editable_select_region(GTK_EDITABLE(entry), begin, end) 
+#define ENTRY_SET_EDITABLE(entry, editable) gtk_editable_set_editable(GTK_EDITABLE(entry), editable)
+#define ENTRY_IS_EDITABLE(entry) gtk_editable_get_editable(GTK_EDITABLE(entry))
+#define ENTRY_SET_POSITION(entry, pos) gtk_editable_set_position(GTK_EDITABLE(entry), pos)
+#define ENTRY_GET_POSITION(entry) gtk_editable_get_position(GTK_EDITABLE(entry))
 #define SCROLLEDWINDOW_NEW() gtk_scrolled_window_new()
 #define SCROLLEDWINDOW_SET_CHILD(sw, child) gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(sw), child)
 #define SCROLLEDWINDOW_GET_CHILD(sw) gtk_scrolled_window_get_child(GTK_SCROLLED_WINDOW(sw))
@@ -90,6 +95,11 @@ extern "C" {
 #define BOX_REMOVE(box, child) gtk_container_remove(GTK_CONTAINER(box), child)
 #define ENTRY_SET_TEXT(entry, text) gtk_entry_set_text(GTK_ENTRY(entry), text)
 #define ENTRY_GET_TEXT(entry) gtk_entry_get_text(GTK_ENTRY(entry))
+#define ENTRY_SET_SELECTION(entry, begin, end) gtk_editable_select_region(GTK_EDITABLE(entry), begin, end)
+#define ENTRY_SET_EDITABLE(entry, editable) gtk_editable_set_editable(GTK_EDITABLE(entry), editable)
+#define ENTRY_IS_EDITABLE(entry) gtk_editable_get_editable(GTK_EDITABLE(entry))
+#define ENTRY_SET_POSITION(entry, pos) gtk_editable_set_position(GTK_EDITABLE(entry), pos)
+#define ENTRY_GET_POSITION(entry) gtk_editable_get_position(GTK_EDITABLE(entry))
 #define SCROLLEDWINDOW_NEW() gtk_scrolled_window_new(NULL, NULL)
 #define SCROLLEDWINDOW_SET_CHILD(sw, child) gtk_container_add(GTK_CONTAINER(sw), child)
 #define SCROLLEDWINDOW_GET_CHILD(sw) gtk_bin_get_child(GTK_BIN(sw))
@@ -139,6 +149,7 @@ typedef struct UiEventData {
     int         value;
     int         customint;
     void        *customdata;
+    char        *action;
 } UiEventData;
 
 typedef struct UiEventDataExt {
@@ -162,6 +173,7 @@ typedef struct UiVarEventData {
     UiVar       *var;
     UiObserver  **observers;
     ui_callback callback;
+    char        *action;
     void        *userdata;
     int         customint1;
     int         customint2;
@@ -190,6 +202,7 @@ void ui_set_widget_visibility_states(UiContext *ctx, GtkWidget *widget, const in
 void ui_set_widget_nvisibility_states(UiContext *ctx, GtkWidget *widget, const int *states, size_t ngroups);
 
 void ui_destroy_userdata(GtkWidget *object, void *userdata);
+void ui_destroy_eventdata(GtkWidget *object, UiEventData *data);
 void ui_destroy_vardata(GtkWidget *unused, UiVarEventData *data);
 void ui_destroy_widget_var(GtkWidget *object, UiVar *var);
 void ui_destroy_boundvar(UiContext *ctx, UiVar *var);
index 10463914976923d0a62a3c8d9689a74ffd2d7950..009d432cac07cd802c7be67fa485ef4147ecb470 100644 (file)
@@ -44,6 +44,8 @@
 #include "container.h"
 #include "headerbar.h"
 #include "button.h"
+#include "window.h"
+#include "widget.h"
 
 static int nwindows = 0;
 
@@ -80,7 +82,7 @@ void ui_exit_event(GtkWidget *widget, gpointer data) {
     g_idle_add(ui_window_destroy, data);
 }
 
-static gboolean ui_window_close_request(UiObject *obj) {
+gboolean ui_window_close_request(UiObject *obj) {
     if(obj->widget) {
         void *appwindow = g_object_get_data(G_OBJECT(obj->widget), "ui.appwindow");
         if(appwindow) {
@@ -111,8 +113,12 @@ static gboolean ui_window_close_request(UiObject *obj) {
         }
     }
     
-    uic_context_prepare_close(obj->ctx);
-    obj->ref--;
+    if(obj->ref > 0) {
+        obj->ref--;
+    } else {
+        // warn about invalid reference counting
+        fprintf(stderr, "Error: UiObject %p ref == 0\n", obj);
+    }
     if(obj->ref > 0) {
 #if GTK_CHECK_VERSION(2, 18, 0)
         gtk_widget_set_visible(obj->widget, FALSE);
@@ -121,16 +127,32 @@ static gboolean ui_window_close_request(UiObject *obj) {
 #endif
         return TRUE;
     } else {
+        // this cleans up any widget references from the context
+        uic_context_prepare_close(obj->ctx);
+        ui_window_widget_destroy(obj);
         return FALSE;
     }
 }
 
+static void window_onclose_callback(UiObject *obj) {
+    if(obj->onclose) {
+        UiEvent event;
+        memset(&event, 0, sizeof(UiEvent));
+        event.obj = obj;
+        event.window = obj->window;
+        event.document = obj->ctx->document;
+        obj->onclose(&event, obj->onclosedata);
+    }
+}
+
 #if GTK_MAJOR_VERSION >= 4
 static gboolean close_request(GtkWindow* self, UiObject *obj) {
+    window_onclose_callback(obj);
     return ui_window_close_request(obj);
 }
 #else
 static gboolean close_request(GtkWidget* self, GdkEvent* event, UiObject *obj) {
+    window_onclose_callback(obj);
     return ui_window_close_request(obj);
 }
 #endif
@@ -153,6 +175,25 @@ static UiObject* create_window(const char *title, UiBool sidebar, UiBool splitvi
     obj->widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
 #endif
     
+#if GTK_MAJOR_VERSION < 4
+    const char *window_pos = ui_get_property("ui.gtk.window.position");
+    GtkWindowPosition wpos = GTK_WIN_POS_CENTER;
+    if(window_pos) {
+        if(!strcmp(window_pos, "none")) {
+            wpos = GTK_WIN_POS_NONE;
+        } else if(!strcmp(window_pos, "center")) {
+            //wpos = GTK_WIN_POS_CENTER;
+        } else if(!strcmp(window_pos, "mouse")) {
+            wpos = GTK_WIN_POS_MOUSE;
+        } else if(!strcmp(window_pos, "center_always")) {
+            wpos = GTK_WIN_POS_CENTER_ALWAYS;
+        } else {
+            fprintf(stderr, "Error: unknown value '%s' for property ui.gtk.window.positionhint", window_pos);
+        }
+    }
+    gtk_window_set_position(GTK_WINDOW(obj->widget), wpos);
+#endif
+    
 #if GTK_CHECK_VERSION(4, 0, 0)
     obj->ctx->action_map = G_ACTION_MAP(obj->widget);
 #endif
@@ -246,6 +287,8 @@ static UiObject* create_window(const char *title, UiBool sidebar, UiBool splitvi
         g_object_set_data(G_OBJECT(obj->widget), "ui_window_splitview", content);
         g_object_set_data(G_OBJECT(obj->widget), "ui_left_panel", vbox);
         g_object_set_data(G_OBJECT(obj->widget), "ui_right_panel", right_vbox);
+        g_object_set_data(G_OBJECT(obj->widget), "ui_left_panel_top", toolbar_view);
+        g_object_set_data(G_OBJECT(obj->widget), "ui_right_panel_top", right_panel);
     }
     
     GtkWidget *content_box = vbox;
@@ -273,17 +316,23 @@ static UiObject* create_window(const char *title, UiBool sidebar, UiBool splitvi
             adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
         } else if(!strcmp(show_title, "sidebar")) {
             adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_main), FALSE);
-            adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), TRUE);
+            if(headerbar_sidebar) {
+                adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), TRUE);
+            }
         } else if(!strcmp(show_title, "false")) {
-            adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
+            if(headerbar_sidebar) {
+                adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
+            }
             adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_main), FALSE);
         } else {
             fprintf(stderr, "Unknown value '%s' for property ui.gtk.window.showtitle\n", show_title);
-            adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
+            if(headerbar_sidebar) {
+                adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
+            }
         }
     } else {
         adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_main), FALSE);
-        if(sidebar) {
+        if(headerbar_sidebar) {
             adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), TRUE);
         }
     }
@@ -342,6 +391,8 @@ static UiObject* create_window(const char *title, UiBool sidebar, UiBool splitvi
             g_object_set_data(G_OBJECT(obj->widget), "ui_window_splitview", content_paned);
             g_object_set_data(G_OBJECT(obj->widget), "ui_left_panel", content_box);
             g_object_set_data(G_OBJECT(obj->widget), "ui_right_panel", right_content_box);
+            g_object_set_data(G_OBJECT(obj->widget), "ui_left_panel_top", content_box);
+            g_object_set_data(G_OBJECT(obj->widget), "ui_right_panel_top", right_content_box);
         } else {
             PANED_SET_CHILD2(paned, content_box);
         }
@@ -366,7 +417,7 @@ static UiObject* create_window(const char *title, UiBool sidebar, UiBool splitvi
     gtk_container_add(GTK_CONTAINER(frame), content_box);
     obj->container = ui_box_container(obj, content_box);
     */
-    UiContainerX *container = ui_box_container(obj, content_box, UI_CONTAINER_VBOX);
+    UiContainer *container = ui_box_container(obj, content_box, UI_CONTAINER_VBOX);
     uic_object_push_container(obj, container);
     
     nwindows++;
@@ -431,10 +482,13 @@ void ui_splitview_window_use_property(UiBool enable) {
 
 UIEXPORT void ui_splitview_window_set_visible(UiObject *obj, int pane, UiBool visible) {
     GtkWidget *panel = NULL;
+    CxList *backup_items = NULL;
     if(pane == 0) {
-        panel = g_object_get_data(G_OBJECT(obj->widget), "ui_left_panel");
+        panel = g_object_get_data(G_OBJECT(obj->widget), "ui_left_panel_top");
+        backup_items = g_object_get_data(G_OBJECT(obj->widget), "ui_toolbar_center_backup");
     } else if(pane == 1) {
-        panel = g_object_get_data(G_OBJECT(obj->widget), "ui_right_panel");
+        panel = g_object_get_data(G_OBJECT(obj->widget), "ui_right_panel_top");
+        // TODO: backup toolbar items
     }
     
     if(panel == NULL) {
@@ -443,6 +497,13 @@ UIEXPORT void ui_splitview_window_set_visible(UiObject *obj, int pane, UiBool vi
     }
     
     gtk_widget_set_visible(panel, visible);
+    
+    if(backup_items) {
+        CxIterator i = cxListIterator(backup_items);
+        cx_foreach(GtkWidget*, w, i) {
+            ui_set_visible(w, !visible);
+        }
+    }
 }
 
 #ifdef UI_LIBADWAITA
@@ -471,6 +532,8 @@ static void dialog_response(AdwAlertDialog *self, gchar *response, UiEventData *
     if(data->callback) {
         data->callback(&evt, data->userdata);
     }
+    
+    ui_app_unref();
 }
 
 void ui_dialog_create(UiObject *parent, UiDialogArgs *args) {
@@ -515,7 +578,8 @@ void ui_dialog_create(UiObject *parent, UiDialogArgs *args) {
                 event);
     
     g_signal_connect(dialog, "response", G_CALLBACK(dialog_response), event);
-    adw_dialog_present(dialog, parent->widget);
+    ui_app_ref();
+    adw_dialog_present(dialog, parent ? parent->widget : NULL);
     
     if(entry) {
         gtk_entry_grab_focus_without_selecting(GTK_ENTRY(entry));
@@ -527,8 +591,14 @@ static void ui_dialog_response (GtkDialog* self, gint response_id, gpointer user
     UiEventData *data = user_data;
     UiEvent evt;
     evt.obj = data->obj;
-    evt.document = evt.obj->ctx->document;
-    evt.window = evt.obj->window;
+    if(evt.obj) {
+        evt.document = evt.obj->ctx->document;
+        evt.window = evt.obj->window;
+    } else {
+        evt.document = NULL;
+        evt.window = NULL;
+    }
+    
     evt.eventdata = NULL;
     evt.intval = 0;
     
@@ -943,7 +1013,7 @@ UiObject* ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
 #endif
     
     GtkWidget *content_vbox = ui_gtk_vbox_new(0);
-    UiContainerX *container = ui_box_container(obj, content_vbox, UI_CONTAINER_VBOX);
+    UiContainer *container = ui_box_container(obj, content_vbox, UI_CONTAINER_VBOX);
     uic_object_push_container(obj, container);
     if(args->lbutton1 || args->lbutton2 || args->rbutton3 || args->rbutton4) {
 #if GTK_CHECK_VERSION(3, 10, 0)
@@ -955,7 +1025,7 @@ UiObject* ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
             }
             
             if(args->lbutton1) {
-                GtkWidget *button = ui_create_button(obj, args->lbutton1, NULL, NULL/*tooltip*/, args->onclick, args->onclickdata, 1, args->default_button == 1);
+                GtkWidget *button = ui_create_button(obj, args->lbutton1, NULL, NULL/*tooltip*/, args->onclick, args->onclickdata, NULL, 1, args->default_button == 1);
                 gtk_header_bar_pack_start(GTK_HEADER_BAR(headerbar), button);
                 if(args->default_button == 1) {
                     WIDGET_ADD_CSS_CLASS(button, "suggested-action");
@@ -963,7 +1033,7 @@ UiObject* ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
                 }
             }
             if(args->lbutton2) {
-                GtkWidget *button = ui_create_button(obj, args->lbutton2, NULL, NULL/*tooltip*/, args->onclick, args->onclickdata, 2, args->default_button == 2);
+                GtkWidget *button = ui_create_button(obj, args->lbutton2, NULL, NULL/*tooltip*/, args->onclick, args->onclickdata, NULL, 2, args->default_button == 2);
                 gtk_header_bar_pack_start(GTK_HEADER_BAR(headerbar), button);
                 if(args->default_button == 2) {
                     WIDGET_ADD_CSS_CLASS(button, "suggested-action");
@@ -972,7 +1042,7 @@ UiObject* ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
             }
             
             if(args->rbutton4) {
-                GtkWidget *button = ui_create_button(obj, args->rbutton4, NULL, NULL/*tooltip*/, args->onclick, args->onclickdata, 4, args->default_button == 4);
+                GtkWidget *button = ui_create_button(obj, args->rbutton4, NULL, NULL/*tooltip*/, args->onclick, args->onclickdata, NULL, 4, args->default_button == 4);
                 gtk_header_bar_pack_end(GTK_HEADER_BAR(headerbar), button);
                 if(args->default_button == 4) {
                     WIDGET_ADD_CSS_CLASS(button, "suggested-action");
@@ -980,7 +1050,7 @@ UiObject* ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
                 }
             }
             if(args->rbutton3) {
-                GtkWidget *button = ui_create_button(obj, args->rbutton3, NULL, NULL/*tooltip*/, args->onclick, args->onclickdata, 3, args->default_button == 3);
+                GtkWidget *button = ui_create_button(obj, args->rbutton3, NULL, NULL/*tooltip*/, args->onclick, args->onclickdata, NULL, 3, args->default_button == 3);
                 gtk_header_bar_pack_end(GTK_HEADER_BAR(headerbar), button);
                 if(args->default_button == 3) {
                     WIDGET_ADD_CSS_CLASS(button, "suggested-action");
@@ -1001,7 +1071,7 @@ UiObject* ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
         gtk_grid_set_column_homogeneous(GTK_GRID(grid), TRUE); 
         
         if(args->lbutton1) {
-            GtkWidget *button = ui_create_button(obj, args->lbutton1, NULL, NULL/*tooltip*/, args->onclick, args->onclickdata, 1, args->default_button == 1);
+            GtkWidget *button = ui_create_button(obj, args->lbutton1, NULL, NULL/*tooltip*/, args->onclick, args->onclickdata, NULL, 1, args->default_button == 1);
             gtk_grid_attach(GTK_GRID(grid), button, 0, 0, 1, 1);
             if(args->default_button == 1) {
                 WIDGET_ADD_CSS_CLASS(button, "suggested-action");
@@ -1009,7 +1079,7 @@ UiObject* ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
             }
         }
         if(args->lbutton2) {
-            GtkWidget *button = ui_create_button(obj, args->lbutton2, NULL, NULL/*tooltip*/, args->onclick, args->onclickdata, 2, args->default_button == 2);
+            GtkWidget *button = ui_create_button(obj, args->lbutton2, NULL, NULL/*tooltip*/, args->onclick, args->onclickdata, NULL, 2, args->default_button == 2);
             gtk_grid_attach(GTK_GRID(grid), button, 1, 0, 1, 1);
             if(args->default_button == 2) {
                 WIDGET_ADD_CSS_CLASS(button, "suggested-action");
@@ -1020,7 +1090,7 @@ UiObject* ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
         gtk_widget_set_hexpand(space, TRUE);
         gtk_grid_attach(GTK_GRID(grid), space, 2, 0, 1, 1);
         if(args->rbutton3) {
-            GtkWidget *button = ui_create_button(obj, args->rbutton3, NULL, NULL/*tooltip*/, args->onclick, args->onclickdata, 3, args->default_button == 3);
+            GtkWidget *button = ui_create_button(obj, args->rbutton3, NULL, NULL/*tooltip*/, args->onclick, args->onclickdata, NULL, 3, args->default_button == 3);
             gtk_grid_attach(GTK_GRID(grid), button, 3, 0, 1, 1);
             if(args->default_button == 3) {
                 WIDGET_ADD_CSS_CLASS(button, "suggested-action");
@@ -1028,7 +1098,7 @@ UiObject* ui_dialog_window_create(UiObject *parent, UiDialogWindowArgs *args) {
             }
         }
         if(args->rbutton4) {
-            GtkWidget *button = ui_create_button(obj, args->rbutton4, NULL, NULL/*tooltip*/, args->onclick, args->onclickdata, 4, args->default_button == 4);
+            GtkWidget *button = ui_create_button(obj, args->rbutton4, NULL, NULL/*tooltip*/, args->onclick, args->onclickdata, NULL, 4, args->default_button == 4);
             gtk_grid_attach(GTK_GRID(grid), button, 4, 0, 1, 1);
             if(args->default_button == 4) {
                 WIDGET_ADD_CSS_CLASS(button, "suggested-action");
diff --git a/ui/gtk/window.h b/ui/gtk/window.h
new file mode 100644 (file)
index 0000000..1b85fd9
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2026 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#ifndef WINDOW_H
+#define WINDOW_H
+
+#include "toolkit.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+gboolean ui_window_close_request(UiObject *obj);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* WINDOW_H */
+
index da74124f14b673ffbbecb3f1366250100ee99048..23cf424994700c4d4c9f0e9b24488157dce3733f 100644 (file)
@@ -281,11 +281,11 @@ GridClassRec gridClassRec = {
         NULL,                         // set_values_hook
         XtInheritSetValuesAlmost,     // set_values_almost
         NULL,                         // get_values_hook
-        (XtAcceptFocusProc)grid_acceptfocus,       // accept_focus
+        (XtAcceptFocusProc)NULL,       // accept_focus
         XtVersion,                    // version
         NULL,                         // callback_offsets
         //NULL,                         // tm_table
-                defaultTranslations,
+        XtInheritTranslations, //defaultTranslations,
         XtInheritQueryGeometry,       // query_geometry
         NULL,                         // display_accelerator
         NULL,                         // extension
@@ -342,7 +342,7 @@ void grid_initialize(Widget request, Widget new, ArgList args, Cardinal num_args
 void grid_realize(Widget w,XtValueMask *valueMask,XSetWindowAttributes *attributes) {
     Grid grid = (Grid)w;
     XtMakeResizeRequest(w, 400, 400, NULL, NULL);
-    (coreClassRec.core_class.realize)((Widget)w, valueMask, attributes); 
+    (*xmManagerClassRec.core_class.realize)(w, valueMask, attributes);
     grid_place_children(grid);
 }
 
@@ -363,9 +363,6 @@ Boolean grid_set_values(Widget old, Widget request, Widget neww, ArgList args, C
     return False;
 }
 
-Boolean grid_acceptfocus(Widget w, Time *t) {
-    
-}
 
 void grid_getfocus(Widget myw, XEvent *event, String *params, Cardinal *nparam) {
     
index 7f7b420c3a41e14b1eaa972e1296b6ee7052370b..03add25107978643376a29112249b1d0817c3ca1 100644 (file)
 # POSSIBILITY OF SUCH DAMAGE.
 #
 
-$(MOTIF_OBJPRE)%.o: motif/%.c
-       $(CC) -o $@ -c -I../ucx $(CFLAGS) $(SHLIB_CFLAGS) $(TK_CFLAGS) $<
-
 $(UI_LIB): $(OBJ)
        $(AR) $(ARFLAGS) $(UI_LIB) $(OBJ)       
 
 $(UI_SHLIB): $(OBJ)
        $(CC) -o $(UI_SHLIB) $(LDFLAGS) $(SHLIB_LDFLAGS) $(TK_LDFLAGS) $(OBJ) -L../build/lib -lucx
+
+FORCE:
+
+$(MOTIF_OBJPRE)button.o: motif/button.c motif/button.h \
+ motif/../ui/button.h motif/../ui/toolkit.h motif/toolkit.h \
+ motif/../ui/toolkit.h motif/../common/context.h \
+ motif/../common/../ui/toolkit.h motif/../common/action.h \
+ motif/../common/object.h motif/container.h motif/../ui/container.h \
+ motif/../common/action.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)container.o: motif/container.c motif/container.h \
+ motif/../ui/toolkit.h motif/../ui/container.h motif/../ui/toolkit.h \
+ motif/../common/context.h motif/../common/../ui/toolkit.h \
+ motif/../common/action.h motif/../common/object.h \
+ motif/../common/container.h motif/../common/../ui/container.h \
+ motif/Grid.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)dnd.o: motif/dnd.c motif/dnd.h motif/../ui/dnd.h \
+ motif/../ui/toolkit.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)entry.o: motif/entry.c motif/entry.h motif/../ui/entry.h \
+ motif/../ui/toolkit.h motif/container.h motif/../ui/toolkit.h \
+ motif/../ui/container.h motif/toolkit.h motif/../common/context.h \
+ motif/../common/../ui/toolkit.h motif/../common/action.h \
+ motif/../common/object.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)Fsb.o: motif/Fsb.c motif/Fsb.h motif/FsbP.h \
+ motif/pathbar.h motif/../ui/text.h motif/../ui/toolkit.h \
+ motif/../common/utils.h motif/../common/../ui/toolkit.h \
+ motif/../common/../ui/text.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)graphics.o: motif/graphics.c motif/graphics.h \
+ motif/../ui/graphics.h motif/../ui/toolkit.h motif/toolkit.h \
+ motif/../ui/toolkit.h motif/../common/context.h \
+ motif/../common/../ui/toolkit.h motif/../common/action.h \
+ motif/../common/object.h motif/container.h motif/../ui/container.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)Grid.o: motif/Grid.c motif/Grid.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)image.o: motif/image.c motif/image.h motif/../ui/image.h \
+ motif/../ui/toolkit.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)label.o: motif/label.c motif/label.h motif/../ui/display.h \
+ motif/../ui/toolkit.h motif/../common/context.h \
+ motif/../common/../ui/toolkit.h motif/../common/action.h \
+ motif/container.h motif/../ui/toolkit.h motif/../ui/container.h \
+ motif/../common/object.h motif/Grid.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)list.o: motif/list.c motif/container.h \
+ motif/../ui/toolkit.h motif/../ui/container.h motif/../ui/toolkit.h \
+ motif/list.h motif/toolkit.h motif/../common/context.h \
+ motif/../common/../ui/toolkit.h motif/../common/action.h \
+ motif/../common/object.h motif/../ui/list.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)menu.o: motif/menu.c motif/menu.h motif/../ui/menu.h \
+ motif/../ui/toolkit.h motif/../common/menu.h \
+ motif/../common/../ui/menu.h motif/../common/context.h \
+ motif/../common/../ui/toolkit.h motif/../common/action.h motif/button.h \
+ motif/../ui/button.h motif/toolkit.h motif/../ui/toolkit.h \
+ motif/../common/object.h motif/container.h motif/../ui/container.h \
+ motif/../common/types.h motif/../ui/window.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)pathbar.o: motif/pathbar.c motif/pathbar.h \
+ motif/../ui/text.h motif/../ui/toolkit.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)range.o: motif/range.c motif/range.h motif/toolkit.h \
+ motif/../ui/toolkit.h motif/../common/context.h \
+ motif/../common/../ui/toolkit.h motif/../common/action.h \
+ motif/../common/object.h motif/../ui/range.h motif/../ui/toolkit.h \
+ motif/container.h motif/../ui/container.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)text.o: motif/text.c motif/text.h motif/../ui/text.h \
+ motif/../ui/toolkit.h motif/toolkit.h motif/../ui/toolkit.h \
+ motif/../common/context.h motif/../common/../ui/toolkit.h \
+ motif/../common/action.h motif/../common/object.h motif/container.h \
+ motif/../ui/container.h motif/pathbar.h motif/../common/utils.h \
+ motif/../common/../ui/text.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)toolbar.o: motif/toolbar.c motif/toolbar.h \
+ motif/../ui/toolbar.h motif/../ui/toolkit.h motif/button.h \
+ motif/../ui/button.h motif/toolkit.h motif/../ui/toolkit.h \
+ motif/../common/context.h motif/../common/../ui/toolkit.h \
+ motif/../common/action.h motif/../common/object.h motif/list.h \
+ motif/../ui/list.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)toolkit.o: motif/toolkit.c motif/toolkit.h \
+ motif/../ui/toolkit.h motif/../common/context.h \
+ motif/../common/../ui/toolkit.h motif/../common/action.h \
+ motif/../common/object.h motif/toolbar.h motif/../ui/toolbar.h \
+ motif/../ui/toolkit.h motif/container.h motif/../ui/container.h \
+ motif/../common/menu.h motif/../common/../ui/menu.h \
+ motif/../common/../ui/toolkit.h motif/../common/toolbar.h \
+ motif/../common/../ui/toolbar.h motif/../common/menu.h \
+ motif/../common/document.h motif/../common/context.h \
+ motif/../common/properties.h motif/../common/../ui/properties.h \
+ motif/../common/app.h motif/../common/threadpool.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)widget.o: motif/widget.c motif/../ui/widget.h \
+ motif/../ui/toolkit.h motif/container.h motif/../ui/toolkit.h \
+ motif/../ui/container.h motif/../common/context.h \
+ motif/../common/../ui/toolkit.h motif/../common/action.h \
+ motif/../common/object.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
+$(MOTIF_OBJPRE)window.o: motif/window.c motif/window.h \
+ motif/../ui/window.h motif/../ui/toolkit.h motif/../ui/widget.h \
+ motif/toolkit.h motif/../ui/toolkit.h motif/../common/context.h \
+ motif/../common/../ui/toolkit.h motif/../common/action.h \
+ motif/../common/object.h motif/menu.h motif/../ui/menu.h \
+ motif/../common/menu.h motif/../common/../ui/menu.h motif/toolbar.h \
+ motif/../ui/toolbar.h motif/container.h motif/../ui/container.h \
+ motif/pathbar.h motif/../ui/text.h motif/../common/utils.h \
+ motif/../common/../ui/text.h motif/Grid.h motif/Fsb.h
+       $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $<
+
index 45e7a1be1ab25c8b6d5db48bf358acdf10a3422b..8578a630ee92393ffb682f8a0d981409d5ed5c98 100644 (file)
@@ -32,6 +32,7 @@
 #include "button.h"
 #include "container.h"
 #include "../common/context.h"
+#include "../common/action.h"
 #include <cx/mempool.h>
 
 #include <cx/linked_list.h>
@@ -60,6 +61,7 @@ UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs *args) {
     Widget button = XmCreatePushButton(parent, name, xargs, n);
     XtManageChild(button);
     ui_container_add(ctn, button);
+    uic_widget_set_visibility_states(obj->ctx, button, args->visibility_states);
     
     ui_set_widget_groups(obj->ctx, button, args->states);
     
@@ -69,6 +71,7 @@ UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs *args) {
         eventdata->userdata = args->onclickdata;
         eventdata->obj = obj;
         eventdata->value = 0;
+        eventdata->action = args->action ? strdup(args->action) : NULL;
         XtAddCallback(
                 button,
                 XmNactivateCallback,
@@ -77,7 +80,7 @@ UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs *args) {
        XtAddCallback(
                 button,
                 XmNdestroyCallback,
-                (XtCallbackProc)ui_destroy_data,
+                (XtCallbackProc)ui_destroy_event_data,
                 eventdata);
     }
     
@@ -94,6 +97,10 @@ void ui_push_button_callback(Widget widget, UiEventData *event, XtPointer d) {
     e.intval = event->value;
     e.set = 0;
     event->callback(&e, event->userdata);
+    
+    if(event->action) {
+        uic_action_callback(&e, event->action);
+    }
 }
 
 UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs *args) {
@@ -117,10 +124,11 @@ UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs *args) {
     Widget button = XmCreateToggleButton(parent, name, xargs, n);
     XtManageChild(button);
     ui_container_add(ctn, button);
+    uic_widget_set_visibility_states(obj->ctx, button, args->visibility_states);
     
     ui_set_widget_groups(obj->ctx, button, args->states);
     
-    ui_bind_togglebutton(obj, button, args->varname, args->value, args->onchange, args->onchangedata, args->enable_state);
+    ui_bind_togglebutton(obj, button, args->varname, args->value, args->onchange, args->onchangedata, args->action, args->enable_state);
     
     XmStringFree(label);
     return button;
@@ -145,10 +153,11 @@ UIWIDGET ui_checkbox_create(UiObject* obj, UiToggleArgs *args) {
     Widget button = XmCreateToggleButton(parent, name, xargs, n);
     XtManageChild(button);
     ui_container_add(ctn, button);
+    uic_widget_set_visibility_states(obj->ctx, button, args->visibility_states);
     
     ui_set_widget_groups(obj->ctx, button, args->states);
     
-    ui_bind_togglebutton(obj, button, args->varname, args->value, args->onchange, args->onchangedata, args->enable_state);
+    ui_bind_togglebutton(obj, button, args->varname, args->value, args->onchange, args->onchangedata, args->action, args->enable_state);
     
     XmStringFree(label);
     return button;
@@ -181,6 +190,10 @@ static void togglebutton_changed(Widget w, UiVarEventData *event, XmToggleButton
         event->callback(&e, event->userdata);
     }
     
+    if(event->action) {
+        uic_action_callback(&e, event->action);
+    }
+    
     if(event->var && event->var->value) {
         UiInteger *v = event->var->value;
         v->value = e.intval;
@@ -195,6 +208,7 @@ void ui_bind_togglebutton(
         UiInteger *value,
         ui_callback onchange,
         void *onchangedata,
+        const char *action,
         int enable_state)
 {
     UiVar* var = uic_widget_var(obj->ctx, obj->ctx, value, varname, UI_VAR_INTEGER);
@@ -213,6 +227,7 @@ void ui_bind_togglebutton(
     event->obj = obj;
     event->callback = onchange;
     event->userdata = onchangedata;
+    event->action = action ? strdup(action) : NULL;
     event->var = var;
     event->observers = NULL;
     event->value = enable_state;
@@ -224,7 +239,7 @@ void ui_bind_togglebutton(
     XtAddCallback(
             widget,
             XmNdestroyCallback,
-            (XtCallbackProc)ui_destroy_data,
+            (XtCallbackProc)ui_destroy_var_event_data,
             event);
 }
 
@@ -291,12 +306,16 @@ static void radiobutton_changed(Widget w, UiVarEventData *event, XmToggleButtonC
         event->callback(&e, event->userdata);
     }
     
+    if(event->action) {
+        uic_action_callback(&e, event->action);
+    }
+    
     if(value) {
         ui_notify_evt(value->observers, &e);
     }
 }
 
-void ui_bind_radiobutton(UiObject *obj, Widget rbutton, UiInteger *value, const char *varname, ui_callback onchange, void *onchangedata, int enable_group) {
+void ui_bind_radiobutton(UiObject *obj, Widget rbutton, UiInteger *value, const char *varname, ui_callback onchange, void *onchangedata, const char *action, int enable_group) {
     UiVar* var = uic_widget_var(obj->ctx, obj->ctx, value, varname, UI_VAR_INTEGER);
     if(var) {
         UiInteger *value = var->value;
@@ -330,6 +349,7 @@ void ui_bind_radiobutton(UiObject *obj, Widget rbutton, UiInteger *value, const
     event->obj = obj;
     event->callback = onchange;
     event->userdata = onchangedata;
+    event->action = action ? strdup(action) : NULL;
     event->observers = NULL;
     event->var = var;
     event->value = enable_group;
@@ -364,6 +384,7 @@ UIWIDGET ui_radiobutton_create(UiObject* obj, UiToggleArgs *args) {
     Widget button = XmCreateToggleButton(parent, name, xargs, n);
     XtManageChild(button);
     ui_container_add(ctn, button);
+    uic_widget_set_visibility_states(obj->ctx, button, args->visibility_states);
     
     ui_set_widget_groups(obj->ctx, button, args->states);
     
@@ -400,6 +421,7 @@ UIWIDGET ui_radiobutton_create(UiObject* obj, UiToggleArgs *args) {
     event->obj = obj;
     event->callback = args->onchange;
     event->userdata = args->onchangedata;
+    event->action = args->action ? strdup(args->action) : NULL;
     event->observers = NULL;
     event->var = var;
     event->value = args->enable_state;
index b6dd711a47fb26c6b950a2b8e0c0a168e7c813a7..35800910b90fdaf0a35542beb28abbdb10e0c208 100644 (file)
@@ -45,12 +45,13 @@ void ui_bind_togglebutton(
         UiInteger *value,
         ui_callback onchange,
         void *onchangedata,
+        const char *action,
         int enable_state);
 
 int64_t ui_togglebutton_get(UiInteger *i);
 void ui_togglebutton_set(UiInteger *i, int64_t value);
 
-void ui_bind_radiobutton(UiObject *obj, Widget rbutton, UiInteger *value, const char *varname, ui_callback onchange, void *onchangedata, int enable_group);
+void ui_bind_radiobutton(UiObject *obj, Widget rbutton, UiInteger *value, const char *varname, ui_callback onchange, void *onchangedata, const char *action, int enable_group);
 
 int64_t ui_radiobutton_get(UiInteger *i);
 void ui_radiobutton_set(UiInteger *i, int64_t value);
index c5c7c4df8f760b24c043234c60ad72400a861d24..d99581adb857ef391dfaebf91106ea74c0d327d2 100644 (file)
@@ -87,9 +87,11 @@ static UIWIDGET box_create(UiObject *obj, UiContainerArgs *args, UiBoxOrientatio
     Widget grid = XtCreateManagedWidget(args->name ? args->name : "boxcontainer", gridClass, parent, xargs, n);
     ctn->add(ctn, grid);
     
-    UiContainerX *container = ui_box_container(obj, grid, orientation);
+    UiContainer *container = ui_box_container(obj, grid, orientation);
     uic_object_push_container(obj, container);
     
+    uic_widget_set_visibility_states(obj->ctx, grid, args->visibility_states);
+    
     return grid;
 }
 
@@ -103,14 +105,14 @@ UIWIDGET ui_hbox_create(UiObject *obj, UiContainerArgs *args) {
     return box_create(obj, args, UI_BOX_HORIZONTAL);
 }
 
-UiContainerX* ui_box_container(UiObject *obj, Widget grid, UiBoxOrientation orientation) {
+UiContainer* ui_box_container(UiObject *obj, Widget grid, UiBoxOrientation orientation) {
     UiBoxContainer *ctn = ui_malloc(obj->ctx, sizeof(UiBoxContainer));
     memset(ctn, 0, sizeof(UiBoxContainer));
     ctn->container.prepare = orientation == UI_BOX_VERTICAL ? ui_vbox_prepare : ui_hbox_prepare;
     ctn->container.add = ui_box_container_add;
     ctn->container.widget = grid;
     ctn->n = 0;
-    return (UiContainerX*)ctn;
+    return (UiContainer*)ctn;
 }
 
 static Widget ui_box_container_prepare(UiBoxContainer *box, UiLayout *layout, Arg *args, int *n) {
@@ -168,13 +170,15 @@ UIWIDGET ui_grid_create(UiObject *obj, UiContainerArgs *args) {
     Widget grid = XtCreateManagedWidget(args->name ? args->name : "gridcontainer", gridClass, parent, xargs, n);
     ui_container_add(ctn, grid);
     
-    UiContainerX *container = ui_grid_container(obj, grid, args->def_hexpand, args->def_vexpand, args->def_hfill, args->def_vfill);
+    UiContainer *container = ui_grid_container(obj, grid, args->def_hexpand, args->def_vexpand, args->def_hfill, args->def_vfill);
     uic_object_push_container(obj, container);
     
+    uic_widget_set_visibility_states(obj->ctx, grid, args->visibility_states);
+    
     return grid;
 }
 
-UiContainerX* ui_grid_container(
+UiContainer* ui_grid_container(
         UiObject *obj,
         Widget grid,
         UiBool def_hexpand,
@@ -193,7 +197,7 @@ UiContainerX* ui_grid_container(
     ctn->def_vexpand = def_vexpand;
     ctn->def_hfill = def_hfill;
     ctn->def_vfill = def_vfill;
-    return (UiContainerX*)ctn;
+    return (UiContainer*)ctn;
 }
 
 Widget ui_grid_container_prepare(UiContainerPrivate *ctn, UiLayout *layout, Arg *args, int *n) {
@@ -271,7 +275,7 @@ UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args) {
         XmStringFree(s);
     }
     
-    UiContainerX *container = ui_frame_container(obj, frame);
+    UiContainer *container = ui_frame_container(obj, frame);
     uic_object_push_container(obj, container);
     
     UiContainerArgs sub_args = {
@@ -299,17 +303,18 @@ UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args) {
         }
     }
     
+    uic_widget_set_visibility_states(obj->ctx, frame, args->visibility_states);
     
     return frame;
 }
 
-UiContainerX* ui_frame_container(UiObject *obj, Widget frame) {
+UiContainer* ui_frame_container(UiObject *obj, Widget frame) {
     UiContainerPrivate *ctn = ui_malloc(obj->ctx, sizeof(UiContainerPrivate));
     memset(ctn, 0, sizeof(UiContainerPrivate));
     ctn->prepare = ui_frame_container_prepare;
     ctn->add = ui_frame_container_add;
     ctn->widget = frame;
-    return (UiContainerX*)ctn;
+    return (UiContainer*)ctn;
 }
 
 Widget ui_frame_container_prepare(UiContainerPrivate *ctn, UiLayout *layout, Arg *args, int *n) {
@@ -467,7 +472,9 @@ UIWIDGET ui_tabview_create(UiObject *obj, UiTabViewArgs *args) {
         i->set = ui_tabview_set;
     }
     
-    uic_object_push_container(obj, (UiContainerX*)ct);
+    uic_object_push_container(obj, (UiContainer*)ct);
+    
+    uic_widget_set_visibility_states(obj->ctx, form, args->visibility_states);
     
     return form;
 }
@@ -549,7 +556,7 @@ UiObject* ui_tabview_add(UIWIDGET tabview, const char *name, int tab_index) {
         UiObject *newobj = ui_calloc(tabviewdata->obj->ctx, 1, sizeof(UiObject));
         newobj->ctx = tabviewdata->obj->ctx;
         newobj->widget = grid;
-        UiContainerX *container = ui_box_container(newobj, grid, UI_BOX_VERTICAL);
+        UiContainer *container = ui_box_container(newobj, grid, UI_BOX_VERTICAL);
         newobj->container_begin = container;
         newobj->container_end = container;
         return newobj;
@@ -686,13 +693,13 @@ void ui_scrolledwindow_add(UiContainerPrivate *ctn, Widget widget) {
     
 }
 
-static UiContainerX* ui_scrolledwindow_container(UiObject *obj, Widget scrolledwindow) {
+static UiContainer* ui_scrolledwindow_container(UiObject *obj, Widget scrolledwindow) {
     UiContainerPrivate *ctn = ui_malloc(obj->ctx, sizeof(UiContainerPrivate));
     memset(ctn, 0, sizeof(UiContainerPrivate));
     ctn->prepare = ui_scrolledwindow_prepare;
     ctn->add = ui_scrolledwindow_add;
     ctn->widget = scrolledwindow;
-    return (UiContainerX*)ctn;
+    return (UiContainer*)ctn;
 }
 
 UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs *args) {
@@ -714,7 +721,7 @@ UIWIDGET ui_scrolledwindow_create(UiObject* obj, UiFrameArgs *args) {
     Widget scrolledwindow = XmCreateScrolledWindow(parent, "scrolledwindow", xargs, n);
     ui_container_add(ctn, scrolledwindow);
     
-    UiContainerX *container = ui_scrolledwindow_container(obj, scrolledwindow);
+    UiContainer *container = ui_scrolledwindow_container(obj, scrolledwindow);
     uic_object_push_container(obj, container);
     
     return scrolledwindow;
index 30262e5dee5c23298d62411a39d71f748fef4b9d..afd2c034033ed49890a05167ca90ea7bf12b6802 100644 (file)
@@ -72,7 +72,7 @@ typedef struct UiContainerPrivate UiContainerPrivate;
 
 
 struct UiContainerPrivate {
-    UiContainerX    container;
+    UiContainer    container;
     Widget          (*prepare)(UiContainerPrivate*, UiLayout *layout, Arg *, int*);
     void            (*add)(UiContainerPrivate*, Widget);
     Widget          widget;
@@ -144,13 +144,13 @@ void ui_tabview_set(UiInteger *i, int64_t value);
 Widget ui_tabview_container_prepare(UiContainerPrivate *ctn, UiLayout *layout, Arg *args, int *n);
 void ui_tabview_container_add(UiContainerPrivate *ctn, Widget widget);
 
-UiContainerX* ui_box_container(UiObject *obj, Widget grid, UiBoxOrientation orientation);
+UiContainer* ui_box_container(UiObject *obj, Widget grid, UiBoxOrientation orientation);
 Widget ui_vbox_prepare(UiContainerPrivate *ctn, UiLayout *layout, Arg *args, int *n);
 Widget ui_hbox_prepare(UiContainerPrivate *ctn, UiLayout *layout, Arg *args, int *n);
 void ui_box_container_add(UiContainerPrivate *ctn, Widget widget);
 
 
-UiContainerX* ui_grid_container(
+UiContainer* ui_grid_container(
         UiObject *obj,
         Widget grid,
         UiBool def_hexpand,
@@ -160,7 +160,7 @@ UiContainerX* ui_grid_container(
 Widget ui_grid_container_prepare(UiContainerPrivate *ctn, UiLayout *layout, Arg *args, int *n);
 void ui_grid_container_add(UiContainerPrivate *ctn, Widget widget);
 
-UiContainerX* ui_frame_container(UiObject *obj, Widget frame);
+UiContainer* ui_frame_container(UiObject *obj, Widget frame);
 Widget ui_frame_container_prepare(UiContainerPrivate *ctn, UiLayout *layout, Arg *args, int *n);
 void ui_frame_container_add(UiContainerPrivate *ctn, Widget widget);
 
index 2acb2c30855d826683a7b0b45aa10acb316ebe46..143996678eec533b7323ba3cf60943c1aec48461 100644 (file)
@@ -65,6 +65,7 @@ static UIWIDGET label_create(UiObject *obj, UiLabelArgs *args, int align) {
     Widget w = XmCreateLabel(parent, name, xargs, n);
     XtManageChild(w);
     ui_container_add(ctn, w);
+    uic_widget_set_visibility_states(obj->ctx, w, args->visibility_states);
       
     XmStringFree(label);
     
@@ -162,6 +163,7 @@ UIWIDGET ui_progressbar_create(UiObject *obj, UiProgressbarArgs *args) {
     char *name = args->name ? (char*)args->name : "progressbar";
     Widget frame = XmCreateFrame(parent, name, xargs, n);
     ui_container_add(ctn, frame);
+    uic_widget_set_visibility_states(obj->ctx, frame, args->visibility_states);
     
     // create a button and get some informations about the height, shadow, highlight, ....
     // we want the frame to have the same dimensions as a normal button
@@ -252,6 +254,7 @@ UIWIDGET ui_progressspinner_create(UiObject* obj, UiProgressbarSpinnerArgs *args
     Widget w = XmCreateLabel(parent, name, xargs, n);
     XtManageChild(w);
     ui_container_add(ctn, w);
+    uic_widget_set_visibility_states(obj->ctx, w, args->visibility_states);
     
     UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_INTEGER);
     if(var) {
index 6d935a9ac5075c25504b8d2fdb8f182158cc2017..d744bd6f537bc33f8bdc5ea1a94a465108ea05bb 100644 (file)
@@ -179,7 +179,7 @@ void add_checkitem_widget(Widget p, int i, UiMenuItemI *item, UiObject *obj) {
         XmStringFree(s);
     }
     
-    ui_bind_togglebutton(obj, checkbox, it->varname, NULL, it->callback, it->userdata, 0);
+    ui_bind_togglebutton(obj, checkbox, it->varname, NULL, it->callback, it->userdata, NULL, 0);
     
     ui_set_widget_groups(obj->ctx, checkbox, it->states);
 }
@@ -199,7 +199,7 @@ void add_radioitem_widget(Widget p, int index, UiMenuItemI *item, UiObject *obj)
     Widget button = XmCreateToggleButton(p, "menuradiobutton", args, n);
     XtManageChild(button);
     
-    ui_bind_radiobutton(obj, button, NULL, it->varname, it->callback, it->userdata, 0);
+    ui_bind_radiobutton(obj, button, NULL, it->varname, it->callback, it->userdata, NULL, 0);
 }
 
 static void menuitem_list_remove_binding(void *obj) {
@@ -302,11 +302,14 @@ void ui_update_menuitem_list(UiActiveMenuItemList *list) {
         i++;
     }
     
-    ui_getvaluefunc getvalue = list->getvalue;
+    int row = 0;
+    ui_getvaluefunc2 getvalue = list->getvalue;
+    void *getvaluedata = list->getvaluedata;
     int pos = list->index;
     while(elm) {
         n = 0;
-        char *label = (char*) (getvalue ? getvalue(elm, 0) : elm);
+        UiBool freeResult = FALSE;
+        char *label = (char*) (getvalue ? getvalue(ls, elm, row, 0, getvaluedata, &freeResult) : elm);
         if(label) {
             s = XmStringCreateLocalized(label);
             XtSetArg(args[n], XmNlabelString, s); n++;
@@ -341,7 +344,12 @@ void ui_update_menuitem_list(UiActiveMenuItemList *list) {
                     eventdata);
         }
         
+        if(freeResult) {
+            free(label);
+        }
+        
         elm = ui_list_next(ls);
+        row++;
         i++;
     }
     
index 4c40d797ff596e88f0dcdb6287a20b5deefcf9fb..9ab72b4e61eb13a4d473a57b7a1a9249ffd4f603 100644 (file)
@@ -44,7 +44,8 @@ struct UiActiveMenuItemList {
     int              index;
     int              oldcount;
     UiVar            *var;
-    ui_getvaluefunc  getvalue;
+    ui_getvaluefunc2 getvalue;
+    void             *getvaluedata;
     ui_callback      callback;
     void             *userdata;
     bool             addseparator;
index b2c5389eaa3f2da819b1788e1821607856d11fd6..68c4bab487eb7671984e121c8e97aaf6eb3f6420 100644 (file)
@@ -56,6 +56,7 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) {
     Widget widget = XmCreateScrolledText(parent, name, xargs, n);
     XtManageChild(widget);
     ui_container_add(ctn, widget);
+    uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
     
     UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_TEXT);
     
@@ -97,6 +98,10 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) {
                 var);
     }
     
+    if(args->onchange || args->onchange_action) {
+        
+    }
+    
     return widget;
 }
 
@@ -149,9 +154,9 @@ char* ui_textarea_getsubstr(UiText *text, int begin, int end) {
     return str;
 }
 
-void ui_textarea_insert(UiText *text, int pos, char *str) {
+void ui_textarea_insert(UiText *text, int pos, const char *str) {
     text->value.ptr = NULL;
-    XmTextInsert(text->obj, pos, str);
+    XmTextInsert(text->obj, pos, (char*)str);
     if(text->value.ptr) {
         text->value.free(text->value.ptr);
     }
@@ -213,9 +218,9 @@ void ui_text_selection_callback(
     int sel = left < right ? 1 : 0;
     if(sel != textarea->last_selection_state) {
         if(sel) {
-            ui_set_state(textarea->obj->ctx, UI_GROUP_SELECTION);
+            ui_set_state(textarea->obj->ctx, UI_STATE_SELECTION);
         } else {
-            ui_unset_state(textarea->obj->ctx, UI_GROUP_SELECTION);
+            ui_unset_state(textarea->obj->ctx, UI_STATE_SELECTION);
         }
     }
     textarea->last_selection_state = sel;
@@ -408,6 +413,7 @@ static UIWIDGET create_textfield(UiObject *obj, UiTextFieldArgs *args, int frame
     XtManageChild(textfield);
     ui_container_add(ctn, textfield);
     
+    uic_widget_set_visibility_states(obj->ctx, textfield, args->visibility_states);
     ui_set_widget_groups(obj->ctx, textfield, args->states);
     
     UiEventDataExt *eventdata = malloc(sizeof(UiEventDataExt));
@@ -492,6 +498,39 @@ UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs *args) {
     return create_textfield(obj, args, FALSE, FALSE);
 }
 
+void ui_textfield_focus(UIWIDGET textfield) {
+    ui_textfield_focus_without_selecting(textfield);
+    ui_textfield_select_all(textfield);
+}
+
+void ui_textfield_focus_without_selecting(UIWIDGET textfield) {
+    XmProcessTraversal(textfield, XmTRAVERSE_CURRENT);
+}
+
+void ui_textfield_set_selection(UIWIDGET textfield, int begin, int end) {
+    XmTextSetSelection(textfield, begin, end, 0);
+}
+
+void ui_textfield_select_all(UIWIDGET textfield) {
+    XmTextSetSelection(textfield, 0, XmTextGetLastPosition(textfield), 0);
+}
+
+void ui_textfield_set_editable(UIWIDGET textfield, UiBool editable) {
+    XmTextFieldSetEditable(textfield, editable);
+}
+
+UiBool ui_textfield_is_editable(UIWIDGET textfield) {
+    return XmTextFieldGetEditable(textfield);
+}
+
+void ui_textfield_set_position(UIWIDGET textfield, int pos) {
+    XmTextFieldSetInsertionPosition(textfield, pos);
+}
+
+int ui_textfield_get_position(UIWIDGET textfield) {
+    return (int)XmTextFieldGetInsertionPosition(textfield);
+}
+
 char* ui_textfield_get(UiString *str) {
     if(str->value.free) {
         str->value.free(str->value.ptr);
@@ -554,6 +593,7 @@ UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs *args) {
     
     XtManageChild(pathbar->widget);
     ui_container_add(ctn, pathbar->widget);
+    uic_widget_set_visibility_states(obj->ctx, pathbar->widget, args->visibility_states);
     
     UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_STRING);
     if (var) {
index 9f2932e3486c701b339c756491f65d0eef5765f7..3c59627aca9be360f105197ab97fc228c691a386 100644 (file)
@@ -70,7 +70,7 @@ 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_insert(UiText *text, int pos, const 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);
index fe49df16fb985c554375afb0d3fbc467c526a66b..2fd1bd299e1d27094e872c9bff2f38a76beeb837 100644 (file)
@@ -39,6 +39,7 @@
 #include "../common/document.h"
 #include "../common/properties.h"
 #include "../common/app.h"
+#include "../common/threadpool.h"
 #include <cx/buffer.h>
 
 #include <X11/Intrinsic.h>
@@ -88,8 +89,11 @@ void ui_motif_set_fallback_resources(String *fallbackres) {
     fallback_resources = fallbackres;
 }
 
+// NOOP on most platforms, expect macos
+void ui_set_main_thread_error_msg(const char *msg) {}
+
 void ui_init(const char *appname, int argc, char **argv) { 
-    application_name = appname;
+    application_name = appname ? strdup(appname) : NULL;
     uic_init_global_context();
     
     XtToolkitInitialize();
@@ -97,7 +101,7 @@ void ui_init(const char *appname, int argc, char **argv) {
     app = XtCreateApplicationContext();
     XtAppSetFallbackResources(app, fallback_resources);
     
-    display =  XtOpenDisplay(app, NULL, appname, appname, NULL, 0, &argc, argv);
+    display =  XtOpenDisplay(app, NULL, application_name, application_name, NULL, 0, &argc, argv);
     
     uic_menu_init();
     uic_toolbar_init();
@@ -141,6 +145,14 @@ void ui_main() {
     }
 }
 
+void ui_app_ref(void) {
+    // TODO
+}
+
+void ui_app_unref(void) {
+    // TODO
+}
+
 void ui_app_quit() {
     XtAppSetExitFlag(app);
 }
@@ -155,8 +167,12 @@ void ui_secondary_event_loop(int *loop) {
 
 void ui_show(UiObject *obj) {
     uic_check_state_widgets(obj->ctx);
-    if(!XtIsRealized(obj->widget)) {
-        XtRealizeWidget(obj->widget);
+    if(obj->widget) {
+        if(!XtIsRealized(obj->widget)) {
+            XtRealizeWidget(obj->widget);
+            obj->ref++;
+        }
+    } else {
         obj->ref++;
     }
 }
@@ -221,6 +237,11 @@ static void* ui_jobthread(void *data) {
 }
 
 void ui_call_mainthread(ui_threadfunc tf, void* td) {
+    if(uic_mainthread_calls_is_buffered()) {
+        uic_add_buffered_mainthread_call(tf, td);
+        return;
+    }
+    
     UiJob *job = malloc(sizeof(UiJob));
     memset(job, 0, sizeof(UiJob));
     job->job_func = tf;
@@ -327,6 +348,16 @@ void ui_destroy_data(Widget w, XtPointer data, XtPointer d) {
     free(data);
 }
 
+void ui_destroy_event_data(Widget w, UiEventData *data, XtPointer d) {
+    free(data->action);
+    free(data);
+}
+
+void ui_destroy_var_event_data(Widget w, UiVarEventData *data, XtPointer d) {
+    free(data->action);
+    free(data);
+}
+
 void ui_set_widget_groups(UiContext *ctx, Widget widget, const int *groups) {
     if(!groups) {
         return;
index 069e31c89ee1141b97d9d8f0ca2c8b689f24ea82..880733315f49c2b58903da945ba87653d96d41f6 100644 (file)
@@ -44,6 +44,7 @@ typedef struct UiEventData {
     void        *userdata;
     int         value;
     void        *customdata;
+    char        *action;
 } UiEventData;
 
 typedef struct UiEventDataExt {
@@ -68,6 +69,7 @@ typedef struct UiVarEventData {
     UiObserver  **observers;
     ui_callback callback;
     void        *userdata;
+    char        *action;
     int         value;
 } UiVarEventData;
 
@@ -94,6 +96,10 @@ void ui_window_dark_theme(Display *dp, Window window);
 
 void ui_destroy_data(Widget w, XtPointer data, XtPointer d);
 
+void ui_destroy_event_data(Widget w, UiEventData *data, XtPointer d);
+
+void ui_destroy_var_event_data(Widget w, UiVarEventData *data, XtPointer d);
+
 void ui_set_widget_groups(UiContext *ctx, Widget widget, const int *groups) ;
 void ui_set_widget_ngroups(UiContext *ctx, Widget widget, const int *groups, size_t ngroups);
 
index c8d5b1d4fa2d579895a3cfcb329dc8bdacbf9706..dd1c9ba6f62443ad9c26acee2e35caf6a79f713d 100644 (file)
@@ -142,7 +142,7 @@ static UiObject* create_window(const char *title, Boolean simple) {
     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
     Widget vbox = XtCreateManagedWidget("window_vbox", gridClass, form, args, n);
-    UiContainerX *container = ui_box_container(obj, vbox, UI_BOX_VERTICAL);
+    UiContainer *container = ui_box_container(obj, vbox, UI_BOX_VERTICAL);
     uic_object_push_container(obj, container);
     
     obj->widget = toplevel;
index 36e5b46080552e655295c062783952d2b8a5c358..fcc622874114bc0df5fef34f2edc38fb06713c55 100644 (file)
@@ -43,7 +43,7 @@ static void delete_container(UiContainerPrivate *ct) {
 }
 
 void ui_obj_add_container(UiObject *obj, UiContainerPrivate *ct) {
-    UiContainerX *container = (UiContainerX*)ui_malloc(obj->ctx, sizeof(UiContainerX));
+    UiContainer *container = (UiContainer*)ui_malloc(obj->ctx, sizeof(UiContainer));
     container->close = 0;
     container->container = ct;
     container->prev = NULL;
index 0adf78aac6a4e2d1efae642121bcc1169fae6041..d9ba67a0692e1d97470a7ae4d595da41f8be993f 100644 (file)
 #include <QSplitter>
 #include <QGroupBox>
 
-#define ui_obj_container(obj) (UiContainerPrivate*)((UiContainerX*)obj->container_end)->container
+#define ui_obj_container(obj) (UiContainerPrivate*)((UiContainer*)obj->container_end)->container
 
 struct UiContainerPrivate {
     UIWIDGET current;
-    UiContainerX *container;
+    UiContainer *container;
 
     virtual void add(QWidget *widget, UiLayout& layout) = 0;
     virtual void end() {}
index a2bac52a2ee86f8cbc84d2c16850d3c44686217b..899e8c6fd4440ac253208d6a9521e2dca506f630 100644 (file)
@@ -102,6 +102,9 @@ UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) {
     if(args->multiselection) {
         view->setSelectionMode(QAbstractItemView::ExtendedSelection);
     }
+    if(args->hide_header) {
+        view->setHeaderHidden(true);
+    }
     
     UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST);
     
index f391753ce0f49af04c4e6fa6d9d912fc1229b536..081bb524cf01b58c508d7b90e120b7bce868a986 100644 (file)
@@ -71,7 +71,7 @@ void add_menu_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj) {
     add_menu_items(menu, i, m, obj);
 }
 
-static UiAction* create_action(
+static UiQAction* create_action(
         UiObject *obj,
         const char *icon,
         const char *label,
@@ -80,7 +80,7 @@ static UiAction* create_action(
         int *states)
 {
     QString str = QString::fromUtf8(label);
-    UiAction *action = new UiAction(obj, str, callback, userdata);
+    UiQAction *action = new UiQAction(obj, str, callback, userdata);
     if(icon) {
         action->setIcon(QIcon::fromTheme(icon));
         action->setIconVisibleInMenu(true);
@@ -97,7 +97,7 @@ static UiAction* create_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->states);
+    UiQAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->states);
     parent->addAction(action);
     QObject::connect(action, SIGNAL(triggered()), action, SLOT(trigger()));
 }
@@ -109,7 +109,7 @@ void add_menuseparator_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject
 void add_checkitem_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj) {
     UiMenuCheckItem *it = (UiMenuCheckItem*)item;
     
-    UiAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->states);
+    UiQAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->states);
     parent->addAction(action);
     action->setCheckable(true);
     action->prepare_event = ui_checkableaction_prepare_event;
@@ -129,7 +129,7 @@ void add_checkitem_widget(QMenu *parent, int i, UiMenuItemI *item, UiObject *obj
 void add_radioitem_widget(QMenu *parent, int index, UiMenuItemI *item, UiObject *obj) {
     UiMenuRadioItem *it = (UiMenuRadioItem*)item;
     
-    UiAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->states);
+    UiQAction *action = create_action(obj, it->icon, it->label, it->callback, it->userdata, it->states);
     parent->addAction(action);
     action->setCheckable(true);
     action->prepare_event = ui_actiongroup_prepare_event;
@@ -152,7 +152,7 @@ void add_radioitem_widget(QMenu *parent, int index, UiMenuItemI *item, UiObject
     action->var;
 }
 
-void ui_actiongroup_prepare_event(UiEvent *event, UiAction *action) {
+void ui_actiongroup_prepare_event(UiEvent *event, UiQAction *action) {
     if(action->var) {
         UiInteger *value = (UiInteger*)action->var->value;
         event->eventdata = value;
@@ -214,7 +214,7 @@ void ui_add_menus(UiObject *obj, QMainWindow *window) {
     }
 }
 
-void ui_checkableaction_prepare_event(UiEvent *event, UiAction *action) {
+void ui_checkableaction_prepare_event(UiEvent *event, UiQAction *action) {
     if(action->var) {
         event->eventdata = action->var->value;
         event->eventdatatype = UI_EVENT_DATA_INTEGER_VALUE;
@@ -223,13 +223,13 @@ void ui_checkableaction_prepare_event(UiEvent *event, UiAction *action) {
 }
 
 int64_t ui_checkableaction_get(UiInteger *value) {
-    UiAction *action= (UiAction*)value->obj;
+    UiQAction *action= (UiQAction*)value->obj;
     value->value = action->isChecked();
     return value->value;
 }
 
 void ui_checkableaction_set(UiInteger *value, int64_t i) {
-    UiAction *action = (UiAction*)value->obj;
+    UiQAction *action = (UiQAction*)value->obj;
     value->value = i;
     if(i != 0) {
         action->setChecked((bool)i);
index 9903ae07396149c37c388c91eae8f48826ef3bb0..21079c514a483795a47b1f78296b557ffce9a24a 100644 (file)
@@ -51,11 +51,11 @@ void add_radioitem_widget(QMenu *parent, int index, UiMenuItemI *item, UiObject
 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);
 
-void ui_checkableaction_prepare_event(UiEvent *event, UiAction *action);
+void ui_checkableaction_prepare_event(UiEvent *event, UiQAction *action);
 int64_t ui_checkableaction_get(UiInteger *value);
 void ui_checkableaction_set(UiInteger *value, int64_t i);
 
-void ui_actiongroup_prepare_event(UiEvent *event, UiAction *action);
+void ui_actiongroup_prepare_event(UiEvent *event, UiQAction *action);
 int64_t ui_actiongroup_get(UiInteger *value);
 void ui_actiongroup_set(UiInteger *value, int64_t i);
 
index 361da2ff36ef7d132cfa9dad05b68c4ab4eda6ba..c74c43fe3ddbb515050a0cede813290b0e591cc8 100644 (file)
@@ -99,6 +99,10 @@ QVariant ListModel::data(const QModelIndex &index, int role) const {
 }
 
 void ListModel::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) {
+    if(!ui_selection_events_is_enabled()) {
+        return;
+    }
+    
     UiListSelection sel;
     if(listview) {
         sel = ui_selection_model_to_selection(listview->selectionModel());
index 32871a295abb38cbe14052f4cb30421c0e86f2d5..bdac8ceaadba65fdce126411b82045fc64b9c17b 100644 (file)
@@ -96,6 +96,10 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) {
     return textarea;
 }
 
+UIWIDGET ui_textarea_gettextwidget(UIWIDGET textarea) {
+    return textarea;
+}
+
 void ui_textarea_save(UiText *text) {
     // NOOP
 }
@@ -154,7 +158,7 @@ char* ui_textarea_getsubstr(UiText *text, int begin, int end) {
     return cstr ? strdup(cstr) : NULL;
 }
 
-void ui_textarea_insert(UiText *text, int pos, char *str) {
+void ui_textarea_insert(UiText *text, int pos, const char *str) {
     QTextDocument *doc = (QTextDocument*)text->data1;
     QTextCursor cursor(doc);
     cursor.setPosition(pos);
@@ -189,10 +193,7 @@ void ui_textarea_selection(UiText *text, int *begin, int *end) {
 
 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); 
+    ui_textarea_set_selection(textview, begin, end);
 }
 
 int ui_textarea_length(UiText *text) {
@@ -208,6 +209,56 @@ void ui_textarea_remove(UiText *text, int begin, int end) {
     cursor.removeSelectedText();
 }
 
+
+void ui_textarea_focus(UIWIDGET textarea) {
+    QTextEdit *edit = static_cast<QTextEdit*>(textarea);
+    edit->setFocus();
+}
+
+void ui_textarea_set_selection(UIWIDGET textarea, int begin, int end) {
+    QTextEdit *edit = static_cast<QTextEdit*>(textarea);
+    QTextCursor cursor = edit->textCursor();
+    cursor.setPosition(begin, QTextCursor::MoveAnchor);
+    cursor.setPosition(end, QTextCursor::KeepAnchor);
+    edit->setTextCursor(cursor); 
+}
+
+void ui_textarea_select_all(UIWIDGET textarea) {
+    QTextEdit *edit = static_cast<QTextEdit*>(textarea);
+    edit->selectAll();
+}
+
+void ui_textarea_set_editable(UIWIDGET textarea, UiBool editable) {
+    QTextEdit *edit = static_cast<QTextEdit*>(textarea);
+    edit->setReadOnly(!editable);
+}
+
+UiBool ui_textarea_is_editable(UIWIDGET textarea) {
+    QTextEdit *edit = static_cast<QTextEdit*>(textarea);
+    return !edit->isReadOnly();
+}
+
+void ui_textarea_set_position(UIWIDGET textarea, int pos) {
+    QTextEdit *edit = static_cast<QTextEdit*>(textarea);
+    QTextCursor cursor = edit->textCursor();
+    cursor.setPosition(pos);
+    edit->setTextCursor(cursor); 
+}
+
+int ui_textarea_get_position(UIWIDGET textarea) {
+    QTextEdit *edit = static_cast<QTextEdit*>(textarea);
+    QTextCursor cursor = edit->textCursor();
+    return cursor.position();
+}
+
+void ui_textarea_scroll_to(UIWIDGET textarea, int pos) {
+    QTextEdit *edit = static_cast<QTextEdit*>(textarea);
+    QTextCursor cursor = edit->textCursor();
+    cursor.setPosition(pos);
+    edit->setTextCursor(cursor);
+    edit->ensureCursorVisible();
+}
+
 /* ------------------------------ TextField ------------------------------ */
 
 static UIWIDGET create_textfield(UiObject *obj, UiTextFieldArgs *args, bool password, bool frameless) {
@@ -278,3 +329,50 @@ void ui_textfield_set(UiString *str, const char *value) {
     }
     str->value.ptr = NULL;
 }
+
+void ui_textfield_focus(UIWIDGET textfield) {
+    QLineEdit *edit = static_cast<QLineEdit*>(textfield);
+    edit->setFocus();
+    edit->selectAll();
+}
+
+void ui_textfield_focus_without_selecting(UIWIDGET textfield) {
+    QLineEdit *edit = static_cast<QLineEdit*>(textfield);
+    edit->setFocus();
+}
+
+void ui_textfield_set_selection(UIWIDGET textfield, int begin, int end) {
+    QLineEdit *edit = static_cast<QLineEdit*>(textfield);
+    if (begin < 0) {
+        begin = 0;
+    }
+    if (end < begin) {
+        end = begin;
+    }
+    edit->setSelection(begin, end - begin);
+}
+
+void ui_textfield_select_all(UIWIDGET textfield) {
+    QLineEdit *edit = static_cast<QLineEdit*>(textfield);
+    edit->selectAll();
+}
+
+void ui_textfield_set_editable(UIWIDGET textfield, UiBool editable) {
+    QLineEdit *edit = static_cast<QLineEdit*>(textfield);
+    edit->setReadOnly(!editable);
+}
+
+UiBool ui_textfield_is_editable(UIWIDGET textfield) {
+    QLineEdit *edit = static_cast<QLineEdit*>(textfield);
+    return !edit->isReadOnly();
+}
+
+void ui_textfield_set_position(UIWIDGET textfield, int pos) {
+    QLineEdit *edit = static_cast<QLineEdit*>(textfield);
+    edit->setCursorPosition(pos);
+}
+
+int ui_textfield_get_position(UIWIDGET textfield) {
+    QLineEdit *edit = static_cast<QLineEdit*>(textfield);
+    return edit->cursorPosition();
+}
index fcfe6129ef58ddf8f810ddc353f6c3dcd4f24a96..5ecee2aa29971e5aad44d2101321090cf8382047 100644 (file)
@@ -43,7 +43,7 @@ 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_insert(UiText *text, int pos, const 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);
index bc355d08c56c25b36d66ee5752c2f221b0846746..548cfdda6d24c8eb66217ea2b1c3fb2f1bafd3a4 100644 (file)
@@ -48,8 +48,11 @@ static QApplication *application = NULL;
 
 static UiBool exit_on_shutdown;
 
+// NOOP on most platforms, expect macos
+extern "C" UIEXPORT void ui_set_main_thread_error_msg(const char *msg) {}
+
 void ui_init(const char *appname, int argc, char **argv) {
-    application_name = appname;
+    application_name = appname ? strdup(appname) : NULL;
     
     app_argc = argc;
     app_argv = argv;
@@ -83,6 +86,14 @@ void ui_main() {
     }
 }
 
+void ui_app_ref(void) {
+    // TODO
+}
+
+void ui_app_unref(void) {
+    // TODO
+}
+
 void ui_show(UiObject *obj) {
     obj->widget->show();
 }
@@ -138,17 +149,17 @@ void UiEventWrapper::destroy() {
 
 /* --------------------- Implemtation UiAction --------------------- */
 
-UiAction::UiAction(UiObject *obj, QString &label, ui_callback f, void *userdata) : QAction(label, NULL) {
+UiQAction::UiQAction(UiObject *obj, QString &label, ui_callback f, void *userdata) : QAction(label, NULL) {
     this->obj = obj;
     this->callback = f;
     this->userdata = userdata;
 }
 
-UiAction::~UiAction() {
+UiQAction::~UiQAction() {
     // TODO: unbind var
 }
 
-void UiAction::trigger() {
+void UiQAction::trigger() {
     if(!callback) {
         return;
     }
@@ -170,7 +181,7 @@ void UiAction::trigger() {
 }
 
 // ui_enablefunc for UiAction
-void ui_action_enable(UiAction *action, int enable) {
+void ui_action_enable(UiQAction *action, int enable) {
     action->setEnabled((bool)enable);
 }
 
index 1db8df722231c78cc8912961b4bbd57813c07da4..6108596b240e0611160b645ff764bcf9db7541ec 100644 (file)
@@ -63,11 +63,11 @@ public slots:
     void destroy();
 };
 
-class UiAction;
+class UiQAction;
 
-typedef void (*ui_prepare_action_event_func)(UiEvent *event, UiAction *action);
+typedef void (*ui_prepare_action_event_func)(UiEvent *event, UiQAction *action);
 
-class UiAction : public QAction {
+class UiQAction : public QAction {
     Q_OBJECT
             
     UiObject *obj;
@@ -83,14 +83,14 @@ public:
     int customvalue1 = 0;
     int customvalue2 = 0;
     
-    UiAction(UiObject *obj, QString &label, ui_callback f, void *userdata);
-    ~UiAction();
+    UiQAction(UiObject *obj, QString &label, ui_callback f, void *userdata);
+    ~UiQAction();
     
 private slots:
     void trigger();
 };
 
-void ui_action_enable(UiAction *action, int enable);
+void ui_action_enable(UiQAction *action, int enable);
 
 #endif /* TOOLKIT_H */
 
index 6e4c1c83af43cd07b8043d06660183566db659ec..1c696065d1417013da5359c722531d629e7ae9c5 100644 (file)
@@ -43,7 +43,6 @@
 
 static UiObject* create_window(const char *title, bool simple, bool sidebar = false) {
     UiObject *obj = uic_object_new_toplevel();
-    obj->next = NULL;
     
     QMainWindow *window = new QMainWindow();
     window->setWindowTitle(title);
index 55367f19fc7e54e34c09738c469edf0fbaf91ce5..ae9155f7fa110b91dc55460b69831cfbb3b15113 100644 (file)
@@ -63,9 +63,11 @@ typedef struct UiButtonArgs {
     const char *tooltip;
     UiLabelType labeltype;
     ui_callback onclick;
-    void *onclickdata;
+    void        *onclickdata;
+    const char  *action;
     
     const int *states;
+    const int *visibility_states;
 } UiButtonArgs;
 
 typedef struct UiToggleArgs {
@@ -85,19 +87,58 @@ typedef struct UiToggleArgs {
     const char *name;
     const char *style_class;
     
-    const char *label;
-    const char *icon;
-    const char *tooltip;
+    const char  *label;
+    const char  *icon;
+    const char  *tooltip;
     UiLabelType labeltype;
-    UiInteger *value;
-    const char *varname;
+    UiInteger   *value;
+    const char  *varname;
     ui_callback onchange;
-    void *onchangedata;
-    int enable_state;
+    void        *onchangedata;
+    const char  *action;
+    int         enable_state;
     
-    const int *states;
+    const int   *states;
+    const int   *visibility_states;
 } UiToggleArgs;
 
+typedef struct UiContentToggleArgs {
+    UiBool fill;
+    UiBool hexpand;
+    UiBool vexpand;
+    UiBool hfill;
+    UiBool vfill;
+    UiBool override_defaults;
+    int margin;
+    int margin_left;
+    int margin_right;
+    int margin_top;
+    int margin_bottom;
+    int colspan;
+    int rowspan;
+    const char *name;
+    const char *style_class;
+    
+    const char  *label0;
+    const char  *icon0;
+    const char  *tooltip0;
+    const char  *label1;
+    const char  *icon1;
+    const char  *tooltip1;
+    UiLabelType labeltype;
+    UiInteger   *value;
+    const char  *varname;
+    ui_callback onchange;
+    void        *onchangedata;
+    const char  *action;
+    UiBool      istogglebutton;
+    int         enable_state;
+    int         toggled_by_state;
+    
+    const int   *states;
+    const int   *visibility_states;
+} UiContentToggleArgs;
+
 typedef struct UiLinkButtonArgs {
     UiBool fill;
     UiBool hexpand;
@@ -121,16 +162,19 @@ typedef struct UiLinkButtonArgs {
     const char *varname;
     ui_callback onclick;
     void *onclickdata;
+    const char *action;
     UiBool nofollow;
     UiLinkType type;
     
     const int *states;
+    const int *visibility_states;
 } UiLinkButtonArgs;
  
 #define ui_button(obj, ...) ui_button_create(obj, &(UiButtonArgs){ __VA_ARGS__ } )
 #define ui_togglebutton(obj, ...) ui_togglebutton_create(obj, &(UiToggleArgs){ __VA_ARGS__ } )
 #define ui_checkbox(obj, ...) ui_checkbox_create(obj, &(UiToggleArgs){ __VA_ARGS__ } )
 #define ui_switch(obj, ...) ui_switch_create(obj, &(UiToggleArgs){ __VA_ARGS__ } )
+#define ui_content_togglebutton(obj, ...) ui_content_togglebutton_create(obj, &(UiContentToggleArgs){ __VA_ARGS__ } )
 #define ui_radiobutton(obj, ...) ui_radiobutton_create(obj, &(UiToggleArgs){ __VA_ARGS__ } )
 #define ui_linkbutton(obj, ...) ui_linkbutton_create(obj, &(UiLinkButtonArgs){ __VA_ARGS__ })
 
@@ -138,11 +182,25 @@ UIEXPORT UIWIDGET ui_button_create(UiObject *obj, UiButtonArgs *args);
 UIEXPORT UIWIDGET ui_togglebutton_create(UiObject *obj, UiToggleArgs *args);
 UIEXPORT UIWIDGET ui_checkbox_create(UiObject *obj, UiToggleArgs *args);
 UIEXPORT UIWIDGET ui_switch_create(UiObject *obj, UiToggleArgs *args);
+UIEXPORT UIWIDGET ui_content_togglebutton_create(UiObject *obj, UiContentToggleArgs *args);
 UIEXPORT UIWIDGET ui_radiobutton_create(UiObject *obj, UiToggleArgs *args);
 UIEXPORT UIWIDGET ui_linkbutton_create(UiObject *obj, UiLinkButtonArgs *args);
 
 UIEXPORT void ui_button_set_label(UIWIDGET button, const char *label);
 UIEXPORT void ui_button_set_icon(UIWIDGET button, const char *icon);
+UIEXPORT void ui_button_set_tooltip(UIWIDGET button, const char *tooltip);
+
+UIEXPORT void ui_togglebutton_set_label(UIWIDGET button, const char *label);
+UIEXPORT void ui_togglebutton_set_icon(UIWIDGET button, const char *icon);
+UIEXPORT void ui_togglebutton_set_tooltip(UIWIDGET button, const char *tooltip);
+
+UIEXPORT void ui_checkbox_set_label(UIWIDGET button, const char *label);
+UIEXPORT void ui_checkbox_set_icon(UIWIDGET button, const char *icon);
+UIEXPORT void ui_checkbox_set_tooltip(UIWIDGET button, const char *tooltip);
+
+UIEXPORT void ui_radiobutton_set_label(UIWIDGET button, const char *label);
+UIEXPORT void ui_radiobutton_set_icon(UIWIDGET button, const char *icon);
+UIEXPORT void ui_radiobutton_set_tooltip(UIWIDGET button, const char *tooltip);
 
 UIEXPORT void ui_linkbutton_value_set(UiString *str, const char *label, const char *uri);
 UIEXPORT void ui_linkbutton_value_set_label(UiString *str, const char *label);
index dc2aa299ebef95b7e26fc502c1edbb28bd58bffc..187f22107f624271f6a8773fd35762c6880cc568 100644 (file)
@@ -82,6 +82,8 @@ typedef struct UiContainerArgs {
     UiBool def_vfill;
     UiBool def_hexpand;
     UiBool def_vexpand;
+    
+    const int *visibility_states;
 } UiContainerArgs;
 
 typedef struct UiFrameArgs {
@@ -112,6 +114,8 @@ typedef struct UiFrameArgs {
 
     const char* label;
     UiBool isexpanded;
+    
+    const int *visibility_states;
 } UiFrameArgs;
 
 typedef struct UiTabViewArgs {
@@ -144,6 +148,8 @@ typedef struct UiTabViewArgs {
     int spacing;
     int columnspacing;
     int rowspacing;
+    
+    const int *visibility_states;
 } UiTabViewArgs;
 
 typedef struct UiHeaderbarArgs {
@@ -207,6 +213,8 @@ typedef struct UiSplitPaneArgs {
     UiInteger *value;
     const char* varname;
     int max_panes;
+    
+    const int *visibility_states;
 } UiSplitPaneArgs;
 
 typedef struct UiItemListContainerArgs {
@@ -277,12 +285,12 @@ struct UiLayout {
     int          rowspan;
 };
 
-struct UiContainerX {
+struct UiContainer {
     void *container;
     UiBool close;
     UiBool newline;
-    UiContainerX *prev;
-    UiContainerX *next;
+    UiContainer *prev;
+    UiContainer *next;
 };
 
 
@@ -373,10 +381,6 @@ UIEXPORT void ui_newline(UiObject *obj);
 typedef void(*ui_addwidget_func)(UiObject *obj, UIWIDGET parent, UIWIDGET child, void *userdata);
 UIEXPORT void ui_custom_container_create(UiObject *obj, UIWIDGET widget, ui_addwidget_func add_child, void *userdata);
 
-// TODO
-UIEXPORT UiTabbedPane* ui_tabbed_document_view(UiObject *obj);
-UIEXPORT UiObject* ui_document_tab(UiTabbedPane *view);
-
 
 
 /* used for macro */
index 1ed1235ba3170ed93a88e6ef88c97e1a92268789..a9c585a9a4ae5c0032c4b6c5bce5d166e878f4d0 100644 (file)
@@ -71,6 +71,8 @@ typedef struct UiLabelArgs {
     UiLabelStyle style;
     UiString* value;
     const char* varname;
+    
+    const int *visibility_states;
 } UiLabelArgs;
 
 typedef struct UiProgressbarArgs {
@@ -95,6 +97,8 @@ typedef struct UiProgressbarArgs {
     double max;
     UiDouble* value;
     const char* varname;
+    
+    const int *visibility_states;
 } UiProgressbarArgs;
 
 typedef struct UiProgressbarSpinnerArgs {
@@ -116,6 +120,8 @@ typedef struct UiProgressbarSpinnerArgs {
 
     UiInteger* value;
     const char* varname;
+    
+    const int *visibility_states;
 } UiProgressbarSpinnerArgs;
 
 /* label widgets */
index 9ee26d3b1e5a02cab83240cb61febc84ba55b7c1..2b898767f635424e6e438729686e42676034f681 100644 (file)
@@ -66,6 +66,7 @@ typedef struct UiSpinBoxArgs {
     void* onchangedata;
     
     const int *states;
+    const int *visibility_states;;
 } UiSpinBoxArgs;
 
 
index 9bc86a44927ced04df40d59a9cfd3c62ab5ed490..2b5540f1a9d625365165f1c36606e79c91ba5769 100644 (file)
@@ -38,23 +38,139 @@ extern "C" {
 #ifdef UI_GTK
     
 #define UI_ICON_HOME "go-home"
-#define UI_ICON_NEW_WINDOW "list-add"
-#define UI_ICON_REFRESH "view-refresh"
+#define UI_ICON_NEW_WINDOW "window-new"
+#define UI_ICON_NEW_TAB "tab-new"
 #define UI_ICON_NEW_FOLDER "folder-new"
-#define UI_ICON_ADD "document-new"
+#define UI_ICON_NEW_DOCUMENT "document-new"
+#define UI_ICON_NEW_APPOINTMENT "appointment-new"
+#define UI_ICON_NEW_CHAT_MESSAGE "chat-message-new"
+#define UI_ICON_NEW_CONTACT "contact-new"
+#define UI_ICON_NEW_MAIL "mail-message-new"
+#define UI_ICON_ADD_BOOKMARK "bookmark-new"
+#define UI_ICON_ADD_IMAGE "insert-image"
+#define UI_ICON_ADD_LINK "insert-link"
+#define UI_ICON_ADD_TEXT "insert-text"
+#define UI_ICON_ADD "list-add"
+#define UI_ICON_REMOVE "list-remove"
+#define UI_ICON_REFRESH "view-refresh"
 #define UI_ICON_UPLOAD "document-open"
 #define UI_ICON_SAVE_LOCAL "document-save-as"
-#define UI_ICON_DELETE "edit-delete"
-#define UI_ICON_DOCK_LEFT ""
-#define UI_ICON_DOCK_RIGHT ""
+#define UI_ICON_EDIT_COPY "edit-copy"
+#define UI_ICON_EDIT_CUT "edit-cut"
+#define UI_ICON_EDIT_DELETE "edit-delete"
+#define UI_ICON_EDIT_PASTE "edit-paste"
+#define UI_ICON_UNDO "edit-undo"
+#define UI_ICON_REDO "edit-redo"
+#define UI_ICON_SIDEBAR_LEFT "sidebar-show"
+#define UI_ICON_SIDEBAR_RIGHT "sidebar-show-right"
 #define UI_ICON_GO_BACK "go-previous"
 #define UI_ICON_GO_FORWARD "go-next"
 #define UI_ICON_GO_UP "go-up"
 #define UI_ICON_GO_DOWN "go-down"
+#define UI_ICON_VIEW_LIST "view-list"
+#define UI_ICON_VIEW_GRID "view-grid"
+#define UI_ICON_VIEW_DUAL "view-dual"
+#define UI_ICON_VIEW_FULLSCREEN "view-fullscreen"
+#define UI_ICON_VIEW_RESTORE "view-restore"
+#define UI_ICON_TEXT_BOLD "format-text-bold"
+#define UI_ICON_TEXT_ITALIC "format-text-italic"
+#define UI_ICON_TEXT_UNDERLINE "format-text-underline"
+#define UI_ICON_LIST_BULLET "view-list-bullet"
+#define UI_ICON_LIST_ORDERED "view-list-ordered"
+#define UI_ICON_LIST_CHECK "checkbox-checked"
+#define UI_ICON_CHECKBOX "checkbox-checked"
+#define UI_ICON_STAR "starred"
+#define UI_ICON_VIEW_REVEAL "view-reveal"
+#define UI_ICON_VIEW_CONCEAL "view-conceal"
+#define UI_ICON_SETTINGS "applications-system"
+#define UI_ICON_MEDIA_PLAY "media-playback-start"
+#define UI_ICON_MEDIA_STOP "media-playback-stop"
+#define UI_ICON_MEDIA_PAUSE "media-playback-pause"
+#define UI_ICON_MEDIA_SEEK_BACKWARD "media-seek-backward"
+#define UI_ICON_MEDIA_SEEK_FORWARD "media-seek-forward"
+#define UI_ICON_MEDIA_SKIP_BACKWARD "media-skip-backward"
+#define UI_ICON_MEDIA_SKIP_FORWARD "media-skip-forward"
+#define UI_ICON_CALL_START "call-start"
+#define UI_ICON_CALL_STOP "call-stop"
+#define UI_ICON_CALL_INCOMING "call-incoming"
+#define UI_ICON_CALL_OUTGOING "call-outgoing"
+#define UI_ICON_MICROPHONE_ON "microphone-sensitivity-high"
+#define UI_ICON_MICROPHONE_OFF "microphone-disabled"
+#define UI_ICON_LOCKED "changes-allow"
+#define UI_ICON_UNLOCKED "changes-prevent"
+#define UI_ICON_SECURE "channel-secure"
+#define UI_ICON_INSECURE "channel-insecure"
+    
     
 #endif /* UI_GTK */
     
+#ifdef UI_QT
+    
+#define UI_ICON_HOME "go-home"
+#define UI_ICON_NEW_WINDOW "window-new"
+#define UI_ICON_NEW_TAB "tab-new"
+#define UI_ICON_NEW_FOLDER "folder-new"
+#define UI_ICON_NEW_DOCUMENT "document-new"
+#define UI_ICON_NEW_APPOINTMENT "appointment-new"
+#define UI_ICON_NEW_CHAT_MESSAGE "chat-message-new"
+#define UI_ICON_NEW_CONTACT "contact-new"
+#define UI_ICON_NEW_MAIL "mail-message-new"
+#define UI_ICON_ADD_BOOKMARK "bookmark-new"
+#define UI_ICON_ADD_IMAGE "insert-image"
+#define UI_ICON_ADD_LINK "insert-link"
+#define UI_ICON_ADD_TEXT "insert-text"
+#define UI_ICON_ADD "list-add"
+#define UI_ICON_REMOVE "list-remove"
+#define UI_ICON_REFRESH "view-refresh"
+#define UI_ICON_UPLOAD "document-open"
+#define UI_ICON_SAVE_LOCAL "document-save-as"
+#define UI_ICON_EDIT_COPY "edit-copy"
+#define UI_ICON_EDIT_CUT "edit-cut"
+#define UI_ICON_EDIT_DELETE "edit-delete"
+#define UI_ICON_EDIT_PASTE "edit-paste"
+#define UI_ICON_UNDO "edit-undo"
+#define UI_ICON_REDO "edit-redo"
+#define UI_ICON_SIDEBAR_LEFT "sidebar-show"
+#define UI_ICON_SIDEBAR_RIGHT "sidebar-show-right"
+#define UI_ICON_GO_BACK "go-previous"
+#define UI_ICON_GO_FORWARD "go-next"
+#define UI_ICON_GO_UP "go-up"
+#define UI_ICON_GO_DOWN "go-down"
+#define UI_ICON_VIEW_LIST "view-list"
+#define UI_ICON_VIEW_GRID "view-grid"
+#define UI_ICON_VIEW_DUAL "view-dual"
+#define UI_ICON_VIEW_FULLSCREEN "view-fullscreen"
+#define UI_ICON_VIEW_RESTORE "view-restore"
+#define UI_ICON_TEXT_BOLD "format-text-bold"
+#define UI_ICON_TEXT_ITALIC "format-text-italic"
+#define UI_ICON_TEXT_UNDERLINE "format-text-underline"
+#define UI_ICON_LIST_BULLET "view-list-bullet"
+#define UI_ICON_LIST_ORDERED "view-list-ordered"
+#define UI_ICON_LIST_CHECK "checkbox-checked"
+#define UI_ICON_CHECKBOX "checkbox-checked"
+#define UI_ICON_STAR "starred"
+#define UI_ICON_VIEW_REVEAL "view-reveal"
+#define UI_ICON_VIEW_CONCEAL "view-conceal"
+#define UI_ICON_SETTINGS "applications-system"
+#define UI_ICON_MEDIA_PLAY "media-playback-start"
+#define UI_ICON_MEDIA_STOP "media-playback-stop"
+#define UI_ICON_MEDIA_PAUSE "media-playback-pause"
+#define UI_ICON_MEDIA_SEEK_BACKWARD "media-seek-backward"
+#define UI_ICON_MEDIA_SEEK_FORWARD "media-seek-forward"
+#define UI_ICON_MEDIA_SKIP_BACKWARD "media-skip-backward"
+#define UI_ICON_MEDIA_SKIP_FORWARD "media-skip-forward"
+#define UI_ICON_CALL_START "call-start"
+#define UI_ICON_CALL_STOP "call-stop"
+#define UI_ICON_CALL_INCOMING "call-incoming"
+#define UI_ICON_CALL_OUTGOING "call-outgoing"
+#define UI_ICON_MICROPHONE_ON "microphone-sensitivity-high"
+#define UI_ICON_MICROPHONE_OFF "microphone-disabled"
+#define UI_ICON_LOCKED "changes-allow"
+#define UI_ICON_UNLOCKED "changes-prevent"
+#define UI_ICON_SECURE "channel-secure"
+#define UI_ICON_INSECURE "channel-insecure"
     
+#endif /* UI_QT */
 
 #ifdef UI_WINUI
     
@@ -72,9 +188,280 @@ extern "C" {
 #define UI_ICON_GO_FORWARD "Forward"
 #define UI_ICON_GO_UP "Up"
 #define UI_ICON_GO_DOWN "" // TODO: implement workaround for missing down symbol
+#define UI_ICON_LIST "List"
     
 #endif /* UI_WINUI */
+
+#ifdef UI_COCOA
+
+#define UI_ICON_HOME "go-home"
+#define UI_ICON_NEW_WINDOW "macwindow.badge.plus"
+#define UI_ICON_NEW_TAB "plus.square"
+#define UI_ICON_NEW_FOLDER "folder.badge.plus"
+#define UI_ICON_NEW_DOCUMENT "document.badge.plus"
+#define UI_ICON_NEW_APPOINTMENT "calendar.badge.plus"
+#define UI_ICON_NEW_CHAT_MESSAGE "plus.bubble"
+#define UI_ICON_NEW_CONTACT "person.badge.plus"
+#define UI_ICON_NEW_MAIL "envelope.badge.plus"
+#define UI_ICON_ADD_BOOKMARK "book.badge.plus"
+#define UI_ICON_ADD_IMAGE "photo.badge.plus"
+#define UI_ICON_ADD_LINK "link.badge.plus"
+#define UI_ICON_ADD_TEXT "text.badge.plus"
+#define UI_ICON_ADD "plus"
+#define UI_ICON_REMOVE "minus"
+#define UI_ICON_REFRESH "arrow.clockwise"
+#define UI_ICON_UPLOAD "square.and.arrow.up"
+#define UI_ICON_SAVE_LOCAL "square.and.arrow.down"
+#define UI_ICON_EDIT_COPY "document.on.document"
+#define UI_ICON_EDIT_CUT "scissors"
+#define UI_ICON_EDIT_DELETE "minus.circle"
+#define UI_ICON_EDIT_PASTE "document.on.clipboard"
+#define UI_ICON_UNDO "arrow.uturn.backward"
+#define UI_ICON_REDO "arrow.uturn.forward"
+#define UI_ICON_SIDEBAR_LEFT "sidebar.left"
+#define UI_ICON_SIDEBAR_RIGHT "sidebar.right"
+#define UI_ICON_GO_BACK "chevron.left"
+#define UI_ICON_GO_FORWARD "chevron.right"
+#define UI_ICON_GO_UP "chevron.up"
+#define UI_ICON_GO_DOWN "chevron.down"
+#define UI_ICON_VIEW_LIST "list.bullet"
+#define UI_ICON_VIEW_GRID "square.grid.2x2"
+#define UI_ICON_VIEW_DUAL "rectangle.split.2x1"
+#define UI_ICON_VIEW_FULLSCREEN "arrow.up.left.and.arrow.down.right.rectangle"
+#define UI_ICON_VIEW_RESTORE "arrow.down.forward.and.arrow.up.backward.rectangle"
+#define UI_ICON_TEXT_BOLD "bold"
+#define UI_ICON_TEXT_ITALIC "italic"
+#define UI_ICON_TEXT_UNDERLINE "underline"
+#define UI_ICON_LIST_BULLET "list.bullet"
+#define UI_ICON_LIST_ORDERED "list.number"
+#define UI_ICON_LIST_CHECK "checklist"
+#define UI_ICON_CHECKBOX "checkmark.square"
+#define UI_ICON_STAR "star"
+#define UI_ICON_VIEW_REVEAL "eye"
+#define UI_ICON_VIEW_CONCEAL "eye.slash"
+#define UI_ICON_SETTINGS "gearshape"
+#define UI_ICON_MEDIA_PLAY "play.fill"
+#define UI_ICON_MEDIA_STOP "stop.fill"
+#define UI_ICON_MEDIA_PAUSE "pause.fill"
+#define UI_ICON_MEDIA_SEEK_BACKWARD "backward.fill"
+#define UI_ICON_MEDIA_SEEK_FORWARD "forward.fill"
+#define UI_ICON_MEDIA_SKIP_BACKWARD "backward.end.fill"
+#define UI_ICON_MEDIA_SKIP_FORWARD "forward.end.fill"
+#define UI_ICON_CALL_START "phone"
+#define UI_ICON_CALL_STOP "phone.down"
+#define UI_ICON_CALL_INCOMING "phone.arrow.down.left"
+#define UI_ICON_CALL_OUTGOING "phone.arrow.up.right"
+#define UI_ICON_MICROPHONE_ON "microphone"
+#define UI_ICON_MICROPHONE_OFF "microphone.slash"
+#define UI_ICON_LOCKED "lock"
+#define UI_ICON_UNLOCKED "lock.open"
+#define UI_ICON_SECURE "lock"
+#define UI_ICON_INSECURE "lock.trianglebadge.exclamationmark"
+
+#endif /* UI_COCOA */
+    
+#ifdef UI_MOTIF
+    
+#define UI_ICON_HOME ""
+#define UI_ICON_NEW_WINDOW ""
+#define UI_ICON_NEW_TAB ""
+#define UI_ICON_NEW_FOLDER ""
+#define UI_ICON_NEW_DOCUMENT ""
+#define UI_ICON_NEW_APPOINTMENT ""
+#define UI_ICON_NEW_CHAT_MESSAGE ""
+#define UI_ICON_NEW_CONTACT ""
+#define UI_ICON_NEW_MAIL ""
+#define UI_ICON_ADD_BOOKMARK ""
+#define UI_ICON_ADD_IMAGE ""
+#define UI_ICON_ADD_LINK ""
+#define UI_ICON_ADD_TEXT ""
+#define UI_ICON_ADD ""
+#define UI_ICON_REMOVE ""
+#define UI_ICON_REFRESH ""
+#define UI_ICON_UPLOAD ""
+#define UI_ICON_SAVE_LOCAL ""
+#define UI_ICON_EDIT_COPY ""
+#define UI_ICON_EDIT_CUT ""
+#define UI_ICON_EDIT_DELETE ""
+#define UI_ICON_EDIT_PASTE ""
+#define UI_ICON_UNDO ""
+#define UI_ICON_REDO ""
+#define UI_ICON_SIDEBAR_LEFT ""
+#define UI_ICON_SIDEBAR_RIGHT ""
+#define UI_ICON_GO_BACK ""
+#define UI_ICON_GO_FORWARD ""
+#define UI_ICON_GO_UP ""
+#define UI_ICON_GO_DOWN ""
+#define UI_ICON_VIEW_LIST ""
+#define UI_ICON_VIEW_GRID ""
+#define UI_ICON_VIEW_DUAL ""
+#define UI_ICON_VIEW_FULLSCREEN ""
+#define UI_ICON_VIEW_RESTORE ""
+#define UI_ICON_TEXT_BOLD ""
+#define UI_ICON_TEXT_ITALIC ""
+#define UI_ICON_TEXT_UNDERLINE ""
+#define UI_ICON_LIST_BULLET ""
+#define UI_ICON_LIST_ORDERED ""
+#define UI_ICON_LIST_CHECK ""
+#define UI_ICON_CHECKBOX ""
+#define UI_ICON_STAR ""
+#define UI_ICON_VIEW_REVEAL ""
+#define UI_ICON_VIEW_CONCEAL ""
+#define UI_ICON_SETTINGS ""
+#define UI_ICON_MEDIA_PLAY ""
+#define UI_ICON_MEDIA_STOP ""
+#define UI_ICON_MEDIA_PAUSE ""
+#define UI_ICON_MEDIA_SEEK_BACKWARD ""
+#define UI_ICON_MEDIA_SEEK_FORWARD ""
+#define UI_ICON_MEDIA_SKIP_BACKWARD ""
+#define UI_ICON_MEDIA_SKIP_FORWARD ""
+#define UI_ICON_CALL_START ""
+#define UI_ICON_CALL_STOP ""
+#define UI_ICON_CALL_INCOMING ""
+#define UI_ICON_CALL_OUTGOING ""
+#define UI_ICON_MICROPHONE_ON ""
+#define UI_ICON_MICROPHONE_OFF ""
+#define UI_ICON_LOCKED ""
+#define UI_ICON_UNLOCKED ""
+#define UI_ICON_SECURE ""
+#define UI_ICON_INSECURE ""
     
+#endif /* UI_MOTIF */
+    
+#ifdef UI_WIN32
+    
+#define UI_ICON_HOME ""
+#define UI_ICON_NEW_WINDOW ""
+#define UI_ICON_NEW_TAB ""
+#define UI_ICON_NEW_FOLDER ""
+#define UI_ICON_NEW_DOCUMENT ""
+#define UI_ICON_NEW_APPOINTMENT ""
+#define UI_ICON_NEW_CHAT_MESSAGE ""
+#define UI_ICON_NEW_CONTACT ""
+#define UI_ICON_NEW_MAIL ""
+#define UI_ICON_ADD_BOOKMARK ""
+#define UI_ICON_ADD_IMAGE ""
+#define UI_ICON_ADD_LINK ""
+#define UI_ICON_ADD_TEXT ""
+#define UI_ICON_ADD ""
+#define UI_ICON_REMOVE ""
+#define UI_ICON_REFRESH ""
+#define UI_ICON_UPLOAD ""
+#define UI_ICON_SAVE_LOCAL ""
+#define UI_ICON_EDIT_COPY ""
+#define UI_ICON_EDIT_CUT ""
+#define UI_ICON_EDIT_DELETE ""
+#define UI_ICON_EDIT_PASTE ""
+#define UI_ICON_UNDO ""
+#define UI_ICON_REDO ""
+#define UI_ICON_SIDEBAR_LEFT ""
+#define UI_ICON_SIDEBAR_RIGHT ""
+#define UI_ICON_GO_BACK ""
+#define UI_ICON_GO_FORWARD ""
+#define UI_ICON_GO_UP ""
+#define UI_ICON_GO_DOWN ""
+#define UI_ICON_VIEW_LIST ""
+#define UI_ICON_VIEW_GRID ""
+#define UI_ICON_VIEW_DUAL ""
+#define UI_ICON_VIEW_FULLSCREEN ""
+#define UI_ICON_VIEW_RESTORE ""
+#define UI_ICON_TEXT_BOLD ""
+#define UI_ICON_TEXT_ITALIC ""
+#define UI_ICON_TEXT_UNDERLINE ""
+#define UI_ICON_LIST_BULLET ""
+#define UI_ICON_LIST_ORDERED ""
+#define UI_ICON_LIST_CHECK ""
+#define UI_ICON_CHECKBOX ""
+#define UI_ICON_STAR ""
+#define UI_ICON_VIEW_REVEAL ""
+#define UI_ICON_VIEW_CONCEAL ""
+#define UI_ICON_SETTINGS ""
+#define UI_ICON_MEDIA_PLAY ""
+#define UI_ICON_MEDIA_STOP ""
+#define UI_ICON_MEDIA_PAUSE ""
+#define UI_ICON_MEDIA_SEEK_BACKWARD ""
+#define UI_ICON_MEDIA_SEEK_FORWARD ""
+#define UI_ICON_MEDIA_SKIP_BACKWARD ""
+#define UI_ICON_MEDIA_SKIP_FORWARD ""
+#define UI_ICON_CALL_START ""
+#define UI_ICON_CALL_STOP ""
+#define UI_ICON_CALL_INCOMING ""
+#define UI_ICON_CALL_OUTGOING ""
+#define UI_ICON_MICROPHONE_ON ""
+#define UI_ICON_MICROPHONE_OFF ""
+#define UI_ICON_LOCKED ""
+#define UI_ICON_UNLOCKED ""
+#define UI_ICON_SECURE ""
+#define UI_ICON_INSECURE ""
+    
+#endif /* UI_MOTIF */
+    
+    
+enum UiIconId {
+    UI_ICON_ID_HOME,
+    UI_ICON_ID_NEW_WINDOW,
+    UI_ICON_ID_NEW_TAB,
+    UI_ICON_ID_NEW_FOLDER,
+    UI_ICON_ID_NEW_DOCUMENT,
+    UI_ICON_ID_NEW_APPOINTMENT,
+    UI_ICON_ID_NEW_CHAT_MESSAGE,
+    UI_ICON_ID_NEW_CONTACT,
+    UI_ICON_ID_NEW_MAIL,
+    UI_ICON_ID_ADD_BOOKMARK,
+    UI_ICON_ID_ADD_IMAGE,
+    UI_ICON_ID_ADD_LINK,
+    UI_ICON_ID_ADD_TEXT,
+    UI_ICON_ID_ADD,
+    UI_ICON_ID_REMOVE,
+    UI_ICON_ID_REFRESH,
+    UI_ICON_ID_UPLOAD,
+    UI_ICON_ID_SAVE_LOCAL,
+    UI_ICON_ID_EDIT_COPY,
+    UI_ICON_ID_EDIT_CUT,
+    UI_ICON_ID_EDIT_DELETE,
+    UI_ICON_ID_EDIT_PASTE,
+    UI_ICON_ID_UNDO,
+    UI_ICON_ID_REDO,
+    UI_ICON_ID_SIDEBAR_LEFT,
+    UI_ICON_ID_SIDEBAR_RIGHT,
+    UI_ICON_ID_GO_BACK,
+    UI_ICON_ID_GO_FORWARD,
+    UI_ICON_ID_GO_UP,
+    UI_ICON_ID_GO_DOWN,
+    UI_ICON_ID_VIEW_LIST,
+    UI_ICON_ID_VIEW_GRID,
+    UI_ICON_ID_VIEW_DUAL,
+    UI_ICON_ID_VIEW_FULLSCREEN,
+    UI_ICON_ID_VIEW_RESTORE,
+    UI_ICON_ID_TEXT_BOLD,
+    UI_ICON_ID_TEXT_ITALIC,
+    UI_ICON_ID_TEXT_UNDERLINE,
+    UI_ICON_ID_LIST_BULLET,
+    UI_ICON_ID_LIST_ORDERED,
+    UI_ICON_ID_LIST_CHECK,
+    UI_ICON_ID_CHECKBOX,
+    UI_ICON_ID_STAR,
+    UI_ICON_ID_VIEW_REVEAL,
+    UI_ICON_ID_VIEW_CONCEAL,
+    UI_ICON_ID_SETTINGS,
+    UI_ICON_ID_MEDIA_PLAY,
+    UI_ICON_ID_MEDIA_STOP,
+    UI_ICON_ID_MEDIA_PAUSE,
+    UI_ICON_ID_MEDIA_SEEK_BACKWARD,
+    UI_ICON_ID_MEDIA_SEEK_FORWARD,
+    UI_ICON_ID_MEDIA_SKIP_BACKWARD,
+    UI_ICON_ID_MEDIA_SKIP_FORWARD,
+    UI_ICON_ID_CALL_START,
+    UI_ICON_ID_CALL_STOP,
+    UI_ICON_ID_CALL_INCOMING,
+    UI_ICON_ID_CALL_OUTGOING,
+    UI_ICON_ID_MICROPHONE_ON,
+    UI_ICON_ID_MICROPHONE_OFF,
+    UI_ICON_ID_LOCKED,
+    UI_ICON_ID_UNLOCKED,
+    UI_ICON_ID_SECURE,
+    UI_ICON_ID_INSECURE
+};
     
 UIEXPORT UiIcon* ui_icon(const char* name, size_t size);
 UIEXPORT UiIcon* ui_icon_unscaled(const char *name, int size);
@@ -85,6 +472,8 @@ UIEXPORT UiIcon* ui_foldericon(size_t size);
 UIEXPORT UiIcon* ui_fileicon(size_t size);
 
 
+UIEXPORT const char* ui_icon_name(enum UiIconId icon_id);
+
 #ifdef __cplusplus
 }
 #endif
index 7cfbfbba5cd2cb14ae25ceed9ab81c3cab0e88da..35de753c60a999004adbab48655f055e0e1f09e9 100644 (file)
@@ -166,20 +166,27 @@ struct UiListArgs {
     void *getstyledata;
     ui_callback onactivate;
     void *onactivatedata;
+    const char *onactivate_action;
     ui_callback onselection;
     void *onselectiondata;
+    const char *onselection_action;
     ui_callback ondragstart;
     void *ondragstartdata;
+    const char *ondragstart_action;
     ui_callback ondragcomplete;
     void *ondragcompletedata;
+    const char *ondragcomplete_action;
     ui_callback ondrop;
     void *ondropdata;
+    const char *ondrop_action;
     UiBool multiselection;
+    UiBool hide_header;
     UiMenuBuilder *contextmenu;
     ui_list_savefunc onsave;
     void *onsavedata;
     
     const int *states;
+    const int *visibility_states;
 };
 
 typedef void (*ui_sublist_getvalue_func)(UiList *list, void *sublist_userdata, void *rowdata, int index, UiSubListItem *item, void *userdata);
@@ -295,6 +302,8 @@ struct UiSourceListArgs {
     void        *onbuttonclickdata;
     
     UiMenuBuilder *contextmenu;
+    
+    const int *visibility_states;;
 };
 
 #define UI_SUBLIST(...) (UiSubList){ __VA_ARGS__ }
index 43cca7e7f6ab80e39a945356b0c8db06fb320f9e..5ad8776419ddbc73c3c44794dd9faaa799efb264 100644 (file)
@@ -37,31 +37,40 @@ extern "C" {
 
 
 typedef struct UiMenuItemArgs {
-       const charlabel;
-       const charicon;
-
+       const char *label;
+       const char *icon;
+        
        ui_callback onclick;
-       void* onclickdata;
+       void *onclickdata;
+        const char *action;
+        const char *accelerator;
+        const char *accelerator_text;
 
-       const intstates;
+       const int *states;
 } UiMenuItemArgs;
 
 typedef struct UiMenuToggleItemArgs {
-       const charlabel;
-       const charicon;
+       const char *label;
+       const char *icon;
 
-       const charvarname;
+       const char *varname;
        ui_callback onchange;
-       void* onchangedata;
+       void *onchangedata;
+        const char *action;
+        const char *accelerator;
+        const char *accelerator_text;
 
-       const intnstates;
+       const int *nstates;
 } UiMenuToggleItemArgs;
 
 typedef struct UiMenuItemListArgs {
-       const charvarname;
+       const char *varname;
        ui_getvaluefunc getvalue;
+        ui_getvaluefunc2 getvalue2;
+        void *getvaluedata;
        ui_callback onselect;
-       void* onselectdata;
+       void *onselectdata;
+        const char *action;
         UiBool addseparator;
 } UiMenuItemListArgs;
 
index c102f0b36ce20b74160aa1b2494b599c099dd92c..793d8eed1b902bc58456a8a9754a593717853fae 100644 (file)
@@ -58,9 +58,27 @@ typedef struct UiTextAreaArgs {
     const char *varname;
     ui_callback onchange;
     void *onchangedata;
+    const char *onchange_action;
+    ui_callback ontextchanged;
+    void *ontextchangeddata;
+    const char *ontextchanged_action;
     
     const int *states;
+    const int *visibility_states;
 } UiTextAreaArgs;
+
+typedef enum UiTextChangedEventType {
+    UI_TEXT_INSERT = 0,
+    UI_TEXT_DELETE
+} UiTextChangedEventType;
+
+typedef struct UiTextChangeEventData {
+    UiTextChangedEventType type;
+    int begin;
+    int end;
+    const char *text;
+    int length;
+} UiTextChangeEventData;
     
 typedef struct UiTextFieldArgs {
     UiBool fill;
@@ -86,8 +104,11 @@ typedef struct UiTextFieldArgs {
     void *onchangedata;
     ui_callback onactivate;
     void *onactivatedata;
+    const char *onactivate_action;
+    const char *onchange_action;
     
     const int *states;
+    const int *visibility_states;
 } UiTextFieldArgs;
 
 typedef struct UiPathElmRet {
@@ -127,6 +148,7 @@ typedef struct UiPathTextFieldArgs {
 
     ui_callback onactivate;
     void *onactivatedata;
+    const char *action;
     
     ui_callback ondragstart;
     void *ondragstartdata;
@@ -134,6 +156,8 @@ typedef struct UiPathTextFieldArgs {
     void *ondragcompletedata;
     ui_callback ondrop;
     void *ondropsdata;
+    
+    const int *visibility_states;
 } UiPathTextFieldArgs;
 
 #define ui_textarea(obj, ...) ui_textarea_create(obj, &(UiTextAreaArgs) { __VA_ARGS__ })
@@ -145,6 +169,15 @@ UIEXPORT UIWIDGET ui_textarea_gettextwidget(UIWIDGET textarea);
 UIEXPORT void ui_text_undo(UiText *value);
 UIEXPORT void ui_text_redo(UiText *value);
 
+UIEXPORT void ui_textarea_focus(UIWIDGET textarea);
+UIEXPORT void ui_textarea_set_selection(UIWIDGET textarea, int begin, int end);
+UIEXPORT void ui_textarea_select_all(UIWIDGET textarea);
+UIEXPORT void ui_textarea_set_editable(UIWIDGET textarea, UiBool editable);
+UIEXPORT UiBool ui_textarea_is_editable(UIWIDGET textarea);
+UIEXPORT void ui_textarea_set_position(UIWIDGET textarea, int pos);
+UIEXPORT int ui_textarea_get_position(UIWIDGET textarea);
+UIEXPORT void ui_textarea_scroll_to(UIWIDGET textarea, int pos);
+
 #define ui_textfield(obj, ...) ui_textfield_create(obj, &(UiTextFieldArgs) { __VA_ARGS__ })
 #define ui_frameless_textfield(obj, ...) ui_frameless_field_create(obj, &(UiTextFieldArgs) { __VA_ARGS__ })
 #define ui_passwordfield(obj, ...) ui_passwordfield_create(obj, &(UiTextFieldArgs) { __VA_ARGS__ })
@@ -155,6 +188,15 @@ UIEXPORT UIWIDGET ui_frameless_textfield_create(UiObject* obj, UiTextFieldArgs *
 UIEXPORT UIWIDGET ui_passwordfield_create(UiObject* obj, UiTextFieldArgs *args);
 
 UIEXPORT UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs *args);
+
+UIEXPORT void ui_textfield_focus(UIWIDGET textfield);
+UIEXPORT void ui_textfield_focus_without_selecting(UIWIDGET textfield);
+UIEXPORT void ui_textfield_set_selection(UIWIDGET textfield, int begin, int end);
+UIEXPORT void ui_textfield_select_all(UIWIDGET textfield);
+UIEXPORT void ui_textfield_set_editable(UIWIDGET textfield, UiBool editable);
+UIEXPORT UiBool ui_textfield_is_editable(UIWIDGET textfield);
+UIEXPORT void ui_textfield_set_position(UIWIDGET textfield, int pos);
+UIEXPORT int ui_textfield_get_position(UIWIDGET textfield);
         
 #ifdef __cplusplus
 }
index 2e230df495810275d9a65fc0313a5ff40e05224e..d52523123cf83bc732e197c999b1c37d939a4b1c 100644 (file)
@@ -42,7 +42,10 @@ typedef struct UiToolbarItemArgs {
     const char *tooltip;
 
     ui_callback onclick;
-    void* onclickdata;
+    void *onclickdata;
+    const char *action;
+    const char *accelerator;
+    const char *accelerator_text;
 
     const int *states;
     const int *visibility_states;
@@ -56,11 +59,36 @@ typedef struct UiToolbarToggleItemArgs {
     const char *varname;
     ui_callback onchange;
     void *onchangedata;
+    const char *action;
+    const char *accelerator;
+    const char *accelerator_text;
 
     const int *states;
     const int *visibility_states;
 } UiToolbarToggleItemArgs;
 
+typedef struct UiToolbarContentToggleItemArgs {
+    const char *label0;
+    const char *icon0;
+    const char *tooltip0;
+    const char *label1;
+    const char *icon1;
+    const char *tooltip1;
+
+    const char *varname;
+    ui_callback onchange;
+    void *onchangedata;
+    const char *action;
+    const char *accelerator;
+    const char *accelerator_text;
+    
+    int toggled_by_state;
+    UiBool istogglebutton;
+
+    const int *states;
+    const int *visibility_states;
+} UiToolbarContentToggleItemArgs;
+
 typedef struct UiToolbarMenuArgs {
     const char *label;
     const char *icon;
@@ -81,6 +109,7 @@ enum UiToolbarPos {
 
 #define ui_toolbar_item(name, ...) ui_toolbar_item_create(name, &(UiToolbarItemArgs){ __VA_ARGS__ } )
 #define ui_toolbar_toggleitem(name, ...) ui_toolbar_toggleitem_create(name, &(UiToolbarToggleItemArgs){ __VA_ARGS__ } )
+#define ui_toolbar_content_toggleitem(name, ...) ui_toolbar_toggleitem_create(name, &(UiToolbarToggleItemArgs){ __VA_ARGS__ } )
 
 #define ui_toolbar_menu(name, ...) for(ui_toolbar_menu_create(name, &(UiToolbarMenuArgs){ __VA_ARGS__ });ui_menu_is_open();ui_menu_close())
 #define ui_toolbar_appmenu() for(ui_toolbar_menu_create(NULL, &(UiToolbarMenuArgs){ 0 });ui_menu_is_open();ui_menu_close())
@@ -88,6 +117,7 @@ enum UiToolbarPos {
 
 UIEXPORT void ui_toolbar_item_create(const char* name, UiToolbarItemArgs *args);
 UIEXPORT void ui_toolbar_toggleitem_create(const char* name, UiToolbarToggleItemArgs *args);
+UIEXPORT void ui_toolbar_content_toggleitem_create(const char* name, UiToolbarContentToggleItemArgs *args);
 UIEXPORT void ui_toolbar_menu_create(const char* name, UiToolbarMenuArgs *args);
 
 UIEXPORT void ui_toolbar_add_default(const char *name, enum UiToolbarPos pos);
index 94c77f01b103693af936b6b2367848dfcdbd24b1..0537d58f073ec029fe8ad69f73d2d28025bab62a 100644 (file)
@@ -47,6 +47,7 @@ typedef void* UIMENU;   // NSMenu*
 
 #include <gtk/gtk.h>
 #define UIWIDGET GtkWidget*
+#define UIWINDOW void*
 
 #if UI_GTK2 || UI_GTK3
 #define UIMENU   GtkMenu*
@@ -83,6 +84,7 @@ typedef void* UIMENU;   // NSMenu*
 
 #include <Xm/XmAll.h> 
 #define UIWIDGET Widget
+#define UIWINDOW void*
 #define UIMENU   Widget
 
 
@@ -154,6 +156,13 @@ typedef struct UiWidget UiWidget;
 #define UIWINDOW UiWidget*
 #define UIMENU   void*
 
+#else
+
+#define UI_GENERIC
+#define UIWIDGET void*
+#define UIWINDOW void*
+#define UIMENU   void*
+
 #endif
 
 #ifndef TRUE
@@ -171,9 +180,9 @@ typedef struct UiWidget UiWidget;
 extern "C" {
 #endif
 
-#define UI_GROUP_SELECTION  20000
+#define UI_STATE_SELECTION  20000
 
-#define UI_GROUPS(...) (const int[]){ __VA_ARGS__, -1 }
+#define UI_STATES(...) (const int[]){ __VA_ARGS__, -1 }
     
 /* public types */
 #ifndef __cplusplus
@@ -183,7 +192,6 @@ typedef bool UiBool;
 #endif
 
 typedef struct UiObject     UiObject;
-typedef struct UiContainerX UiContainerX;
 typedef struct UiEvent      UiEvent;
 typedef struct UiMouseEvent UiMouseEvent;
 typedef struct UiObserver   UiObserver;
@@ -205,6 +213,8 @@ typedef struct UiListSelection UiListSelection;
 typedef struct UiTextStyle  UiTextStyle;
 typedef struct UiColor      UiColor;
 
+typedef enum UiEventType UiEventType;
+
 /* begin opaque types */
 typedef struct UiContext     UiContext;
 typedef struct UiContainer   UiContainer;
@@ -218,8 +228,6 @@ typedef struct UiDnD         UiDnD;
 typedef struct UiThreadpool  UiThreadpool;
 /* end opaque types */
 
-typedef struct UiTabbedPane UiTabbedPane;
-
 typedef enum UiTri {
     UI_DEFAULT = 0,
     UI_ON,
@@ -273,12 +281,10 @@ struct UiObject {
      */
     UIWIDGET    widget;
 
-#if defined(UI_COCOA) || defined(UI_WINUI)
     /*
      * native window object 
      */
     UIWINDOW    wobj;
-#endif
     
     /*
      * user window data
@@ -292,15 +298,15 @@ struct UiObject {
     
     /*
      * container list
-     * TODO: remove old UiContainer and rename UiContainerX to UiContainer
      */
-    UiContainerX *container_begin;
-    UiContainerX *container_end;
+    UiContainer *container_begin;
+    UiContainer *container_end;
     
     /*
-     * next container object
+     * called when someone requests to close the window
      */
-    UiObject    *next;
+    void (*onclose)(UiEvent *event, void *userdata);
+    void *onclosedata;
     
     /*
      * obj destroy func
@@ -313,31 +319,32 @@ struct UiObject {
     unsigned int ref;
 };
 
-struct UiTabbedPane {
-    /*
-     * native widget
-     */
-    UIWIDGET  widget;
-    
-    /*
-     * current document
-     */
-    void      *document;
-    
-    /*
-     * parent context
-     */
-    UiContext *ctx;
+enum UiEventType {
+    UI_EVENT_DATA_NULL = 0,
+    UI_EVENT_DATA_POINTER,
+    UI_EVENT_DATA_STRING,
+    UI_EVENT_DATA_INTEGER_VALUE,
+    UI_EVENT_DATA_STRING_VALUE,
+    UI_EVENT_DATA_TEXT_VALUE,
+    UI_EVENT_DATA_DOUBLE_VALUE,
+    UI_EVENT_DATA_RANGE_VALUE,
+    UI_EVENT_DATA_TEXT_CHANGED,
+    UI_EVENT_DATA_LIST_SELECTION,
+    UI_EVENT_DATA_LIST_ELM,
+    UI_EVENT_DATA_DND,
+    UI_EVENT_DATA_SUBLIST,
+    UI_EVENT_DATA_FILE_LIST,
+    UI_EVENT_DATA_TYPED_OBJECT
 };
 
 struct UiEvent {
-    UiObject *obj;
-    void     *document;
-    void     *window;
-    void     *eventdata;
-    int      eventdatatype;
-    int      intval;
-    int      set;
+    UiObject     *obj;
+    void         *document;
+    void         *window;
+    void         *eventdata;
+    UiEventType  eventdatatype;
+    int          intval;
+    int          set;
 };
 
 struct UiMouseEvent {
@@ -392,20 +399,23 @@ struct UiText {
     void  (*set)(UiText*, const char*);
     char* (*get)(UiText*);
     char* (*getsubstr)(UiText*, int, int); /* text, begin, end */
-    void  (*insert)(UiText*, int, char*);
+    void  (*insert)(UiText*, int, const char*);
+    void  (*replace)(UiText*, int, int, const char*);
     void  (*setposition)(UiText*,int);
     int   (*position)(UiText*);
+    void  (*showposition)(UiText*, int);
     void  (*setselection)(UiText*, int, int); /* text, begin, end */
     void  (*selection)(UiText*, int*, int*); /* text, begin, end */
     int   (*length)(UiText*);
     void  (*remove)(UiText*, int, int); /* text, begin, end */
+    void  (*setreadonly)(UiText*, int);
     UiStr value;
     int   pos;
+    int   readonly;
     void  *obj;
     int   datatype;
     void  *data1;
     void  *data2;
-    // TODO: replacefunc, ...
     UiObserver *observers;
 };
 
@@ -431,27 +441,33 @@ typedef void (*ui_list_destroy_func)(UiContext *ctx, UiList *list, void *userdat
  * abstract list
  */
 struct UiList {
-    /* get the first element */
+    // destructor
+    ui_list_destroy_func destroy;
+    // get the first element
     void*(*first)(UiList *list);
-    /* get the next element */
+    // get the next element
     void*(*next)(UiList *list);
-    /* get the nth element */
+    // get the nth element
     void*(*get)(UiList *list, int i);
-    /* get the number of elements */
+    // get the number of elements 
     int(*count)(UiList *list);
-    /* iterator changes after first() next() and get() */
+    // iterator changes after first() next() and get() 
     void *iter;
-    /* private - implementation dependent */
+    // private - implementation dependent
     void *data;
     
-    /* binding functions */
+    // binding functions 
     void (*update)(UiList *list, int i);
     UiListSelection (*getselection)(UiList *list);
     void (*setselection)(UiList *list, UiListSelection selection);
-    /* binding object */
+    // binding object
     void *obj;
+    // saved selection after unbind
+    UiListSelection *saved_selection;
+    // enable selection saving
+    UiBool save_selection;
     
-    /* list of observers */
+    // list of observers
     UiObserver *observers;
 };
 
@@ -492,21 +508,11 @@ typedef struct UiCondVar {
     int intdata;
 } UiCondVar;
 
-enum UiEventType {
-    UI_EVENT_DATA_NULL = 0,
-    UI_EVENT_DATA_POINTER,
-    UI_EVENT_DATA_STRING,
-    UI_EVENT_DATA_INTEGER_VALUE,
-    UI_EVENT_DATA_STRING_VALUE,
-    UI_EVENT_DATA_TEXT_VALUE,
-    UI_EVENT_DATA_DOUBLE_VALUE,
-    UI_EVENT_DATA_RANGE_VALUE,
-    UI_EVENT_DATA_LIST_SELECTION,
-    UI_EVENT_DATA_LIST_ELM,
-    UI_EVENT_DATA_DND,
-    UI_EVENT_DATA_SUBLIST,
-    UI_EVENT_DATA_FILE_LIST
-};
+// eventdata in case eventdatatype is UI_EVENT_DATA_TYPED_OBJECT
+typedef struct UiTypedObj {
+    void *ptr;
+    uint64_t type;
+} UiTypedObj;
 
 #define UI_COLOR(r, g, b) (UiColor){r, g, b}
 struct UiColor {
@@ -527,7 +533,7 @@ struct UiTextStyle {
 
 
 UIEXPORT void ui_init(const char *appname, int argc, char **argv);
-UIEXPORT const char* ui_appname();
+UIEXPORT const char* ui_appname(void);
 
 UIEXPORT void ui_add_styledata(const char *styledata, int len);
 
@@ -535,17 +541,19 @@ UIEXPORT UiContext* ui_global_context(void);
 
 UIEXPORT void ui_context_closefunc(UiContext *ctx, ui_callback fnc, void *udata);
 
-UIEXPORT void ui_context_destroy(UiContext *ctx);
-
 UIEXPORT UiContext* ui_context_parent(UiContext *ctx);
+UIEXPORT UiContext* ui_context_toplevel_parent(UiContext *ctx);
 
 UIEXPORT void ui_object_ref(UiObject *obj);
 UIEXPORT int ui_object_unref(UiObject *obj);
 
 UIEXPORT void ui_onstartup(ui_callback f, void *userdata);
+UIEXPORT void ui_onnewwindow(ui_callback f, void *userdata);
 UIEXPORT void ui_onopen(ui_callback f, void *userdata);
 UIEXPORT void ui_onexit(ui_callback f, void *userdata);
 
+UIEXPORT void ui_newwindow(void);
+
 UIEXPORT int ui_app_save_settings(void);
 UIEXPORT void ui_app_exit_on_shutdown(UiBool exitapp);
 
@@ -554,18 +562,36 @@ UIEXPORT void ui_app_quit(void);
 UIEXPORT void ui_show(UiObject *obj);
 UIEXPORT void ui_close(UiObject *obj);
 
+UIEXPORT UiObject* ui_dummy_object(void);
+
 UIEXPORT void ui_job(UiObject *obj, ui_threadfunc tf, void *td, ui_callback f, void *fd);
 UIEXPORT void ui_call_mainthread(ui_threadfunc tf, void* td);
+
+UIEXPORT void ui_buffer_mainthread_calls(UiBool enable_buffering);
+UIEXPORT void ui_exec_buffered_mainthread_calls(void);
+UIEXPORT void ui_exec_buffered_mainthread_calls_wait(int timeout);
+
 UIEXPORT UiThreadpool* ui_threadpool_create(int nthreads);
 UIEXPORT void ui_threadpool_destroy(UiThreadpool* pool);
 UIEXPORT void ui_threadpool_job(UiThreadpool* pool, UiObject* obj, ui_threadfunc tf, void* td, ui_callback f, void* fd);
 
 UIEXPORT void* ui_document_new(size_t size);
+UIEXPORT void  ui_document_ref(void *doc);
+UIEXPORT void  ui_document_unref(void *doc);
 UIEXPORT void  ui_document_destroy(void *doc);
+UIEXPORT void  ui_document_onattach(void *doc, ui_callback cb, void *data);
+UIEXPORT void  ui_document_ondetach(void *doc, ui_callback cb, void *data);
+UIEXPORT void  ui_document_onattachmentstatuschange(void *doc, ui_callback cb, void *data);
+UIEXPORT void  ui_document_onattach_action(void *doc, const char *action);
+UIEXPORT void  ui_document_ondetach_action(void *doc, const char *action);
+UIEXPORT void  ui_document_onattachmentstatuschange_action(void *doc, const char *action);
 
-UIEXPORT void* ui_get_subdocument(void *document);               // deprecated
+UIEXPORT int   ui_document_is_attached(void *doc);
+UIEXPORT int   ui_document_is_attached_to_obj(void *doc);
 
 UIEXPORT UiContext* ui_document_context(void *doc);
+UIEXPORT void* ui_context_document(UiContext *ctx);
+UIEXPORT UiObject* ui_context_obj(UiContext *ctx);
 
 UIEXPORT void* ui_context_get_document(UiContext *ctx);
 UIEXPORT void ui_context_single_attachment_mode(UiContext *ctx, UiBool enable);
@@ -576,8 +602,30 @@ UIEXPORT void ui_widget_set_states(UiContext *ctx, UIWIDGET widget, ui_enablefun
 UIEXPORT void ui_widget_set_states2(UiContext *ctx, UIWIDGET widget, ui_enablefunc enable, const int *states, int nstates);
 UIEXPORT void ui_widget_set_visibility_states(UiContext *ctx, UIWIDGET widget, const int *states, int nstates);
 
+UIEXPORT void ui_add_action(UiContext *ctx, const char *name, ui_callback callback, void *userdata);
+UIEXPORT void ui_add_action_with_accelerator(
+        UiContext *ctx,
+        const char *name,
+        ui_callback callback,
+        void *userdata,
+        const char *accelerator,
+        const char *accelerator_text);
+UIEXPORT void ui_update_action_bindings(UiContext *ctx);
+UIEXPORT int ui_call_action(UiContext *ctx, const char *action_name);
+UIEXPORT int ui_call_action2(UiContext *ctx, const char *action_name, void *eventdata, int intval);
+UIEXPORT int ui_call_action3(UiContext *ctx, const char *action_name, void *ptr, uint64_t type_id);
+UIEXPORT void ui_broadcast_action(const char *action_name);
+UIEXPORT void ui_broadcast_action2(const char *action_name, void *eventdata, int intval);
+UIEXPORT void ui_broadcast_action3(const char *action_name, void *ptr, uint64_t type_id);
+UIEXPORT void ui_mainthread_broadcast(const char *action_name);
+UIEXPORT void ui_mainthread_broadcast2(const char *action_name, void *eventdata, int intval);
+UIEXPORT void ui_mainthread_broadcast3(const char *action_name, void *ptr, uint64_t type_id);
+UIEXPORT void ui_call_action_on(UiContext *ctx, const char *action);
+
 UIEXPORT void ui_set_state(UiContext *ctx, int state);
 UIEXPORT void ui_unset_state(UiContext *ctx, int state);
+UIEXPORT void ui_suppress_state(UiContext *ctx, int state);
+UIEXPORT void ui_unsuppress_state(UiContext *ctx, int state);
 UIEXPORT int* ui_active_states(UiContext *ctx, int *nstates);
     
 UIEXPORT void* ui_allocator(UiContext *ctx);
@@ -589,6 +637,7 @@ UIEXPORT void  ui_free(UiContext *ctx, void *ptr);
 UIEXPORT void* ui_realloc(UiContext *ctx, void *ptr, size_t size);
 UIEXPORT char* ui_strdup(UiContext *ctx, const char *str);
 UIEXPORT void  ui_reg_destructor(UiContext *ctx, void *data, ui_destructor_func destr);
+UIEXPORT void  ui_remove_destructor(UiContext *ctx, void *data);
 UIEXPORT void  ui_set_destructor(void *mem, ui_destructor_func destr);
 
 // types
@@ -671,16 +720,22 @@ UIEXPORT void* ui_list_get(UiList *list, int i);
 UIEXPORT int ui_list_count(UiList *list);
 UIEXPORT void ui_list_append(UiList *list, void *data);
 UIEXPORT void ui_list_prepend(UiList *list, void *data);
+UIEXPORT void ui_list_insert(UiList *list, int index, void *data);
 UIEXPORT void ui_list_remove(UiList *list, int i);
 UIEXPORT void ui_list_clear(UiList *list);
 UIEXPORT void ui_list_update(UiList *list);
 UIEXPORT void ui_list_update_row(UiList *list, int row);
 UIEXPORT UiListSelection ui_list_get_selection(UiList *list);
+UIEXPORT void ui_list_set_selection(UiList *list, UiListSelection sel);
 UIEXPORT void ui_list_addobsv(UiList *list, ui_callback f, void *data);
 UIEXPORT void ui_list_notify(UiList *list);
+UIEXPORT void ui_list_clear_saved_selection(UiList *list);
 
-UIEXPORT UiListSelection ui_list_getselection(UiList *list);
+UIEXPORT int ui_list_getselection(UiList *list);
 UIEXPORT void ui_list_setselection(UiList *list, int index);
+UIEXPORT void ui_list_setselection2(UiList *list, int index, UiBool selection_event);
+
+UIEXPORT void ui_listselection_free(UiListSelection selection);
 
 UIEXPORT UiFileList ui_filelist_copy(UiFileList list);
 UIEXPORT void ui_filelist_free(UiFileList list);
@@ -690,16 +745,24 @@ UIEXPORT char* ui_clipboard_get();
 
 UIEXPORT void ui_add_image(char *imgname, char *filename); // TODO: remove?
 
-
-
-UIEXPORT void ui_listselection_free(UiListSelection selection);
-
+UIEXPORT char* ui_text_getsubstr(UiText *text, int begin, int end);
+UIEXPORT void  ui_text_insert(UiText *text, int pos, const char *str);
+UIEXPORT void  ui_text_replace(UiText *text, int begin, int end, const char *str);
+UIEXPORT void  ui_text_setposition(UiText *text, int pos);
+UIEXPORT int   ui_text_position(UiText *text);
+UIEXPORT void  ui_text_showposition(UiText *text, int pos);
+UIEXPORT void  ui_text_setselection(UiText *text, int begin, int end);
+UIEXPORT void  ui_text_selection(UiText *text, int *begin, int *end);
+UIEXPORT int   ui_text_length(UiText *text);
+UIEXPORT void  ui_text_remove(UiText *text, int begin, int end);
+UIEXPORT void  ui_text_setreadonly(UiText *text, int readonly);
 
 UIEXPORT UiStr ui_str(char *cstr);
 UIEXPORT UiStr ui_str_free(char *str, void (*free)(void *v));
 
 
 UIEXPORT char* ui_getappdir(void);
+UIEXPORT void ui_setappdir(const char *path);
 UIEXPORT char* ui_configfile(const char *name);
 
 UIEXPORT UiCondVar* ui_condvar_create(void);
@@ -711,10 +774,13 @@ UIEXPORT void ui_setop_enable(int set);
 UIEXPORT int ui_get_setop(void);
 UIEXPORT void ui_onchange_events_enable(UiBool enable);
 UIEXPORT UiBool ui_onchange_events_is_enabled(void);
+UIEXPORT void ui_selection_events_enable(UiBool enable);
+UIEXPORT UiBool ui_selection_events_is_enabled(void);
 
     
 UIEXPORT void ui_global_list_initializer(ui_list_init_func func, void *userdata);
 UIEXPORT void ui_global_list_destructor(ui_list_destroy_func func, void *userdata);
+UIEXPORT void ui_list_class_set_destructor(UiList *list, ui_list_destroy_func destroy);
 UIEXPORT void ui_list_class_set_first(UiList *list, void*(*first)(UiList *list));
 UIEXPORT void ui_list_class_set_next(UiList *list, void*(*next)(UiList *list));
 UIEXPORT void ui_list_class_set_get(UiList *list, void*(*get)(UiList *list, int i));
@@ -725,6 +791,11 @@ UIEXPORT void ui_list_class_set_iter(UiList *list, void *iter);
 UIEXPORT void ui_object_set(UiObject *obj, const char *key, void *data);
 UIEXPORT void* ui_object_get(UiObject *obj, const char *key);
 
+UIEXPORT void ui_app_ref(void);
+UIEXPORT void ui_app_unref(void);
+
+UIEXPORT void ui_open_uri(const char *uri);
+
 #ifdef __cplusplus
 }
 #endif
index d5a243ddb9d48aca1ddb928e42684dde547952f1..65ca1392036b67717490d808ff135ecce8d36d15 100644 (file)
@@ -69,6 +69,7 @@ typedef struct UiWebviewArgs {
     const char *varname;
     
     const int* states;
+    const int *visibility_states;
 } UiWebviewArgs;
 
 #define ui_webview(obj, ...) ui_webview_create(obj, &(UiWebviewArgs){ __VA_ARGS__ } )
index 40503baa2fb88e61111eced55a096b768f5a4bc5..62c5c6341d6e9f65008a080826f9e7a0e12c4757 100644 (file)
@@ -52,6 +52,8 @@ typedef struct UiWidgetArgs {
     const char *style_class;
 } UiWidgetArgs;
 
+#ifndef UI_GENERIC
+
 #ifdef UI_GTK
 typedef UIWIDGET (*ui_createwidget_func)(UiObject *obj, UiWidgetArgs *args, void *userdata);
 #elif defined(UI_QT)
@@ -71,6 +73,7 @@ UIEXPORT UIWIDGET ui_customwidget_create(UiObject *obj, ui_createwidget_func cre
 
 #define ui_customwidget(obj, create_widget, userdata, ...) ui_customwidget_create(obj, create_widget, userdata, &(UiWidgetArgs) { __VA_ARGS__ })
 
+#endif
 
 UIEXPORT UIWIDGET ui_separator_create(UiObject *obj, UiWidgetArgs *args);