use std::ffi::{c_char, c_int, c_void, CString};
use std::marker::PhantomData;
-use crate::ui::{event, ffi, toolkit, AppContext, EventWrapper, GetValueFunc, ToggleButtonCreate, UiActions, UiContext, UiModel};
-use crate::ui::ffi::{UiCallback, UiMenuItemArgs, UiMenuItemListArgs, UiMenuToggleItemArgs, UiObject, UiToggleArgs};
+use std::ops::Deref;
+use crate::ui::{event, ffi, toolkit, ui_document_context, ui_document_new, ui_document_unref, AppContext, EventWrapper, GetValueFunc, ToggleButtonCreate, UiActions, UiContext, UiModel};
+use crate::ui::ffi::{UiCallback, UiDestructor, UiMenuBuilder, UiMenuItemArgs, UiMenuItemListArgs, UiMenuToggleItemArgs, UiObject, UiToggleArgs};
impl<T: UiModel + UiActions> AppContext<T> {
pub fn menu<F>(&self, title: &str, f: F)
}
}
+
+pub struct MenuBuilder<T: UiModel + UiActions> {
+ menu: Menu<T>,
+ doc: *mut c_void,
+ ctx: *mut ffi::UiContext,
+ builder: *mut UiMenuBuilder,
+}
+
+impl<T: UiModel + UiActions> Deref for MenuBuilder<T> {
+ type Target = Menu<T>;
+
+ fn deref(&self) -> &Self::Target {
+ &self.menu
+ }
+}
+
+impl<T: UiModel + UiActions> MenuBuilder<T> {
+ pub fn ref_by_obj(&self, obj: &toolkit::UiObject<T>) {
+ unsafe {
+ ui_menubuilder_ref_by_obj(self.builder, obj.ptr);
+ }
+ }
+}
+
+impl<T: UiModel + UiActions> Clone for MenuBuilder<T> {
+ fn clone(&self) -> Self {
+ unsafe {
+ ui_menubuilder_ref(self.builder);
+ }
+ MenuBuilder {
+ menu: Menu {
+ ctx: self.ctx,
+ _marker: PhantomData
+ },
+ doc: self.doc,
+ ctx: self.ctx,
+ builder: self.builder,
+ }
+ }
+}
+
+impl<T: UiModel + UiActions> Drop for MenuBuilder<T> {
+ fn drop(&mut self) {
+ unsafe {
+ ui_menubuilder_unref(self.builder);
+ }
+ }
+}
+
+pub fn menubuilder_new<T: UiModel + UiActions>() -> MenuBuilder<T> {
+ unsafe {
+ let doc = ui_document_new(8);
+ let ctx = ui_document_context(doc);
+ let mut builder: *mut UiMenuBuilder = std::ptr::null_mut();
+ ui_contextmenu_builder(&mut builder);
+ ui_menubuilder_set_custom_data(builder, doc, menubuilder_doc_destroy);
+ let menu = Menu {
+ ctx,
+ _marker: PhantomData,
+ };
+
+ MenuBuilder {
+ menu,
+ doc,
+ ctx,
+ builder
+ }
+ }
+}
+
+
+extern "C" fn menubuilder_doc_destroy(doc: *mut c_void) {
+ unsafe {
+ ui_document_unref(doc);
+ }
+}
+
unsafe extern "C" {
fn ui_menu_create(label: *const c_char);
fn ui_menuitem_create(args: *const UiMenuItemArgs);
fn ui_menu_toggleitemlist_create(args: *const UiMenuItemListArgs);
fn ui_menu_radioitemlist_create(args: *const UiMenuItemListArgs);
pub fn ui_menu_end();
+ fn ui_contextmenu_builder(out_builder: *mut *mut ffi::UiMenuBuilder);
+ fn ui_menubuilder_set_custom_data(builder: *mut UiMenuBuilder, data: *mut c_void, destr: UiDestructor);
+ fn ui_menubuilder_ref_by_obj(builder: *mut ffi::UiMenuBuilder, obj: *mut ffi::UiObject);
+ fn ui_menubuilder_ref(builder: *mut ffi::UiMenuBuilder);
+ fn ui_menubuilder_unref(builder: *mut ffi::UiMenuBuilder);
fn ui_menuitem_args_new() -> *mut UiMenuItemArgs;
fn ui_menuitem_args_set_label(args: *mut UiMenuItemArgs, label: *const c_char);
fn ui_configfile(name: *const c_char) -> *mut c_char;
pub fn ui_call_mainthread(func: UiThreadFunc, data: *mut c_void);
- fn ui_document_new(size: usize) -> *mut c_void;
- fn ui_document_ref(doc: *mut c_void);
- fn ui_document_unref(doc: *mut c_void);
- fn ui_document_context(doc: *mut c_void) -> *mut ffi::UiContext;
+ pub fn ui_document_new(size: usize) -> *mut c_void;
+ pub fn ui_document_ref(doc: *mut c_void);
+ pub fn ui_document_unref(doc: *mut c_void);
+ pub fn ui_document_context(doc: *mut c_void) -> *mut ffi::UiContext;
fn ui_attach_document(ctx: *mut ffi::UiContext, doc: *mut c_void);
fn ui_detach_document(ctx: *mut ffi::UiContext, doc: *mut c_void);
fn ui_context_onattach(ctx: *mut ffi::UiContext, callback: UiCallback, data: *mut c_void);
// add new box to the obj container chain
uic_object_push_container(obj, container);
- return (__bridge void*)box;
+ void *widget = (__bridge void*)box;
+ uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
+
+ return widget;
}
UIWIDGET ui_vbox_create(UiObject *obj, UiContainerArgs *args) {
// add new box to the obj container chain
uic_object_push_container(obj, container);
- return (__bridge void*)grid;
+ void *widget = (__bridge void*)grid;
+ uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
+
+ return widget;
}
UIWIDGET ui_frame_create(UiObject *obj, UiFrameArgs *args) {
uic_object_push_container(obj, container);
- return (__bridge void*)frame;
+ void *widget = (__bridge void*)frame;
+ uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
+
+ return widget;
}
UIWIDGET ui_expander_create(UiObject *obj, UiFrameArgs *args) {
UiContainer *container = ui_create_container(obj, scrollview);
uic_object_push_container(obj, container);
- return (__bridge void*)scrollview;
+ void *widget = (__bridge void*)scrollview;
+ uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
+
+ return widget;
}
static int64_t tabview_get(UiInteger *i) {
UiContainer *container = ui_create_container(obj, tabview);
uic_object_push_container(obj, container);
- return (__bridge void*)tabview;
+ void *widget = (__bridge void*)tabview;
+ uic_widget_set_visibility_states(obj->ctx, widget, args->visibility_states);
+
+ return widget;
}
void ui_tab_create(UiObject *obj, const char* title) {
if(s->value.ptr) {
label.stringValue = [[NSString alloc]initWithUTF8String:s->value.ptr];
}
+ if(s->value.free) {
+ s->value.free(s->value.ptr);
+ }
}
return (__bridge void*)label;
s->value.free(s->value.ptr);
}
s->value.ptr = strdup(label.stringValue.UTF8String);
+ s->value.free = free;
return s->value.ptr;
}
s->value.free(s->value.ptr);
}
s->value.ptr = NULL;
+ s->value.free = NULL;
label.stringValue = [[NSString alloc] initWithUTF8String:str];
}
COCOAOBJ += entry.o
COCOAOBJ += TabView.o
COCOAOBJ += action.o
+COCOAOBJ += webview.o
TOOLKITOBJS += $(COCOAOBJ:%=$(COCOA_OBJPRE)%)
TOOLKITSOURCE += $(COCOAOBJ:%.o=cocoa/%.m)
}
@end
+
+
+
+/* -------------------- Path TextField -------------------- */
+
+UIWIDGET ui_path_textfield_create(UiObject* obj, UiPathTextFieldArgs *args) {
+ return NULL; // TODO: implement
+}
#import "webview.h"
#import "Container.h"
+static UiWebViewData* create_webview_data(void) {
+ UiWebViewData *data = malloc(sizeof(UiWebViewData));
+ memset(data, 0, sizeof(UiWebViewData));
+ data->javascript = TRUE;
+ data->zoom = 1;
+ return data;
+}
+
UIWIDGET ui_webview_create(UiObject *obj, UiWebviewArgs *args) {
UiVar *var = uic_widget_var(obj->ctx, obj->ctx, args->value, args->varname, UI_VAR_GENERIC);
if(value->value) {
ui_webview_set(value, value->value, UI_WEBVIEW_OBJECT_TYPE);
} else {
- UiWebViewData *data = malloc(sizeof(UiWebViewData));
- memset(data, 0, sizeof(UiWebViewData));
+ UiWebViewData *data = create_webview_data();
data->webview = (__bridge void*)webview;
- data->javascript = TRUE;
- data->zoom = 1;
value->value = data;
}
}
}
UiWebViewData* ui_webview_data_clone(UiWebViewData *data) {
- UiWebViewData *newdata = malloc(sizeof(UiWebViewData));
- memset(newdata, 0, sizeof(UiWebViewData));
- newdata->zoom = 1;
- newdata->javascript = TRUE;
+ UiWebViewData *newdata = create_webview_data();
if(data) {
newdata->uri = data->uri ? strdup(data->uri) : NULL;
UiWebViewData *data = g->value;
WKWebView *webview = (__bridge WKWebView*)g->obj;
+ if(data == NULL) {
+ data = create_webview_data();
+ data->webview = g->obj;
+ g->value = data;
+ }
+
if(data->type == WEBVIEW_CONTENT_URL) {
(void)ui_webview_get_uri(g); // this updates data->uri
}
void ui_webview_load_url(UiGeneric *g, const char *url) {
WKWebView *webview = (__bridge WKWebView*)g->obj;
UiWebViewData *data = g->value;
+
+ if(data == NULL) {
+ data = create_webview_data();
+ data->webview = g->obj;
+ g->value = data;
+ }
+
data->type = WEBVIEW_CONTENT_URL;
if(!url) {
UiWebViewData *data = g->value;
WKWebView *webview = (__bridge WKWebView*)g->obj;
+ if(data == NULL) {
+ data = create_webview_data();
+ data->webview = g->obj;
+ g->value = data;
+ }
+
data->type = WEBVIEW_CONTENT_CONTENT;
free(data->uri);
EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata action:nil];
event.obj = obj;
- event.value = 2;
+ event.value = 4;
rbutton4.target = event;
rbutton4.action = @selector(handleEvent:);
objc_setAssociatedObject(rbutton4, "eventdata", event, OBJC_ASSOCIATION_RETAIN);
EventData *event = [[EventData alloc] init:args->onclick userdata:args->onclickdata action:nil];
event.obj = obj;
- event.value = 2;
+ event.value = 3;
rbutton3.target = event;
rbutton3.action = @selector(handleEvent:);
objc_setAssociatedObject(rbutton3, "eventdata", event, OBJC_ASSOCIATION_RETAIN);
builder->menus_begin = NULL;
builder->menus_end = NULL;
builder->current = cxLinkedListCreate(cxDefaultAllocator, CX_STORE_POINTERS);
+ builder->custom_data = NULL;
+ builder->custom_destr = NULL;
builder->ref = 1;
current_builder = builder;
*out_builder = builder;
ui_menu_create(NULL);
}
+void ui_menubuilder_set_custom_data(UiMenuBuilder *builder, void *data, ui_destructor_func destr) {
+ builder->custom_destr = destr;
+ builder->custom_data = data;
+}
static void free_menuitem(UiMenuItemI *item) {
ui_menubuilder_free(builder);
}
}
+
+void ui_menubuilder_ref_by_obj(UiMenuBuilder *builder, UiObject *obj) {
+ builder->ref++;
+ ui_reg_destructor(obj->ctx, builder, (ui_destructor_func)ui_menubuilder_unref);
+}
UiMenu *menus_begin;
UiMenu *menus_end;
CxList *current;
+ ui_destructor_func custom_destr;
+ void *custom_data;
int ref;
};
UIEXPORT void ui_contextmenu_builder(UiMenuBuilder **out_builder);
UIEXPORT void ui_menubuilder_ref(UiMenuBuilder *builder);
UIEXPORT void ui_menubuilder_unref(UiMenuBuilder *builder);
+UIEXPORT void ui_menubuilder_ref_by_obj(UiMenuBuilder *builder, UiObject *obj);
UIEXPORT UIMENU ui_contextmenu_create(UiMenuBuilder *builder, UiObject *obj, UIWIDGET widget);
UIEXPORT void ui_contextmenu_popup(UIMENU menu, UIWIDGET widget, int x, int y);
UIEXPORT void ui_menu_close(void);
UIEXPORT int ui_menu_is_open(void);
+UIEXPORT void ui_menubuilder_set_custom_data(UiMenuBuilder *builder, void *data, ui_destructor_func destr);
+
#ifdef __cplusplus
}
#endif