]> uap-core.de Git - note.git/commitdiff
add ui for note list / content
authorOlaf Wintermann <olaf.wintermann@gmail.com>
Wed, 5 Feb 2025 22:14:27 +0000 (23:14 +0100)
committerOlaf Wintermann <olaf.wintermann@gmail.com>
Wed, 5 Feb 2025 22:14:27 +0000 (23:14 +0100)
application/window.c
ui/cocoa/EventData.h
ui/cocoa/EventData.m
ui/cocoa/MainWindow.m
ui/cocoa/button.h
ui/cocoa/button.m
ui/gtk/container.c
ui/gtk/container.h
ui/ui/button.h
ui/ui/container.h

index d44a15e1357dd0764aa32c5ce0faa511afb41cd9..4e97ed9dcc2613536757261deb4b623c8ad5f407 100644 (file)
@@ -45,6 +45,21 @@ void window_create() {
         }
     }
     
+    ui_hsplitpane(obj, .initial_position = 200) {
+        // splitpane left: table
+        UiModel* model = ui_model(obj->ctx, UI_STRING, "Name", UI_STRING_FREE, "Last Modified", -1);
+        ui_table(obj, .model = model, .varname = "notes");
+        
+        // splitpane right: content
+        ui_grid(obj, .columnspacing = 10, .rowspacing = 10) {
+            ui_label(obj, .label = "Title");
+            ui_textfield(obj, .varname = "note_title", .hexpand = TRUE);
+            ui_newline(obj);
+            
+            ui_textarea(obj, .varname = "note_content", .vfill = TRUE, .hfill = TRUE, .hexpand = TRUE, .vexpand = TRUE, .colspan = 2);
+        }
+    }
+    
     ui_show(obj);
 }
 
index 31f01077ea432812ef0bae60e4896d01c5881750..8da0ee44c6ad80a747642af112e87bfaff984726 100644 (file)
 #import "../ui/toolkit.h"
 #import "../common/context.h"
 
+typedef void(*get_eventdata_func)(id sender, UiVar *var, void **eventdata, int *value);
+
 @interface EventData : NSObject
-@property UiObject    *obj;
-@property ui_callback callback;
-@property void        *userdata;
-@property void        *data;
-@property int         value;
+@property UiObject           *obj;
+@property UiVar              *var;
+@property int                vartype;
+@property ui_callback        callback;
+@property void               *userdata;
+@property void               *data;
+@property int                value;
+@property get_eventdata_func get_eventdata;
 
 - (EventData*)init:(ui_callback)cb userdata:(void*)userdata;
 
 - (void)handleEvent:(id)sender;
 
+- (void)handleEventWithEventData:(id)sender;
+
+- (SEL)addDynamicMethod:(unsigned long long)method_id;
+
 @end
index 85992f1213eb366d23f7cc7eb9da9de729ae7694..f8513438535714d0e6963a993599e6078fbc21ba 100644 (file)
@@ -28,6 +28,9 @@
 
 #import "EventData.h"
 
+#import <objc/runtime.h>
+
+
 @implementation EventData
 
 - (EventData*)init:(ui_callback)cb userdata:(void*)userdata {
@@ -37,7 +40,7 @@
 }
 
 - (void)handleEvent:(id)sender {
-    if(self.callback) {
+    if(_callback) {
         UiEvent event;
         event.obj = self.obj;
         event.window = event.obj->window;
     }
 }
 
+- (void)handleEventWithEventData:(id)sender {
+    UiEvent event;
+    event.obj = self.obj;
+    event.window = event.obj->window;
+    event.document = event.obj->ctx->document;
+    event.eventdata = NULL;
+    event.intval = 0;
+    if(_get_eventdata) {
+        _get_eventdata(sender, _var, &event.eventdata, &event.intval);
+    }
+    if(self.callback) {
+        self.callback(&event, self.userdata);
+    }
+}
 
 @end
index a46ab57c4d8f16dc963a3b185229e5abe2e96b19..232f93ff1b2d3e5e28ec1ce2390ebf55ff10873a 100644 (file)
@@ -46,8 +46,8 @@
                                defer:false];
     
     // create a vertical stackview as default container
