#[derive(UiModel)]
pub struct MainWindow {
+ pub obj: Option<UiObject<MainWindow>>,
pub backend: BackendHandle,
#[bind]
impl MainWindow {
pub fn new(app: &App) -> MainWindow {
MainWindow {
+ obj: None,
backend: app.backend.clone(),
notebooks: UiSourceList::default()
}
pub fn create_window(app: &App, ctx: &AppContext<MainWindow>) -> UiObject<MainWindow> {
let windowdata: MainWindow = MainWindow::new(app);
- let window = ctx.splitview_window("note", true, windowdata, |obj, data| {
+ let mut window = ctx.splitview_window("note", true, windowdata, |obj, data| {
init_window_data(data, app);
+ data.obj = Some(obj.clone());
obj.sidebar_builder().create(|obj|{
obj.sourcelist(|b|{
});
window.show();
+ window.onclose(|event| {
+ println!("window closing");
+ event.data.obj = None;
+ });
window
}
}
}
+ pub fn onclose<F>(&mut self, f: F)
+ where F: FnMut(&mut event::Event<T>) + 'static {
+ let wrapper = Box::new(EventWrapper { callback: Box::new(f) });
+ let ptr = self.ctx.reg_box(wrapper);
+ unsafe {
+ ui_object_set_onclose(self.ptr, Some(event::event_wrapper::<T>), ptr.cast());
+ }
+ }
+
pub fn set_size(&mut self, width: u32, height: u32) {
unsafe {
ui_window_size(self.ptr, width as c_int, height as c_int);
pub fn ui_object_get_windowdata(obj: *const UiObject) -> *mut c_void;
pub fn ui_object_set_windowdata(obj: *mut UiObject, data: *mut c_void);
pub fn ui_object_get_context(obj: *const UiObject) -> *mut UiContext;
+ fn ui_object_set_onclose(obj: *const UiObject, onclose: UiCallback, data: *mut c_void);
pub fn ui_reg_destructor(ctx: *mut UiContext, data: *mut c_void, destructor: UiDestructor);
cxListAdd(ctx->destroy_handler, &handler);
}
+void uic_context_remove_destructor(UiContext *ctx, void *data) {
+ CxIterator i = cxListIterator(ctx->destroy_handler);
+ cx_foreach(UiDestroyHandler *, handler, i) {
+ if(handler->data == data) {
+ cxIteratorFlagRemoval(i);
+ }
+ }
+}
+
void uic_context_prepare_close(UiContext *ctx) {
cxListClear(ctx->states);
cxListClear(ctx->state_widgets);
uic_context_add_destructor(ctx, destr, data);
}
+void ui_remove_destructor(UiContext *ctx, void *data) {
+ uic_context_remove_destructor(ctx, data);
+}
+
void ui_set_destructor(void *mem, ui_destructor_func destr) {
cxMempoolSetDestructor(mem, (cx_destructor_func)destr);
}
UiContext* uic_context(UiObject *toplevel, CxMempool *mp);
UiContext* uic_root_context(UiContext *ctx);
void uic_context_add_destructor(UiContext *ctx, cx_destructor_func func, void *data);
+void uic_context_remove_destructor(UiContext *ctx, void *data);
void uic_context_prepare_close(UiContext *ctx);
void uic_context_destroy(UiContext *ctx, void *document);
// it is possible to have 0 references, in case
// a window was created but ui_show was never called
if(obj->ref == 0 || --obj->ref == 0) {
+ uic_context_prepare_close(obj->ctx);
if(obj->destroy) {
obj->destroy(obj);
} else {
obj->window = windowdata;
}
+void ui_object_set_onclose(UiObject *obj, ui_callback callback, void *userdata) {
+ obj->onclose = callback;
+ obj->onclosedata = userdata;
+}
+
/* ---------------------------- UiList ---------------------------- */
UIEXPORT UiContext* ui_object_get_context(UiObject *obj);
UIEXPORT void* ui_object_get_windowdata(UiObject *obj);
UIEXPORT void ui_object_set_windowdata(UiObject *obj, void *windowdata);
+UIEXPORT void ui_object_set_onclose(UiObject *obj, ui_callback callback, void *userdata);
UIEXPORT void* ui_list_get_data(UiList *list);
UIEXPORT void* ui_list_get_iter(UiList *list);
void ui_show(UiObject *obj) {
gboolean visible = FALSE;
- uic_check_state_widgets(obj->ctx);
if(obj->widget) {
visible = gtk_widget_is_visible(obj->widget);
#if GTK_MAJOR_VERSION >= 4
gtk_widget_show_all(obj->widget);
#endif
}
+ uic_check_state_widgets(obj->ctx);
if(!visible) {
obj->ref++;
}
void ui_close(UiObject *obj) {
- uic_context_prepare_close(obj->ctx); // TODO: should this be moved to the close event handler? Yes!
- /*
- if(obj->widget) {
-#if GTK_CHECK_VERSION(4, 0, 0)
- gtk_window_close(GTK_WINDOW(obj->widget));
-#else
- gtk_widget_destroy(obj->widget);
-#endif
- } else {
- ui_window_close_request(obj);
- }
- */
ui_window_close_request(obj);
}
}
}
- obj->ref--;
+ if(obj->ref > 0) {
+ obj->ref--;
+ } else {
+ // warn about invalid reference counting
+ fprintf(stderr, "Error: UiObject %p ref == 0\n", obj);
+ }
if(obj->ref > 0) {
#if GTK_CHECK_VERSION(2, 18, 0)
gtk_widget_set_visible(obj->widget, FALSE);
#endif
return TRUE;
} else {
- if(obj->ctx->close_callback) {
- UiEvent ev;
- ev.window = obj->window;
- ev.document = obj->ctx->document;
- ev.obj = obj;
- ev.eventdata = NULL;
- ev.eventdatatype = 0;
- ev.intval = 0;
- obj->ctx->close_callback(&ev, obj->ctx->close_data);
- obj->ctx->close_callback = NULL;
- }
-
uic_context_prepare_close(obj->ctx);
return FALSE;
}
}
+static void window_onclose_callback(UiObject *obj) {
+ if(obj->onclose) {
+ UiEvent event;
+ memset(&event, 0, sizeof(UiEvent));
+ event.obj = obj;
+ event.window = obj->window;
+ event.document = obj->ctx->document;
+ obj->onclose(&event, obj->onclosedata);
+ }
+}
+
#if GTK_MAJOR_VERSION >= 4
static gboolean close_request(GtkWindow* self, UiObject *obj) {
+ window_onclose_callback(obj);
return ui_window_close_request(obj);
}
#else
static gboolean close_request(GtkWidget* self, GdkEvent* event, UiObject *obj) {
+ window_onclose_callback(obj);
return ui_window_close_request(obj);
}
#endif
adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
} else if(!strcmp(show_title, "sidebar")) {
adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_main), FALSE);
- adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), TRUE);
+ if(headerbar_sidebar) {
+ adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), TRUE);
+ }
} else if(!strcmp(show_title, "false")) {
- adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
+ if(headerbar_sidebar) {
+ adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
+ }
adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_main), FALSE);
} else {
fprintf(stderr, "Unknown value '%s' for property ui.gtk.window.showtitle\n", show_title);
- adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
+ if(headerbar_sidebar) {
+ adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), FALSE);
+ }
}
} else {
adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_main), FALSE);
- if(sidebar) {
+ if(headerbar_sidebar) {
adw_header_bar_set_show_title(ADW_HEADER_BAR(headerbar_sidebar), TRUE);
}
}
static UiObject* create_window(const char *title, bool simple, bool sidebar = false) {
UiObject *obj = uic_object_new_toplevel();
- obj->next = NULL;
QMainWindow *window = new QMainWindow();
window->setWindowTitle(title);
UiContainer *container_end;
/*
- * next container object
+ * called when someone requests to close the window
*/
- UiObject *next;
+ void (*onclose)(UiEvent *event, void *userdata);
+ void *onclosedata;
/*
* obj destroy func