]> uap-core.de Git - note.git/commitdiff
update toolkit
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 21 Apr 2025 17:33:52 +0000 (19:33 +0200)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Mon, 21 Apr 2025 17:33:52 +0000 (19:33 +0200)
16 files changed:
ui/cocoa/EventData.h
ui/cocoa/MainWindow.h
ui/cocoa/MainWindow.m
ui/cocoa/button.m
ui/cocoa/menu.h
ui/cocoa/menu.m
ui/cocoa/window.m
ui/qt/list.cpp [new file with mode: 0644]
ui/qt/list.h [new file with mode: 0644]
ui/qt/model.cpp
ui/qt/model.h
ui/qt/qt5.pro
ui/qt/text.cpp
ui/qt/toolbar.cpp
ui/qt/toolbar.h
ui/qt/window.cpp

index 8da0ee44c6ad80a747642af112e87bfaff984726..4ee89f3e11e512b842e669f2acb6cc403c5c5e3f 100644 (file)
@@ -47,6 +47,5 @@ typedef void(*get_eventdata_func)(id sender, UiVar *var, void **eventdata, int *
 
 - (void)handleEventWithEventData:(id)sender;
 
-- (SEL)addDynamicMethod:(unsigned long long)method_id;
-
 @end
+
index 50e2eefd91f34c37a4f5208e2b9156f9951254d7..aab8a700e412ce1352792f7cf843e4ab44b57474 100644 (file)
 
 @interface MainWindow : NSWindow
 
+- (MainWindow*)init:(UiObject*)obj;
+
+@end
+
+
+@interface MainWindowController : NSWindowController<NSMenuItemValidation>
+
 @property UiObject *uiobj;
+@property NSMutableDictionary *checkItemStates;
+@property NSMutableDictionary *radioItems;
 
-- (MainWindow*)init:(UiObject*)obj;
+- (MainWindowController*)initWithWindow:(UiObject*)obj window:(NSWindow*)window;
+
+- (void) windowDidLoad;
 
+- (void)menuItemAction:(id)sender;
+
+- (BOOL) validateMenuItem:(NSMenuItem *) menuItem;
+
+@end
+
+@interface MenuItemState : NSObject
+@property (weak) MainWindowController *mainWindow;
+@property UiVar *var;
+@property int state;
 @end
+
+
+int64_t ui_menu_check_item_get(UiInteger *i);
+void ui_menu_check_item_set(UiInteger *i, int64_t value);
+
+int64_t ui_menu_radio_item_get(UiInteger *i);
+void ui_menu_radio_item_set(UiInteger *i, int64_t value);
index 232f93ff1b2d3e5e28ec1ce2390ebf55ff10873a..27f34fdcae6986701cce4a93c465dfb19c9be0a9 100644 (file)
 #import "Container.h"
 #import "GridLayout.h"
 #import "../common/object.h"
+#import <objc/runtime.h>
+
+#import "EventData.h"
+#import "menu.h"
 
 @implementation MainWindow
 
 - (MainWindow*)init:(UiObject*)obj {
-    self.uiobj = obj;
     NSRect frame = NSMakeRect(300, 200, 600, 500);
     
     self = [self initWithContentRect:frame
 }
 
 @end
+
+
+
+@implementation MainWindowController
+
+- (MainWindowController*)initWithWindow:(UiObject*)obj window:(NSWindow*)window {
+    self = [super initWithWindow:window];
+    _uiobj = obj;
+    
+    self.checkItemStates = [[NSMutableDictionary alloc] init];
+    self.radioItems = [[NSMutableDictionary alloc] init];
+    
+    // bind all stateful menu items (checkbox, radiobuttons, lists)
+    NSArray *menuBindItems = ui_get_binding_items(); // returns all items that require binding
+    for(MenuItem *item in menuBindItems) {
+        if(item.checkItem || item.radioItem) {
+            // simple check item (ui_menu_toggleitem_create)
+            UiVar *var = uic_widget_var(obj->ctx, obj->ctx, NULL, item.checkItem ? item.checkItem->varname : item.radioItem->varname, UI_VAR_INTEGER);
+            // create the state object for this item/window
+            MenuItemState *state = [[MenuItemState alloc] init];
+            state.mainWindow = self;
+            state.var = var;
+            if(var) {
+                UiInteger *i = var->value;
+                if(item.checkItem) {
+                    // bind toggle item
+                    state.state = (int)i->value;
+                    i->obj = (__bridge void*)state;
+                    i->get = ui_menu_check_item_get;
+                    i->set = ui_menu_check_item_set;
+                } else {
+                    // bind radio item
+                    NSMutableArray *rgroup = nil;
+                    if(i->obj) {
+                        rgroup = (__bridge NSMutableArray*)i->obj;
+                    } else {
+                        // create a new rgroup array and register it in the window
+                        rgroup = [[NSMutableArray alloc] init];
+                        NSString *varname = [[NSString alloc] initWithUTF8String:item.radioItem->varname];
+                        [_radioItems setObject:rgroup forKey:varname];
+                        i->obj = (__bridge void*)rgroup;
+                    }
+                    i->get = ui_menu_radio_item_get;
+                    i->set = ui_menu_radio_item_set;
+                    [rgroup addObject:state]; // add this item state to the radio group
+                    // i->value can contain a non-zero value, which means a specific radiobutton
+                    // should be pre-selected
+                    if(i->value == rgroup.count) {
+                        state.state = NSControlStateValueOn;
+                    }
+                }
+            } else {
+                state.state = 0;
+            }
+            [_checkItemStates setObject:state forKey:item.itemId];
+        }
+    }
+    
+    return self;
+}
+
+- (void) windowDidLoad {
+    [self.window setNextResponder:self];
+}
+
+- (void)menuItemAction:(id)sender {
+    EventData *event = objc_getAssociatedObject(sender, "eventdata");
+    if(event) {
+        event.obj = self.uiobj; // temporary set the event object
+        [event handleEvent:sender];
+    }
+}
+
+- (void)menuCheckItemAction:(id)sender {
+    NSMenuItem *menuItem = sender;
+    MenuItem *item = objc_getAssociatedObject(sender, "menuitem");
+    if(!item || !item.checkItem) {
+        return;
+    }
+    
+    MenuItemState *state = [_checkItemStates objectForKey:item.itemId];
+    state.state = state.state == NSControlStateValueOff ? NSControlStateValueOn : NSControlStateValueOff;
+    menuItem.state = state.state;
+    
+    UiMenuCheckItem *it = item.checkItem;
+    if(it->callback) {
+        UiEvent event;
+        event.obj = _uiobj;
+        event.window = event.obj->window;
+        event.document = event.obj->ctx->document;
+        event.eventdata = state.var ? state.var->value : NULL;
+        event.intval = state.state;
+        it->callback(&event, it->userdata);
+    }
+}
+
+- (void)menuRadioItemAction:(id)sender {
+    NSMenuItem *menuItem = sender;
+    MenuItem *item = objc_getAssociatedObject(sender, "menuitem");
+    if(!item || !item.radioItem) {
+        return;
+    }
+    
+    UiMenuRadioItem *it = item.radioItem;
+    if(!it->varname) {
+        return;
+    }
+    
+    MenuItemState *state = [_checkItemStates objectForKey:item.itemId]; // current state of this menu item
+    
+    NSString *varname = [[NSString alloc] initWithUTF8String:it->varname];
+    NSArray *radioGroup = [_radioItems objectForKey:varname];
+    if(!radioGroup) {
+        return;
+    }
+    int index = 1;
+    int value = 0;
+    for(MenuItemState *g in radioGroup) {
+        if(g == state) {
+            menuItem.state = NSControlStateValueOn;
+            g.state = NSControlStateValueOn;
+            value = index;
+        } else {
+            menuItem.state = NSControlStateValueOff;
+            g.state = NSControlStateValueOff;
+        }
+    }
+    
+    if(it->callback) {
+        UiEvent event;
+        event.obj = _uiobj;
+        event.window = event.obj->window;
+        event.document = event.obj->ctx->document;
+        event.eventdata = state.var ? state.var->value : NULL;
+        event.intval = value;
+        it->callback(&event, it->userdata);
+    }
+}
+
+
+- (BOOL) validateMenuItem:(NSMenuItem *) menuItem {
+    MenuItem *item = objc_getAssociatedObject(menuItem, "menuitem");
+    if(item) {
+        MenuItemState *state = [_checkItemStates objectForKey:item.itemId];
+        if(state) {
+            menuItem.state = state.state;
+        } else {
+            menuItem.state = NSControlStateValueOff;
+        }
+    }
+    
+    return YES;
+}
+
+@end
+
+@implementation MenuItemState
+
+@end
+
+int64_t ui_menu_check_item_get(UiInteger *i) {
+    MenuItemState *state = (__bridge MenuItemState*)i->obj;
+    i->value = state.state;
+    return i->value;
+}
+
+void ui_menu_check_item_set(UiInteger *i, int64_t value) {
+    MenuItemState *state = (__bridge MenuItemState*)i->obj;
+    i->value = value;
+    state.state = (int)value;
+}
+
+int64_t ui_menu_radio_item_get(UiInteger *i) {
+    NSArray *rgroup = (__bridge NSArray*)i->obj;
+    i->value = 0;
+    int index = 1;
+    for(MenuItemState *state in rgroup) {
+        if(state.state == NSControlStateValueOn) {
+            i->value = index;
+            break;
+        }
+        index++;
+    }
+    return i->value;
+}
+
+void ui_menu_radio_item_set(UiInteger *i, int64_t value) {
+    NSArray *rgroup = (__bridge NSArray*)i->obj;
+    i->value = 0;
+    int index = 1;
+    for(MenuItemState *state in rgroup) {
+        state.state = value == index;
+        index++;
+    }
+}
index cd2f245da5279d38ccf069b0d3cdf3b2bfe6ddbf..e819fb05ece5eaf3f7b79ef38a7f1d3d9124f892 100644 (file)
@@ -252,17 +252,17 @@ int64_t ui_radiobuttons_get(UiInteger *i) {
     int64_t index = 0;
     for(UiRadioButton *b in buttons) {
         if([b cell].state != 0) {
-            i->value = index;
+            i->value = index + 1;
             break;
         }
         index++;
     }
-    return index;
+    return i->value;
 }
 
 void ui_radiobuttons_set(UiInteger *i, int64_t value) {
     NSMutableArray *buttons = (__bridge NSMutableArray*)i->obj;
-    int64_t index = 0;
+    int64_t index = 1;
     for(UiRadioButton *b in buttons) {
         if(index == value) {
             [b cell].state = NSControlStateValueOn;
@@ -271,5 +271,4 @@ void ui_radiobuttons_set(UiInteger *i, int64_t value) {
         }
         index++;
     }
-    return index;
 }
index 9836fa32d4e9504b6ddaf602e2bf1e3fc05e0a45..be58c9f46e1650e3ab02e9081438281f5a35a60a 100644 (file)
 
 #import "../common/menu.h"
 
+@interface MenuItem : NSObject
+
+@property (strong) NSString *itemId;
+@property UiMenuCheckItem *checkItem;
+@property UiMenuRadioItem *radioItem;
+@property ui_callback     callback;
+@property void            *userdata;
+
+- (MenuItem*)init:(int)itId;
+
+@end
+
 void ui_menu_init(void);
 
 typedef void(*ui_menu_add_f)(NSMenu*, int, UiMenuItemI*);
@@ -42,3 +54,5 @@ void add_checkitem_widget(NSMenu *parent, int i, UiMenuItemI *item);
 void add_radioitem_widget(NSMenu *parent, int index, UiMenuItemI *item);
 void add_checkitemnv_widget(NSMenu *parent, int i, UiMenuItemI *item);
 void add_menuitem_list_widget(NSMenu *parent, int i, UiMenuItemI *item);
+
+NSArray* ui_get_binding_items(void);
index 10dd588d29f65f2df8322c151e2d06459b7d6758..5395d0ad9b04ec1b7668f5e3682135db456556b0 100644 (file)
 #import <stdlib.h>
 #import <string.h>
 #import <stdarg.h>
+#import <objc/runtime.h>
 
 #import "menu.h"
 #import "window.h"
+#import "EventData.h"
+
+#pragma GCC diagnostic ignored "-Wundeclared-selector"
+#pragma clang diagnostic ignored "-Wundeclared-selector"
+
+// holds all items that need bindings
+// value type: MenuItem*
+static NSMutableArray *bindingItems;
+
+@implementation MenuItem
+
+- (MenuItem*)init:(int)itId {
+    self.itemId = [[NSString alloc] initWithFormat:@"item%d", itId];
+    return self;
+}
+
+@end
 
 static ui_menu_add_f createMenuItem[] = {
     /* UI_MENU                 */ add_menu_widget,
@@ -67,20 +85,51 @@ void add_menu_widget(NSMenu *parent, int i, UiMenuItemI *item) {
 
 void add_menuitem_widget(NSMenu *parent, int i, UiMenuItemI *item) {
     UiMenuItem *it = (UiMenuItem*)item;
+    
     NSString *str = [[NSString alloc] initWithUTF8String:it->label];
-    NSMenuItem *menuItem = [parent addItemWithTitle:str action:nil keyEquivalent:@""];
+    NSMenuItem *menuItem = [parent addItemWithTitle:str action:@selector(menuItemAction:) keyEquivalent:@""];
+    
+    if(it->callback) {
+        EventData *event = [[EventData alloc] init:it->callback userdata:it->userdata];
+        objc_setAssociatedObject(menuItem, "eventdata", event, OBJC_ASSOCIATION_RETAIN);
+    }
 }
 
 void add_menuseparator_widget(NSMenu *parent, int i, UiMenuItemI *item) {
-    
+    NSMenuItem *menuItem = [NSMenuItem separatorItem];
+    [parent addItem:menuItem];
 }
 
+static int nItem = 0;
+
 void add_checkitem_widget(NSMenu *parent, int i, UiMenuItemI *item) {
+    UiMenuCheckItem *it = (UiMenuCheckItem*)item;
+    
+    NSString *str = [[NSString alloc] initWithUTF8String:it->label];
+    NSMenuItem *menuItem = [parent addItemWithTitle:str action:@selector(menuCheckItemAction:) keyEquivalent:@""];
     
+    MenuItem *mItem = [[MenuItem alloc] init:nItem++];
+    mItem.callback = it->callback;
+    mItem.userdata = it->userdata;
+    mItem.checkItem = it;
+    
+    objc_setAssociatedObject(menuItem, "menuitem", mItem, OBJC_ASSOCIATION_RETAIN);
+    [bindingItems addObject:mItem];
 }
 
 void add_radioitem_widget(NSMenu *parent, int index, UiMenuItemI *item) {
+    UiMenuRadioItem *it = (UiMenuRadioItem*)item;
+    
+    NSString *str = [[NSString alloc] initWithUTF8String:it->label];
+    NSMenuItem *menuItem = [parent addItemWithTitle:str action:@selector(menuRadioItemAction:) keyEquivalent:@""];
     
+    MenuItem *mItem = [[MenuItem alloc] init:nItem++];
+    mItem.callback = it->callback;
+    mItem.userdata = it->userdata;
+    mItem.radioItem = it;
+    
+    objc_setAssociatedObject(menuItem, "menuitem", mItem, OBJC_ASSOCIATION_RETAIN);
+    [bindingItems addObject:mItem];
 }
 
 void add_checkitemnv_widget(NSMenu *parent, int i, UiMenuItemI *item) {
@@ -93,17 +142,25 @@ void add_menuitem_list_widget(NSMenu *parent, int i, UiMenuItemI *item) {
 
 
 void ui_menu_init(void) {
+    bindingItems = [[NSMutableArray alloc] init];
+    
     UiMenu *menus_begin = uic_get_menu_list();
     UiMenu *ls = menus_begin;
+    int index = 1;
     while(ls) {
         if(ls->item.type == UI_MENU) {
             NSString *str = [[NSString alloc] initWithUTF8String:ls->label];
             NSMenu *menu = [[NSMenu alloc] initWithTitle: str];
-            NSMenuItem *menuItem = [[NSApp mainMenu] addItemWithTitle:str action:nil keyEquivalent:@""];
+            NSMenuItem *menuItem = [[NSApp mainMenu] insertItemWithTitle:str action:nil keyEquivalent:@"" atIndex:index];
             [[NSApp mainMenu] setSubmenu:menu forItem:menuItem];
             
             add_menu_items(menu, 0, ls);
         }
         ls = (UiMenu*)ls->item.next;
+        index++;
     }
 }
+
+NSArray* ui_get_binding_items(void) {
+    return bindingItems;
+}
index a04537eac47c4b8434828418e5be0a864eec9533..8e2c81f7deb16f074327f9f94add72753ffa4ca1 100644 (file)
@@ -31,6 +31,8 @@
 #import "MainWindow.h"
 #import "WindowManager.h"
 
+#import <objc/runtime.h>
+
 #include "../ui/window.h"
 #include "../ui/properties.h"
 #include "../common/context.h"
@@ -39,6 +41,7 @@
 
 #include <cx/mempool.h>
 
+
 static UiObject* create_window(const char *title, BOOL simple) {
     CxMempool *mp = cxMempoolCreateSimple(256);
     UiObject *obj = cxCalloc(mp->allocator, 1, sizeof(UiObject));
@@ -52,6 +55,11 @@ static UiObject* create_window(const char *title, BOOL simple) {
     
     obj->wobj = (__bridge void*)window;
     
+    MainWindowController *controller = [[MainWindowController alloc] initWithWindow:obj window:window];
+    window.windowController = controller;
+    [window setNextResponder:(NSResponder*)controller];
+    objc_setAssociatedObject(window, "windowcontroller", controller, OBJC_ASSOCIATION_RETAIN);
+    
     return obj;
 }
 
diff --git a/ui/qt/list.cpp b/ui/qt/list.cpp
new file mode 100644 (file)
index 0000000..3253ca7
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2014 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "list.h"
+#include "container.h"
+
+#include <QTreeView>
+#include <QTreeWidgetItem>
+#include <QListView>
+
+extern "C" void* ui_strmodel_getvalue(void *elm, int column) {
+    return column == 0 ? elm : NULL;
+}
+
+
+UIWIDGET ui_listview_create(UiObject* obj, UiListArgs args) {
+    UiContainerPrivate *ctn = ui_obj_container(obj);
+    UI_APPLY_LAYOUT(ctn->layout, args);
+    
+    QListView *view = new QListView();
+    
+    ui_getvaluefunc getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue;
+    UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.list, args.varname, UI_VAR_LIST);
+    
+    ListModel *model = new ListModel(obj, view, var, getvalue);
+    view->setModel(model);
+    
+    if(var) {
+        UiList *list = (UiList*)var->value;
+        list->update = ui_listmodel_update;
+        list->getselection = ui_listmodel_getselection;
+        list->setselection = ui_listmodel_setselection;
+        list->obj = model;
+    }
+    
+    model->setActivationCallback(args.onactivate, args.onactivatedata);
+    model->setSelectionCallback(args.onselection, args.onselectiondata);
+    
+    QItemSelectionModel *s = view->selectionModel();
+    QObject::connect(
+            s,
+            SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
+            model,
+            SLOT(selectionChanged(const QItemSelection &, const QItemSelection &)));
+    
+    
+    ctn->add(view, false);
+    
+    return view;
+}
diff --git a/ui/qt/list.h b/ui/qt/list.h
new file mode 100644 (file)
index 0000000..664b32b
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2014 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef TREE_H
+#define        TREE_H
+
+#include "../ui/tree.h"
+#include "model.h"
+
+#include <QTableView>
+
+
+
+#endif /* TREE_H */
+
index d6ead680948420d752471852ee67d88766c39c1e..1ac457489be406ede8c0c8eceee6d65e9eb1149a 100644 (file)
 
 #include "model.h"
 
+
+ListModel::ListModel(UiObject *obj, QListView *view, UiVar *var, ui_getvaluefunc getvalue){
+    this->obj = obj;
+    this->view = view;
+    this->var = var;
+    this->getvalue = getvalue;
+    this->onactivate = nullptr;
+    this->onactivatedata = nullptr;
+    this->onselection = nullptr;
+    this->onselectiondata = nullptr;
+}
+
+void ListModel::setActivationCallback(ui_callback f, void *userdata) {
+    onactivate = f;
+    onactivatedata = userdata;
+}
+
+void ListModel::setSelectionCallback(ui_callback f, void *userdata) {
+    onselection = f;
+    onselectiondata = userdata;
+}
+
+void ListModel::update(int row) {
+    if(row >= 0) {
+        this->update(row);
+    } else {
+        this->beginResetModel();
+        this->endResetModel();
+    }
+}
+
+int ListModel::rowCount(const QModelIndex& parent) const {
+    UiList *list = (UiList*)var->value;
+    return ui_list_count(list);
+}
+
+QVariant ListModel::data(const QModelIndex &index, int role) const {
+    if(role == Qt::DisplayRole) {
+        UiList *ls = (UiList*)var->value;
+        void *rowData = ls->get(ls, index.row());
+        if(rowData && getvalue) {
+            void *value = getvalue(rowData, 0);
+            return QString::fromUtf8((char*)value); 
+        }
+    }
+    return QVariant();
+}
+
+void ListModel::selectionChanged(const QItemSelection& selected, const QItemSelection& deselected) {
+    UiListSelection sel = ui_selection_model_to_selection(view->selectionModel());
+    
+    UiEvent event;
+    event.obj = obj;
+    event.window = obj->window;
+    event.document = obj->ctx->document;
+    event.eventdata = &sel;
+    event.intval = sel.count;
+    event.set = ui_get_setop();
+    
+    if(onactivate) {
+        onactivate(&event, onactivatedata);
+    }
+    if(onselection) {
+        onselection(&event, onselectiondata);
+    }
+    
+    free(sel.rows);
+}
+
+
+
+
+UiListSelection ui_selection_model_to_selection(QItemSelectionModel *model) {
+    UiListSelection sel;
+    sel.rows = NULL;
+    sel.count = 0;
+    
+    if(model->hasSelection()) {
+        QModelIndexList indices = model->selectedIndexes();
+        sel.count = indices.count();
+        sel.rows = (int*)calloc(sel.count, sizeof(int));
+        
+        int i = 0;
+        for (const QModelIndex &index : indices) {
+            sel.rows[i++] = index.row();
+        }
+    }
+    
+    return sel;
+}
+
+/* ---------------------- UiList implementation -----------------------------*/
+
+void ui_listmodel_update(UiList *list, int row) {
+    ListModel *model = (ListModel*)list->obj;
+    model->update(row);
+}
+
+void ui_listmodel_setselection(UiList *list, UiListSelection sel) {
+    ListModel *model = (ListModel*)list->obj;
+    QItemSelection selection;
+    for (int i=0;i<sel.count;i++) {
+        QModelIndex index = model->index(sel.rows[i]);
+        selection.select(index, index);
+    }
+    model->view->selectionModel()->select(selection, QItemSelectionModel::ClearAndSelect);
+}
+
+UiListSelection ui_listmodel_getselection(UiList *list) {
+    ListModel *model = (ListModel*)list->obj;
+    return ui_selection_model_to_selection(model->view->selectionModel());
+}
index d9a707d6932daeac5029688ca211f9c7e1c4853d..e2c2e594ad319ce5e445b439c5593f43f0f2d90d 100644 (file)
 #include <QItemSelectionModel>
 
 
+
+class ListModel : public QAbstractListModel {
+    Q_OBJECT
+    
+    ui_getvaluefunc getvalue;
+    ui_callback onactivate;
+    void        *onactivatedata;
+    ui_callback onselection;
+    void        *onselectiondata;
+    
+public:
+    UiObject    *obj;
+    UiVar       *var;
+    QListView   *view;
+    
+    ListModel(UiObject *obj, QListView *view, UiVar *var, ui_getvaluefunc getvalue);
+    
+    void setActivationCallback(ui_callback f, void *userdata);
+    void setSelectionCallback(ui_callback f, void *userdata);
+    
+    void update(int row);
+    
+    int rowCount(const QModelIndex &parent = QModelIndex()) const;
+    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
+    
+public slots:
+    void selectionChanged(
+        const QItemSelection & selected,
+        const QItemSelection & deselected);
+};
+
+
+UiListSelection ui_selection_model_to_selection(QItemSelectionModel *model);
+
+extern "C" {
+    
+    void ui_listmodel_update(UiList *list, int row);
+    void ui_listmodel_setselection(UiList *list, UiListSelection sel);
+    UiListSelection ui_listmodel_getselection(UiList *list);
+
+}
+
 #endif /* MODEL_H */
 
index 5971c329bc7fb0a60282cf95c4687955b4f26146..a97ef1cfb3252a6b8c26cddbf2b1be020a0fabd2 100644 (file)
@@ -45,7 +45,7 @@ SOURCES += stock.cpp
 SOURCES += container.cpp
 SOURCES += text.cpp
 SOURCES += model.cpp
-SOURCES += tree.cpp
+SOURCES += list.cpp
 SOURCES += button.cpp
 SOURCES += label.cpp
 SOURCES += graphics.cpp
@@ -60,7 +60,7 @@ HEADERS += stock.h
 HEADERS += container.h
 HEADERS += text.h
 HEADERS += model.h
-HEADERS += tree.h
+HEADERS += list.h
 HEADERS += button.h
 HEADERS += label.h
 HEADERS += graphics.h
index f900ac0bbd0e2f105d2a42d637bfb9497e9bb891..fb3f6567621ff4c6c5865e92a0ac4822782c9467 100644 (file)
@@ -201,7 +201,11 @@ int ui_textarea_length(UiText *text) {
 }
 
 void ui_textarea_remove(UiText *text, int begin, int end) {
-    // TODO
+    QTextDocument *doc = (QTextDocument*)text->data1;
+    QTextCursor cursor(doc);
+    cursor.setPosition(begin);
+    cursor.setPosition(end, QTextCursor::KeepAnchor);
+    cursor.removeSelectedText();
 }
 
 /* ------------------------------ TextField ------------------------------ */
index 11285856d525bc8536698a5ec7221d20c1f0e656..22e81ded0fbcf7d65a5d783acf1aab3c71106056 100644 (file)
 #include "menu.h"
 #include "stock.h"
 
+static void add_items(UiObject *obj, QToolBar *toolbar, CxList *defaults, CxMap *items);
+static void create_item(UiObject *obj, QToolBar *toolbar, UiToolbarItemI *i);
+
+QToolBar* ui_create_toolbar(UiObject *obj) {
+    CxMap *items = uic_get_toolbar_items();
+    CxList *left_defaults = uic_get_toolbar_defaults(UI_TOOLBAR_LEFT);
+    CxList *center_defaults = uic_get_toolbar_defaults(UI_TOOLBAR_CENTER);
+    CxList *right_defaults = uic_get_toolbar_defaults(UI_TOOLBAR_RIGHT);
+    
+    if(!items || cxMapSize(items) == 0) {
+        return nullptr;
+    }
+    
+    QToolBar *toolbar = new QToolBar();
+    add_items(obj, toolbar, left_defaults, items);
+    add_items(obj, toolbar, center_defaults, items);
+    add_items(obj, toolbar, right_defaults, items);
+    
+    
+    return toolbar;
+}
+
+static void add_items(UiObject *obj, QToolBar *toolbar, CxList *defaults, CxMap *items) {
+    CxIterator i = cxListIterator(defaults);
+    cx_foreach(char *, name, i) {
+        UiToolbarItemI *item = (UiToolbarItemI*)cxMapGet(items, name);
+        if(item) {
+            create_item(obj, toolbar, item);
+        } else {
+            fprintf(stderr, "UI Error: unknown toolbar item '%s'\n", name);
+        }
+    }
+}
+
+static void create_item(UiObject *obj, QToolBar *toolbar, UiToolbarItemI *i) {
+    switch(i->type) {
+        case UI_TOOLBAR_ITEM: {
+            ui_toolbar_add_item(obj, toolbar, (UiToolbarItem*)i);
+            break;
+        }
+        case UI_TOOLBAR_TOGGLEITEM: {
+            ui_toolbar_add_toggleitem(obj, toolbar, (UiToolbarToggleItem*)i);
+            break;
+        }
+        case UI_TOOLBAR_MENU: {
+            ui_toolbar_add_menu(obj, toolbar, (UiToolbarMenuItem*)i);
+            break;
+        }
+        default: fprintf(stderr, "toolbar item type unimplemented: %d\n", (int)i->type);
+    }
+}
+
+void ui_toolbar_add_item(UiObject *obj, QToolBar *toolbar, UiToolbarItem *item) {
+    QAction *action = new QAction();
+    if(item->args.label) {
+        action->setText(item->args.label);
+    }
+    if(item->args.icon) {
+        action->setIcon(QIcon::fromTheme(item->args.icon));
+    }
+    toolbar->addAction(action);
+    
+    UiEventWrapper *event = new UiEventWrapper(obj, item->args.onclick, item->args.onclickdata);
+    action->connect(action, SIGNAL(triggered()), event, SLOT(slot()));
+    action->connect(action, SIGNAL(destroyed()), event, SLOT(destroy()));
+}
+
+static void toolbar_togglebutton_event(UiEvent *event, UiEventWrapper *wrapper) {
+    QAction *action = (QAction*)wrapper->customdata1;
+    event->intval = action->isChecked();
+    if(wrapper->var) {
+        event->eventdata = wrapper->var->value;
+    }
+}
+
+void ui_toolbar_add_toggleitem(UiObject *obj, QToolBar *toolbar, UiToolbarToggleItem *item) {
+    QAction *action = new QAction();
+    action->setCheckable(true);
+    if(item->args.label) {
+        action->setText(item->args.label);
+    }
+    if(item->args.icon) {
+        action->setIcon(QIcon::fromTheme(item->args.icon));
+    }
+    toolbar->addAction(action);
+    
+    UiVar* var = uic_widget_var(obj->ctx, obj->ctx, nullptr, item->args.varname, UI_VAR_INTEGER);
+    UiEventWrapper *event = new UiEventWrapper(obj, item->args.onchange, item->args.onchangedata);
+    event->var = var;
+    event->customdata1 = action;
+    event->prepare_event = toolbar_togglebutton_event;
+    action->connect(action, SIGNAL(triggered()), event, SLOT(slot()));
+    action->connect(action, SIGNAL(destroyed()), event, SLOT(destroy()));
+}
+
+void ui_toolbar_add_menu(UiObject *obj, QToolBar *toolbar, UiToolbarMenuItem *item) {
+    
+}
index 7a4dc2a14c86ed44175de93e3ca27aa5deb68cf4..749e84f7bbef12d819f46079cc5b0b4dad254cb1 100644 (file)
 
 #include "toolkit.h"
 #include "../ui/toolbar.h"
+#include "../common/toolbar.h"
 #include <QToolBar>
 
+QToolBar* ui_create_toolbar(UiObject *obj);
 
-
+void ui_toolbar_add_item(UiObject *obj, QToolBar *toolbar, UiToolbarItem *item);
+void ui_toolbar_add_toggleitem(UiObject *obj, QToolBar *toolbar, UiToolbarToggleItem *item);
+void ui_toolbar_add_menu(UiObject *obj, QToolBar *toolbar, UiToolbarMenuItem *item);
 
 #endif /* TOOLBAR_H */
 
index a30dc6bf31aa37074fb790be8be74225d0fd56b6..bab1fa6d3ebd50df82df03905f07eee1cf9d16c0 100644 (file)
@@ -51,8 +51,10 @@ static UiObject* create_window(const char *title, void *window_data, bool simple
     
     if(!simple) {
         ui_add_menus(obj, window);
-        //QToolBar *toolbar = ui_create_toolbar(obj);
-        //window->addToolBar(Qt::TopToolBarArea, toolbar);
+        QToolBar *toolbar = ui_create_toolbar(obj);
+        if(toolbar) {
+            window->addToolBar(Qt::TopToolBarArea, toolbar);
+        }
     }
     
     QBoxLayout *box = new QVBoxLayout();