}
}
+ 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);
}
#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
#import "EventData.h"
+#import <objc/runtime.h>
+
+
@implementation EventData
- (EventData*)init:(ui_callback)cb userdata:(void*)userdata {
}
- (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
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:@[
#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);
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) {
+
+}
+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) {
#include "../ui/toolkit.h"
#include "../ui/container.h"
+#include "toolkit.h"
#include <string.h>
#include <cx/allocator.h>
#endif
} UiGridContainer;
-/*
-typedef struct UiPanedContainer {
- UiContainer container;
- GtkWidget *current_pane;
- int orientation;
- int max;
- int cur;
-} UiPanedContainer;
-*/
-
typedef struct UiTabViewContainer {
UiContainer container;
} UiTabViewContainer;
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;
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);
+
#ifdef __cplusplus
}
#endif
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;
#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))
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