From: Olaf Wintermann Date: Thu, 23 Apr 2026 15:22:31 +0000 (+0200) Subject: finish SourceList bindings X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;h=92e84d9f7cb9369e770672f62b03fa044c7e9701;p=note.git finish SourceList bindings --- diff --git a/application/src/main.rs b/application/src/main.rs index 45fdf7c..db83377 100644 --- a/application/src/main.rs +++ b/application/src/main.rs @@ -15,8 +15,8 @@ struct TestData { i: i32, #[bind("list")] list: UiList, - #[bind] - sublists: UiList> + #[bind("source")] + sublists: UiSourceList } #[ui_actions] @@ -37,6 +37,14 @@ fn create_window() { list.push(11); list.push(12); + let mut sl = SubList::new(); + sl.set_header("Header"); + sl.data().push(String::from("Elm 1")); + sl.data().push(String::from("Elm 2")); + + data.sublists.push(sl); + + obj.button_builder().label("Hello").onclick(|e| { println!("Button clicked: {}", e.data.i); e.data.i += 1; @@ -47,7 +55,12 @@ fn create_window() { //obj.tableview_builder::().fill(true).varname("list").model(&model).getvalue(|elm, _row, _col| { // ListValue::String(elm.to_string()) //}).create(); - obj.sourcelist_builder::().fill(true).value(&data.sublists).create(); + obj.sourcelist_builder::().fill(true).value(&data.sublists).getvalue(|elm, index, item| { + item.label = Some(elm.to_string()); + item.badge = Some(index.to_string()); + }).create(); + + println!("test"); }); window.show(); diff --git a/ui-rs/src/ui/list.rs b/ui-rs/src/ui/list.rs index a667220..a1fca13 100644 --- a/ui-rs/src/ui/list.rs +++ b/ui-rs/src/ui/list.rs @@ -43,10 +43,20 @@ pub struct TableModel { } pub struct SubList { - handle: *mut ffi::UiSubList, + pub handle: *mut ffi::UiSubList, list: toolkit::UiList } +#[derive(Default)] +pub struct SourceListItem { + pub icon: Option, + pub label: Option, + pub button_icon: Option, + pub button_label: Option, + pub badge: Option, + // TODO: button_menu +} + pub enum ColumnType { String = 0, // skip UI_STRING_FREE @@ -473,6 +483,7 @@ impl<'a, T, E> TableViewBuilder<'a, T, E> { impl<'a, T, E> SourceListBuilder<'a, T, E> { pub fn create(&mut self) { unsafe { + ui_sourcelist_args_set_getvalue_func(self.args, sourcelist_getvalue_wrapper::); ui_sourcelist_create(self.obj.ptr, self.args); } } @@ -591,7 +602,7 @@ impl<'a, T, E> SourceListBuilder<'a, T, E> { } self } - pub fn value(&mut self, value: &toolkit::UiList>) -> &mut Self { + pub fn value(&mut self, value: &toolkit::UiSourceList) -> &mut Self { unsafe { ui_sourcelist_args_set_dynamic_sublists(self.args, value.ptr); } @@ -599,11 +610,10 @@ impl<'a, T, E> SourceListBuilder<'a, T, E> { } pub fn getvalue(&mut self, f: F) -> &mut Self - where F: Fn(&E, i32, i32) -> ListValue<'a> + 'static { + where F: Fn(&E, i32, &mut SourceListItem) + 'static { unsafe { - let wrapper = Box::new(GetValueWrapper { callback: Box::new(f), is_table: false }); + let wrapper = Box::new(SLGetValueWrapper { callback: Box::new(f)}); let ptr = self.obj.ctx.reg_box(wrapper); - ui_sourcelist_args_set_getvalue_func(self.args, sourcelist_getvalue_wrapper::); ui_sourcelist_args_set_getvalue_userdata(self.args, ptr as *mut c_void); } self @@ -685,10 +695,12 @@ impl Drop for TableModel { impl SubList { pub fn new() -> Self { unsafe { - SubList { + let s = SubList { handle: ui_sublist_new(), list: toolkit::UiList::new() - } + }; + ui_sublist_set_value(s.handle, s.list.ptr); + s } } @@ -698,6 +710,14 @@ impl SubList { ui_sublist_set_header(self.handle, cstr.as_ptr()); } } + + pub fn list(&mut self) -> &mut toolkit::UiList { + &mut self.list + } + + pub fn data(&mut self) -> &mut Vec { + self.list.data() + } } impl Drop for SubList { @@ -718,6 +738,10 @@ struct GetValueWrapper<'a, T> { is_table: bool } +struct SLGetValueWrapper { + callback: Box +} + fn str_dup(str: &str) -> *mut c_void { let cstr = CString::new(str).unwrap(); @@ -765,12 +789,51 @@ pub extern "C" fn null_getvalue_wrapper(_list: *const ffi::UiList, _elm_ptr: *co pub extern "C" fn sourcelist_getvalue_wrapper( _list: *const ffi::UiList, _sublist_userdata: *mut c_void, - _row_data: *mut c_void, - _index: c_int, - _item: *mut ffi::UiSubListItem, - _userdata: *mut c_void) + row_data: *mut c_void, + index: c_int, + item: *mut ffi::UiSubListItem, + userdata: *mut c_void) { - // TODO + if userdata.is_null() { + return; + } + + let wrapper = unsafe { &*(userdata as *const SLGetValueWrapper ) }; + let elm = unsafe { &*(row_data as *const T) }; + + let mut it: SourceListItem = Default::default(); + (wrapper.callback)(elm, index, &mut it); + + if let Some(icon) = it.icon { + let cstr = CString::new(icon).unwrap(); + unsafe { + ui_sublist_item_set_icon(item, cstr.as_ptr()); + } + } + if let Some(label) = it.label { + let cstr = CString::new(label).unwrap(); + unsafe { + ui_sublist_item_set_label(item, cstr.as_ptr()); + } + } + if let Some(icon) = it.button_icon { + let cstr = CString::new(icon).unwrap(); + unsafe { + ui_sublist_item_set_button_icon(item, cstr.as_ptr()); + } + } + if let Some(label) = it.button_label { + let cstr = CString::new(label).unwrap(); + unsafe { + ui_sublist_item_set_button_label(item, cstr.as_ptr()); + } + } + if let Some(badge) = it.badge { + let cstr = CString::new(badge).unwrap(); + unsafe { + ui_sublist_item_set_badge(item, cstr.as_ptr()); + } + } } type SLGetValueFunc = extern "C" fn( @@ -856,4 +919,10 @@ extern "C" { fn ui_sublist_set_value(list: *mut ffi::UiSubList, value: *mut ffi::UiList); fn ui_sublist_set_header(list: *mut ffi::UiSubList, header: *const c_char); fn ui_sublist_free(list: *mut ffi::UiSubList); + + fn ui_sublist_item_set_icon(item: *mut ffi::UiSubListItem, icon: *const c_char); + fn ui_sublist_item_set_label(item: *mut ffi::UiSubListItem, label: *const c_char); + fn ui_sublist_item_set_button_icon(item: *mut ffi::UiSubListItem, icon: *const c_char); + fn ui_sublist_item_set_button_label(item: *mut ffi::UiSubListItem, label: *const c_char); + fn ui_sublist_item_set_badge(item: *mut ffi::UiSubListItem, badge: *const c_char); } \ No newline at end of file diff --git a/ui-rs/src/ui/toolkit.rs b/ui-rs/src/ui/toolkit.rs index 4a5b8e8..a1765a7 100644 --- a/ui-rs/src/ui/toolkit.rs +++ b/ui-rs/src/ui/toolkit.rs @@ -1,7 +1,7 @@ #![allow(dead_code)] use std::ffi::{c_char, c_int, c_void, CStr, CString}; -use crate::ui::{action_event_wrapper, event, ffi, ui_object_get_context, ui_object_get_windowdata, ui_reg_destructor, ActionEventWrapper, EventWrapper}; +use crate::ui::{action_event_wrapper, event, ffi, ui_object_get_context, ui_object_get_windowdata, ui_reg_destructor, ActionEventWrapper, EventWrapper, SubList}; use std::marker::PhantomData; use std::mem; @@ -186,6 +186,11 @@ pub struct UiList { data: Box> } +pub struct UiSourceList { + pub ptr: *mut ffi::UiList, + sublists: Vec> +} + /* -------------------------------- Default implementation -------------------------------- */ macro_rules! value_default_impl { @@ -213,6 +218,17 @@ impl Default for UiList { } } +impl Default for UiSourceList { + fn default() -> Self { + Self { + ptr: std::ptr::null_mut(), + sublists: Default::default() + } + } + + +} + pub fn app_init(appname: &str) { let s; let c_str = if appname.len() > 0 { @@ -372,6 +388,47 @@ impl Drop for UiList { } +/* -------------------------------- SourceList -------------------------------- */ + +impl UiSourceList { + pub fn init(&mut self, ctx: &UiContext, name: Option<&str>) { + let c_string = name.map(|n| CString::new(n).unwrap()); + let c_str = c_string.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()); + unsafe { + self.ptr = ui_list_new(ctx.ptr, c_str); + } + } + + pub fn push(&mut self, sublist: SubList) { + unsafe { + ui_list_append(self.ptr, sublist.handle as *mut c_void); + } + self.sublists.push(sublist); + } + + pub fn insert(&mut self, index: usize, sublist: SubList) { + unsafe { + ui_list_insert(self.ptr, index as c_int, sublist.handle as *mut c_void); + } + self.sublists.insert(index, sublist); + } + + pub fn remove(&mut self, index: usize) { + // TODO + self.sublists.remove(index); + } + + pub fn clear(&mut self) { + // TODO + self.sublists.clear(); + } + + pub fn update(&mut self) { + + } +} + + /* -------------------------------- List -------------------------------- */ /* @@ -500,6 +557,7 @@ type UiListGetFunc = extern "C" fn(*const ffi::UiList, c_int) -> *mut c_void; type UiListCountFunc = extern "C" fn(*const ffi::UiList) -> c_int; extern "C" { + fn ui_list_new(ctx: *mut ffi::UiContext, name: *const c_char) -> *mut ffi::UiList; fn ui_list_new2(ctx: *mut ffi::UiContext, name: *const c_char, init: UiListInitFunc, userdata: *mut c_void) -> *mut ffi::UiList; fn ui_list_class_set_first(list: *mut ffi::UiList, func: UiListFirstFunc); fn ui_list_class_set_next(list: *mut ffi::UiList, func: UiListNextFunc); @@ -521,5 +579,8 @@ extern "C" { fn ui_list_selection_get_rows(list: *mut ffi::UiListSelection) -> *const c_int; fn ui_list_selection_free(list: *mut ffi::UiListSelection); + pub fn ui_list_append(list: *mut ffi::UiList, data: *mut c_void); + pub fn ui_list_insert(list: *mut ffi::UiList, index: c_int, data: *mut c_void); + fn ui_list_free(ctx: *mut ffi::UiContext, list: *mut ffi::UiList); } diff --git a/ui/cocoa/EventData.h b/ui/cocoa/EventData.h index 603b87c..f82f1d4 100644 --- a/ui/cocoa/EventData.h +++ b/ui/cocoa/EventData.h @@ -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, int *eventdatatype, int *value); @interface EventData : NSObject @property UiObject *obj; diff --git a/ui/cocoa/EventData.m b/ui/cocoa/EventData.m index c7e95ec..aa8c74b 100644 --- a/ui/cocoa/EventData.m +++ b/ui/cocoa/EventData.m @@ -70,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); diff --git a/ui/cocoa/button.m b/ui/cocoa/button.m index 70ee28c..9a85451 100644 --- a/ui/cocoa/button.m +++ b/ui/cocoa/button.m @@ -47,12 +47,14 @@ UIWIDGET ui_button_create(UiObject* obj, UiButtonArgs *args) { button.image = ui_cocoa_named_icon(args->icon);; } - if(args->onclick) { + 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); @@ -62,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, int *eventdatatype, int *value) { NSButton *btn = (NSButton*)button; NSControlStateValue state = btn.state; *value = (int)state; @@ -135,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, int *eventdatatype, int *value) { NSSwitch *btn = (NSSwitch*)button; NSControlStateValue state = btn.state; *value = (int)state; @@ -205,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, int *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; diff --git a/ui/cocoa/text.h b/ui/cocoa/text.h index 415717c..aa4d410 100644 --- a/ui/cocoa/text.h +++ b/ui/cocoa/text.h @@ -47,3 +47,15 @@ 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 TextFieldDelegate : NSObject + +@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 diff --git a/ui/cocoa/text.m b/ui/cocoa/text.m index b01a07b..00a0877 100644 --- a/ui/cocoa/text.m +++ b/ui/cocoa/text.m @@ -29,6 +29,7 @@ #import "text.h" #import "EventData.h" #import "container.h" +#import "action.h" #import UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) { @@ -186,6 +187,10 @@ void ui_textarea_remove(UiText *text, int begin, int end) { /* -------------------------- TextField -------------------------- */ +static void textfield_geteventdata(id sender, UiVar *var, void **eventdata, int *eventdatatype, int *value) { + +} + static UIWIDGET textfield_create(UiObject *obj, UiTextFieldArgs *args, BOOL password, BOOL frameless) { NSTextField *textfield; if(password) { @@ -222,6 +227,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; } @@ -306,3 +332,41 @@ int ui_textfield_get_position(UIWIDGET textfield) { 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 diff --git a/ui/common/types.c b/ui/common/types.c index c4b51ce..aeb8586 100644 --- a/ui/common/types.c +++ b/ui/common/types.c @@ -100,8 +100,9 @@ void ui_notify_evt(UiObserver *observer, UiEvent *event) { /* --------------------------- UiList --------------------------- */ void uic_ucx_list_init(UiContext *ctx, UiList *list, void *unused) { + const CxAllocator *a = ctx ? ctx->allocator : cxDefaultAllocator; list->destroy = uic_ucx_list_destroy; - list->data = cxArrayListCreate(ctx->mp->allocator, CX_STORE_POINTERS, 32); + list->data = cxArrayListCreate(a, CX_STORE_POINTERS, 32); list->first = ui_list_first; list->next = ui_list_next; list->get = ui_list_get; @@ -170,6 +171,10 @@ 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) { if(i >= 0) { cxListRemove(list->data, i); @@ -394,7 +399,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; @@ -403,7 +408,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; @@ -419,7 +424,7 @@ 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; @@ -435,7 +440,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; @@ -444,7 +449,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; @@ -459,8 +464,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; diff --git a/ui/gtk/text.c b/ui/gtk/text.c index e9dc703..e3929da 100644 --- a/ui/gtk/text.c +++ b/ui/gtk/text.c @@ -129,6 +129,7 @@ UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs *args) { uitext->last_selection_state = 0; uitext->onchange = args->onchange; uitext->onchangedata = args->onchangedata; + uitext->action = args->action ? strdup(args->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); @@ -212,6 +213,7 @@ void ui_textarea_destroy(GtkWidget *object, UiTextArea *textarea) { if(textarea->var) { ui_destroy_boundvar(textarea->ctx, textarea->var); } + free(textarea->action); free(textarea); } @@ -394,6 +396,10 @@ void ui_textbuf_changed(GtkTextBuffer *textbuffer, UiTextArea *textarea) { if(value->observers) { ui_notify_evt(value->observers, &e); } + + if(textarea->action) { + uic_action_callback(&e, textarea->action); + } } // undo manager functions @@ -660,6 +666,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, @@ -703,7 +711,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", @@ -711,7 +719,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", @@ -771,6 +779,8 @@ int ui_textfield_get_position(UIWIDGET textfield) { } void ui_textfield_destroy(GtkWidget *object, UiTextField *textfield) { + free(textfield->onactivate_action); + free(textfield->onchange_action); free(textfield); } @@ -786,7 +796,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(); @@ -797,22 +807,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) { diff --git a/ui/gtk/text.h b/ui/gtk/text.h index 4d306aa..057aef8 100644 --- a/ui/gtk/text.h +++ b/ui/gtk/text.h @@ -67,6 +67,7 @@ typedef struct UiTextArea { int last_selection_state; ui_callback onchange; void *onchangedata; + char *action; } UiTextArea; typedef struct UiTextField { @@ -76,6 +77,8 @@ typedef struct UiTextField { void *onchangedata; ui_callback onactivate; void *onactivatedata; + char *onactivate_action; + char *onchange_action; } UiTextField; typedef struct UiPathTextField { diff --git a/ui/ui/toolkit.h b/ui/ui/toolkit.h index 77234b9..d76f7a5 100644 --- a/ui/ui/toolkit.h +++ b/ui/ui/toolkit.h @@ -694,6 +694,7 @@ 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);