-    //BoxContainer *vbox = [[BoxContainer alloc] init:NSUserInterfaceLayoutOrientationVertical spacing:0];
-    GridLayout *vbox = [[GridLayout alloc] init];
+    BoxContainer *vbox = [[BoxContainer alloc] init:NSUserInterfaceLayoutOrientationVertical spacing:0];
+    //GridLayout *vbox = [[GridLayout alloc] init];
     vbox.translatesAutoresizingMaskIntoConstraints = false;
     [self.contentView addSubview:vbox];
     [NSLayoutConstraint activateConstraints:@[
index 8857d2f7c63988a6a97060b5739d9a3c9c3d58fa..8c9311b64190b26ffd2b440a8174a4046088b093 100644 (file)
 #import "toolkit.h"
 
 #import "../ui/button.h"
+
+int64_t ui_togglebutton_get(UiInteger *i);
+void ui_togglebutton_set(UiInteger *i, int64_t value);
+
+int64_t ui_switch_get(UiInteger *i);
+void ui_switch_set(UiInteger *i, int64_t value);
+
+int64_t ui_radiobuttons_get(UiInteger *i);
+void ui_radiobuttons_set(UiInteger *i, int64_t value);
index b15355358df27269989795042ea2515be8a46ae6..5ac939b2f6ae9767c96969096ebcaf2ae3adf38b 100644 (file)
@@ -51,3 +51,178 @@ UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs args) {
     
     return (__bridge void*)button;
 }
+
+
+static void togglebutton_eventdata(id button, UiVar *var, void **eventdata, int *value) {
+    NSButton *btn = (NSButton*)button;
+    NSControlStateValue state = btn.state;
+    *value = (int)state;
+}
+
+UIWIDGET togglebutton_create(UiObject* obj, UiToggleArgs args, enum NSButtonType type) {
+    NSButton *button = [[NSButton alloc] init];
+    [button setButtonType:type];
+    //[button setAllowsMixedState:YES];
+    
+    if(args.label) {
+        NSString *label = [[NSString alloc] initWithUTF8String:args.label];
+        button.title = label;
+    }
+    
+    UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_INTEGER);
+    if(var) {
+        UiInteger *i = var->value;
+        i->obj = (__bridge void*)button;
+        i->get = ui_togglebutton_get;
+        i->set = ui_togglebutton_set;
+    }
+    
+    if(args.onchange) {
+        EventData *event = [[EventData alloc] init:args.onchange userdata:args.onchangedata];
+        event.get_eventdata = togglebutton_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);
+    }
+    
+    UiLayout layout = UI_INIT_LAYOUT(args);
+    ui_container_add(obj, button, &layout, FALSE);
+    
+    return (__bridge void*)button;
+}
+
+int64_t ui_togglebutton_get(UiInteger *i) {
+    NSButton *button = (__bridge NSButton*)i->obj;
+    NSControlStateValue state = button.state;
+    i->value = (int64_t)state;
+    return (int64_t)state;
+}
+
+void ui_togglebutton_set(UiInteger *i, int64_t value) {
+    NSButton *button = (__bridge NSButton*)i->obj;
+    NSControlStateValue state;
+    switch(value) {
+        case 0: state = NSControlStateValueOff; break;
+        case 1: state = NSControlStateValueOff; break;
+        default: state = NSControlStateValueMixed;
+    }
+    i->value = (int64_t)state;
+    button.state = state;
+}
+
+UIWIDGET ui_togglebutton_create(UiObject* obj, UiToggleArgs args) {
+    return togglebutton_create(obj, args, NSButtonTypePushOnPushOff);
+}
+
+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) {
+    NSSwitch *btn = (NSSwitch*)button;
+    NSControlStateValue state = btn.state;
+    *value = (int)state;
+}
+
+UIWIDGET ui_switch_create(UiObject* obj, UiToggleArgs args) {
+    NSSwitch *button = [[NSSwitch alloc] init];
+    
+    UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_INTEGER);
+    if(var) {
+        UiInteger *i = var->value;
+        i->obj = (__bridge void*)button;
+        i->get = ui_switch_get;
+        i->set = ui_switch_set;
+    }
+    
+    if(args.onchange) {
+        EventData *event = [[EventData alloc] init:args.onchange userdata:args.onchangedata];
+        event.get_eventdata = switch_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);
+    }
+    
+    UiLayout layout = UI_INIT_LAYOUT(args);
+    ui_container_add(obj, button, &layout, FALSE);
+    
+    return (__bridge void*)button;
+}
+
+int64_t ui_switch_get(UiInteger *i) {
+    NSSwitch *button = (__bridge NSSwitch*)i->obj;
+    NSControlStateValue state = button.state;
+    i->value = (int64_t)state;
+    return (int64_t)state;
+}
+
+void ui_switch_set(UiInteger *i, int64_t value) {
+    NSSwitch *button = (__bridge NSSwitch*)i->obj;
+    NSControlStateValue state;
+    switch(value) {
+        case 0: state = NSControlStateValueOff; break;
+        case 1: state = NSControlStateValueOff; break;
+        default: state = NSControlStateValueMixed;
+    }
+    i->value = (int64_t)state;
+    button.state = state;
+}
+
+static void radiobutton_eventdata(id button, UiVar *var, void **eventdata, int *value) {
+    if(var) {
+        printf("switch radiobutton\n");
+    }
+}
+
+UIWIDGET ui_radiobutton_create(UiObject* obj, UiToggleArgs args) {
+    NSButton *button = [[NSButton alloc] init];
+    [button setButtonType:NSButtonTypeRadio];
+    
+    UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args.value, args.varname, UI_VAR_INTEGER);
+    NSMutableArray *buttons = nil;
+    if(var) {
+        UiInteger *i = var->value;
+        buttons = (__bridge NSMutableArray*)i->obj;
+        if(!buttons) {
+            buttons = [[NSMutableArray alloc] init];
+            i->obj = (__bridge void*)buttons;
+            i->get = ui_radiobuttons_get;
+            i->set = ui_radiobuttons_set;
+        }
+        [buttons addObject:button];
+        objc_setAssociatedObject(button, "radiogroup", buttons, OBJC_ASSOCIATION_RETAIN);
+    }
+    
+    if(args.onchange || var) {
+        EventData *event = [[EventData alloc] init:args.onchange userdata:args.onchangedata];
+        event.get_eventdata = radiobutton_eventdata;
+        event.obj = obj;
+        event.var = var;
+        event.vartype = UI_VAR_INTEGER;
+        button.target = event;
+        
+        
+        button.action = @selector(handleEventWithEventData:);
+        
+        objc_setAssociatedObject(button, "eventdata", event, OBJC_ASSOCIATION_RETAIN);
+    }
+    
+    UiLayout layout = UI_INIT_LAYOUT(args);
+    ui_container_add(obj, button, &layout, FALSE);
+    
+    return (__bridge void*)button;
+}
+
+int64_t ui_radiobuttons_get(UiInteger *i) {
+    return 0;
+}
+
+void ui_radiobuttons_set(UiInteger *i, int64_t value) {
+    
+}
index 9a24822d2c48783ec5da67dda882266fe738c64f..17b4e4c0da5988292083fbaf648309e853f368d5 100644 (file)
@@ -957,6 +957,68 @@ static GtkWidget* create_paned(UiOrientation orientation) {
 
 
 
+static UIWIDGET splitpane_create(UiObject *obj, UiOrientation orientation, UiSplitPaneArgs args) {
+    UiObject* current = uic_current_obj(obj);
+    
+    GtkWidget *pane0 = create_paned(orientation);
+    
+    UI_APPLY_LAYOUT1(current, args);
+    current->container->add(current->container, pane0, TRUE);
+    
+    int max = args.max_panes == 0 ? 2 : args.max_panes;
+    
+    UiObject *newobj = uic_object_new(obj, pane0);
+    newobj->container = ui_splitpane_container(obj, pane0, orientation, max);
+    uic_obj_add(obj, newobj);
+    
+    return pane0;
+}
+
+UIWIDGET ui_hsplitpane_create(UiObject *obj, UiSplitPaneArgs args) {
+    return splitpane_create(obj, UI_HORIZONTAL, args);
+}
+
+UIWIDGET ui_vsplitpane_create(UiObject *obj, UiSplitPaneArgs args) {
+    return splitpane_create(obj, UI_VERTICAL, args);
+}
+
+UiContainer* ui_splitpane_container(UiObject *obj, GtkWidget *pane, UiOrientation orientation, int max) {
+    UiSplitPaneContainer *ct = ui_calloc(obj->ctx, 1, sizeof(UiSplitPaneContainer));
+    ct->container.widget = pane;
+    ct->container.add = ui_splitpane_container_add;
+    ct->current_pane = pane;
+    ct->orientation = orientation;
+    ct->max = max;
+    return (UiContainer*)ct;
+}
+
+void ui_splitpane_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill) {
+    UiSplitPaneContainer *s = (UiSplitPaneContainer*)ct;
+    
+    if(s->nchildren >= s->max) {
+        fprintf(stderr, "splitpane: maximum number of children reached\n");
+        return;
+    }
+    
+    if(s->pos == 0) {
+        gtk_paned_set_start_child(GTK_PANED(s->current_pane), widget);
+        s->pos++;
+        s->nchildren++;
+    } else {
+        if(s->nchildren+1 == s->max) {
+            gtk_paned_set_end_child(GTK_PANED(s->current_pane), widget);
+        } else {
+            GtkWidget *pane = create_paned(s->orientation);
+            gtk_paned_set_start_child(GTK_PANED(pane), widget);
+            gtk_paned_set_end_child(GTK_PANED(s->current_pane), pane);
+            s->current_pane = pane;
+        }
+        
+        s->pos = 0;
+        s->nchildren++;
+    }
+}
+
 /* -------------------- ItemList Container -------------------- */
 
 static void remove_item(void *data, void *item) {
index 3ea8fbb1dce1ccd41a54dc0da958f4e4e4db220a..271ed507ce01d7263b2f0147c8a7e43200ddc3ad 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "../ui/toolkit.h"
 #include "../ui/container.h"
+#include "toolkit.h"
 #include <string.h>
 
 #include <cx/allocator.h>
@@ -97,16 +98,6 @@ typedef struct UiGridContainer {
 #endif
 } UiGridContainer;
 
-/*
-typedef struct UiPanedContainer {
-    UiContainer container;
-    GtkWidget *current_pane;
-    int orientation;
-    int max;
-    int cur;
-} UiPanedContainer;
-*/
-
 typedef struct UiTabViewContainer {
     UiContainer container;
 } UiTabViewContainer;
@@ -127,6 +118,16 @@ typedef struct UiGtkTabView {
     int rowspacing;
 } UiGtkTabView;
 
+
+typedef struct UiSplitPaneContainer {
+    UiContainer container;
+    GtkWidget *current_pane;
+    UiOrientation orientation;
+    int pos;
+    int max;
+    int nchildren;
+} UiSplitPaneContainer;
+
 typedef struct UiHeaderbarContainer {
     UiContainer container;
     GtkWidget *centerbox;
@@ -185,10 +186,9 @@ void ui_scrolledwindow_container_add(UiContainer *ct, GtkWidget *widget, UiBool
 UiContainer* ui_tabview_container(UiObject *obj, GtkWidget *tabview);
 void ui_tabview_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
 
-void ui_paned_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
+UiContainer* ui_splitpane_container(UiObject *obj, GtkWidget *pane, UiOrientation orientation, int max);
+void ui_splitpane_container_add(UiContainer *ct, GtkWidget *widget, UiBool fill);
 
-void ui_split_container_add1(UiContainer *ct, GtkWidget *widget, UiBool fill);
-void ui_split_container_add2(UiContainer *ct, GtkWidget *widget, UiBool fill);
 
 UiGtkTabView* ui_widget_get_tabview_data(UIWIDGET tabview);
 
index 17407b72463bff6842c214781a9ac3440c8aac5c..c53912e2be8d9e2913315b67cd3895541644f0b9 100644 (file)
@@ -94,6 +94,7 @@ UIEXPORT UIWIDGET ui_radiobutton_create(UiObject* obj, UiToggleArgs args);
 
 
 
+
 #ifdef __cplusplus
 }
 #endif
index dda4867a259912de8c91944be0e52533f50d72e6..ea14d8ced4a175b92920c01149b121b74141349f 100644 (file)
@@ -160,6 +160,28 @@ typedef struct UiSidebarArgs {
     int spacing;
 } UiSidebarArgs;
 
+typedef struct UiSplitPaneArgs {
+    UiTri fill;
+    UiBool hexpand;
+    UiBool vexpand;
+    UiBool hfill;
+    UiBool vfill;
+    int colspan;
+    int rowspan;
+    const char *name;
+    const char *style_class;
+
+    int margin;
+    int spacing;
+    int columnspacing;
+    int rowspacing;
+    
+    int initial_position;
+    UiInteger *value;
+    const char* varname;
+    int max_panes;
+} UiSplitPaneArgs;
+
 typedef struct UiItemListContainerArgs {
     UiTri fill;
     UiBool hexpand;
@@ -234,6 +256,11 @@ struct UiContainerX {
 #define ui_headerbar0(obj) for(ui_headerbar_create(obj, (UiHeaderbarArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
 #define ui_sidebar0(obj) for(ui_sidebar_create(obj, (UiSidebarArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
 
+#define ui_hsplitpane(obj, ...) for(ui_hsplitpane_create(obj, (UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_vsplitpane(obj, ...) for(ui_vsplitpane_create(obj, (UiSplitPaneArgs){ __VA_ARGS__ });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_hsplitpane0(obj) for(ui_hsplitpane_create(obj, (UiSplitPaneArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
+#define ui_vsplitpane0(obj) for(ui_vsplitpane_create(obj, (UiSplitPaneArgs){ 0 });ui_container_finish(obj);ui_container_begin_close(obj))
+
 #define ui_tab(obj, label) for(ui_tab_create(obj, label);ui_container_finish(obj);ui_container_begin_close(obj))
 
 #define ui_headerbar_start(obj) for(ui_headerbar_start_create(obj);ui_container_finish(obj);ui_container_begin_close(obj))
@@ -267,8 +294,8 @@ UIEXPORT UIWIDGET ui_sidebar_create(UiObject *obj, UiSidebarArgs args);
 
 UIEXPORT UIWIDGET ui_itemlist_create(UiObject *obj, UiItemListContainerArgs args);
 
-UIEXPORT UIWIDGET ui_hsplitpane(UiObject *obj, int max); // TODO
-UIEXPORT UIWIDGET ui_vsplitpane(UiObject *obj, int max); // TODO
+UIEXPORT UIWIDGET ui_hsplitpane_create(UiObject *obj, UiSplitPaneArgs args);
+UIEXPORT UIWIDGET ui_vsplitpane_create(UiObject *obj, UiSplitPaneArgs args);
 
 
 // box container layout functions