From: Olaf Wintermann Date: Thu, 4 Jun 2026 18:36:49 +0000 (+0200) Subject: save selection when switching notebooks X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;h=HEAD;p=note.git save selection when switching notebooks --- diff --git a/ui-rs/src/ui/toolkit.rs b/ui-rs/src/ui/toolkit.rs index b36bf72..394626b 100644 --- a/ui-rs/src/ui/toolkit.rs +++ b/ui-rs/src/ui/toolkit.rs @@ -835,6 +835,24 @@ impl UiList { ui_list_setselection2(self.ptr, index, trigger_event as i32); } } + + pub fn set_save_selection(&mut self, enable: bool) { + unsafe { + ui_list_set_save_selection(self.ptr, enable as c_int); + } + } + + pub fn get_save_selection(&self) -> bool { + unsafe { + ui_list_get_save_selection(self.ptr) != 0 + } + } + + pub fn clear_saved_selection(&mut self) { + unsafe { + ui_list_clear_saved_selection(self.ptr); + } + } } impl Drop for UiList { @@ -1223,6 +1241,9 @@ extern "C" { pub fn ui_list_get_data(list: *const ffi::UiList) -> *mut c_void; fn ui_list_get_iter(list: *mut ffi::UiList) -> *mut c_void; fn ui_list_set_iter(list: *mut ffi::UiList, iter: *mut c_void); + fn ui_list_set_save_selection(list: *mut ffi::UiList, value: c_int); + fn ui_list_get_save_selection(list: *const ffi::UiList) -> c_int; + fn ui_list_clear_saved_selection(list: *mut ffi::UiList); fn ui_list_update(list: *mut ffi::UiList); fn ui_list_update_row(list: *mut ffi::UiList, row: c_int); diff --git a/ui/common/Makefile b/ui/common/Makefile new file mode 100644 index 0000000..703da14 --- /dev/null +++ b/ui/common/Makefile @@ -0,0 +1,111 @@ +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. +# +# Copyright 2012 Olaf Wintermann. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +FORCE: + +$(COMMON_OBJPRE)uic_action$(OBJ_EXT): common/action.c common/action.h \ + common/../ui/toolkit.h common/context.h common/object.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + +$(COMMON_OBJPRE)uic_app$(OBJ_EXT): common/app.c common/app.h \ + common/../ui/toolkit.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + +$(COMMON_OBJPRE)uic_args$(OBJ_EXT): common/args.c common/args.h \ + common/../ui/window.h common/../ui/toolkit.h common/../ui/container.h \ + common/../ui/display.h common/../ui/button.h common/../ui/entry.h \ + common/../ui/menu.h common/../ui/toolbar.h common/../ui/list.h \ + common/../ui/text.h common/../ui/webview.h common/../ui/widget.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + +$(COMMON_OBJPRE)uic_condvar$(OBJ_EXT): common/condvar.c common/condvar.h \ + common/../ui/toolkit.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + +$(COMMON_OBJPRE)uic_container$(OBJ_EXT): common/container.c \ + common/container.h common/../ui/container.h common/../ui/toolkit.h \ + common/object.h common/../ui/toolkit.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + +$(COMMON_OBJPRE)uic_context$(OBJ_EXT): common/context.c common/context.h \ + common/../ui/toolkit.h common/action.h common/../ui/window.h \ + common/../ui/toolkit.h common/../ui/widget.h common/document.h \ + common/types.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + +$(COMMON_OBJPRE)uic_document$(OBJ_EXT): common/document.c \ + common/document.h common/../ui/toolkit.h common/context.h \ + common/action.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + +$(COMMON_OBJPRE)uic_icons$(OBJ_EXT): common/icons.c common/icons.h \ + common/../ui/icons.h common/../ui/toolkit.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + +$(COMMON_OBJPRE)uic_menu$(OBJ_EXT): common/menu.c common/menu.h \ + common/../ui/menu.h common/../ui/toolkit.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + +$(COMMON_OBJPRE)uic_message$(OBJ_EXT): common/message.c common/message.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + +$(COMMON_OBJPRE)uic_object$(OBJ_EXT): common/object.c common/object.h \ + common/../ui/toolkit.h common/context.h common/action.h \ + common/../ui/container.h common/../ui/toolkit.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + +$(COMMON_OBJPRE)uic_properties$(OBJ_EXT): common/properties.c \ + common/../ui/toolkit.h common/properties.h common/../ui/properties.h \ + common/../ui/toolkit.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + +$(COMMON_OBJPRE)uic_threadpool$(OBJ_EXT): common/threadpool.c \ + common/threadpool.h common/../ui/toolkit.h common/context.h \ + common/action.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + +$(COMMON_OBJPRE)uic_toolbar$(OBJ_EXT): common/toolbar.c common/toolbar.h \ + common/../ui/toolbar.h common/../ui/toolkit.h common/menu.h \ + common/../ui/menu.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + +$(COMMON_OBJPRE)uic_types$(OBJ_EXT): common/types.c common/../ui/list.h \ + common/../ui/toolkit.h common/types.h common/../ui/toolkit.h \ + common/context.h common/action.h common/../ui/image.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + +$(COMMON_OBJPRE)uic_utils$(OBJ_EXT): common/utils.c common/utils.h \ + common/../ui/toolkit.h common/../ui/text.h common/../ui/toolkit.h \ + common/properties.h common/../ui/properties.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + +$(COMMON_OBJPRE)uic_wrapper$(OBJ_EXT): common/wrapper.c common/wrapper.h \ + common/../ui/toolkit.h common/../ui/list.h common/../ui/toolkit.h \ + common/../ui/text.h common/types.h + $(CC) -o $@ $(CFLAGS) -I../ucx $(SHLIB_CFLAGS) $(TK_CFLAGS) -c $< + diff --git a/ui/common/context.c b/ui/common/context.c index b369578..c2eb53d 100644 --- a/ui/common/context.c +++ b/ui/common/context.c @@ -71,9 +71,6 @@ UiContext* uic_context(UiObject *toplevel, CxMempool *mp) { ctx->actions = cxHashMapCreate(ctx->allocator, sizeof(UiAction), 8); ctx->action_bindings = cxArrayListCreate(ctx->allocator, sizeof(UiActionBinding), 0); - ctx->attach_document = uic_context_attach_document; - ctx->detach_document2 = uic_context_detach_document; - #if UI_GTK2 || UI_GTK3 if(toplevel && toplevel->widget) { ctx->accel_group = gtk_accel_group_new(); @@ -141,29 +138,20 @@ void uic_context_destroy(UiContext *ctx, void *document) { cxMempoolFree(ctx->mp); } -void uic_context_attach_document(UiContext *ctx, void *document) { - if(ctx->single_document_mode) { - if(ctx->document) { - uic_context_detach_document(ctx, ctx->document); - } - } - - cxListAdd(ctx->documents, document); - ctx->document = document; - - UiContext *doc_ctx = ui_document_context(document); - doc_ctx->parent = ctx; - doc_ctx->ref++; - +void uic_context_update_bindings(UiContext *ctx) { + int onchange_enabled = ui_onchange_events_is_enabled(); + int onselection_enabled = ui_selection_events_is_enabled(); + ui_onchange_events_enable(FALSE); + ui_selection_events_enable(FALSE); // if a document variable has the same name as a parent variable, // move the bindings to the document - UiContext *var_ctx = ctx; + UiContext *var_ctx = ctx->parent; while(var_ctx) { CxMapIterator i = cxMapIterator(var_ctx->vars); cx_foreach(CxMapEntry*, entry, i) { - printf("attach %.*s\n", (int)entry->key->len, (char*)entry->key->data); + // printf("attach %.*s\n", (int)entry->key->len, (char*)entry->key->data); UiVar *var = entry->value; - UiVar *docvar = cxMapGet(doc_ctx->vars, *entry->key); + UiVar *docvar = cxMapGet(ctx->vars, *entry->key); if(docvar) { // bind var to document var uic_copy_var_binding(var, docvar, TRUE); @@ -175,13 +163,43 @@ void uic_context_attach_document(UiContext *ctx, void *document) { } ui_update_action_bindings(ctx); + + if(ctx->documents) { + CxIterator i = cxListIterator(ctx->documents); + cx_foreach(void *, doc, i) { + UiContext *subctx = ui_document_context(doc); + uic_context_update_bindings(subctx); + } + } + ui_onchange_events_enable(onchange_enabled); + ui_selection_events_enable(onselection_enabled); +} + +void uic_context_attach_document(UiContext *ctx, void *document) { + if(ctx->single_document_mode) { + if(ctx->document) { + uic_context_detach_document(ctx, ctx->document); + } + } + + cxListAdd(ctx->documents, document); + ctx->document = document; + + UiContext *doc_ctx = ui_document_context(document); + doc_ctx->parent = ctx; + doc_ctx->ref++; + + uic_context_update_bindings(doc_ctx); } static void uic_context_unbind_vars(UiContext *ctx) { + int onchange_enabled = ui_onchange_events_is_enabled(); + int onselection_enabled = ui_selection_events_is_enabled(); ui_onchange_events_enable(FALSE); + ui_selection_events_enable(FALSE); CxMapIterator mi = cxMapIterator(ctx->vars); cx_foreach(CxMapEntry*, entry, mi) { - printf("detach %.*s\n", (int)entry->key->len, (char*)entry->key->data); + //printf("detach %.*s\n", (int)entry->key->len, (char*)entry->key->data); UiVar *var = entry->value; // var->from && var->from_ctx && var->from_ctx != ctx uic_save_var(var); @@ -201,7 +219,8 @@ static void uic_context_unbind_vars(UiContext *ctx) { } } - ui_onchange_events_enable(TRUE); + ui_onchange_events_enable(onchange_enabled); + ui_selection_events_enable(onselection_enabled); } void uic_context_detach_document(UiContext *ctx, void *document) { @@ -233,7 +252,7 @@ void uic_context_detach_all(UiContext *ctx) { // detach documents i = cxListIterator(ls); cx_foreach(void *, doc, i) { - ctx->detach_document2(ctx, doc); + uic_context_detach_document(ctx, doc); } cxListFree(ls); @@ -455,8 +474,21 @@ void uic_copy_value_binding(UiVarType type, void *from, void *to) { case UI_VAR_LIST: { UiList *f = from; UiList *t = to; + // save selection + ui_list_selection_free(f->saved_selection); + if(f->getselection && f->save_selection) { + f->saved_selection = ui_list_get_selection_allocated(f); + } else { + f->saved_selection = NULL; + } + uic_list_copy(f, t); ui_list_update(t); + if(t->setselection && t->saved_selection) { + t->setselection(t, *t->saved_selection); + } + ui_list_selection_free(t->saved_selection); + t->saved_selection = NULL; break; } case UI_VAR_RANGE: { diff --git a/ui/common/context.h b/ui/common/context.h index d692f16..75be090 100644 --- a/ui/common/context.h +++ b/ui/common/context.h @@ -80,9 +80,6 @@ struct UiContext { CxMap *actions; // key: action name (string), value: UiAction CxList *action_bindings; // UiActionBinding list - void (*attach_document)(UiContext *ctx, void *document); - void (*detach_document2)(UiContext *ctx, void *document); - char *title; #ifdef UI_GTK @@ -139,6 +136,7 @@ void uic_context_remove_destructor(UiContext *ctx, void *data); void uic_context_prepare_close(UiContext *ctx); void uic_context_destroy(UiContext *ctx, void *document); +void uic_context_update_bindings(UiContext *ctx); void uic_context_attach_document(UiContext *ctx, void *document); void uic_context_detach_document(UiContext *ctx, void *document); void uic_context_attach_context(UiContext *ctx, UiContext *doc_ctx); // TODO diff --git a/ui/common/types.c b/ui/common/types.c index 7105af5..bd4d384 100644 --- a/ui/common/types.c +++ b/ui/common/types.c @@ -121,6 +121,7 @@ UiList* ui_list_new2(UiContext *ctx, const char *name, ui_list_init_func listini UiList *list = ui_malloc(ctx, sizeof(UiList)); memset(list, 0, sizeof(UiList)); listinit(ctx, list, userdata); + list->save_selection = TRUE; if(name && ctx) { uic_reg_var(ctx, name, UI_VAR_LIST, list); @@ -137,6 +138,7 @@ void ui_list_free(UiContext *ctx, UiList *list) { } else { default_list_destroy(ctx, list, default_list_destroy_userdata); } + ui_list_selection_free(list->saved_selection); ui_free(ctx, list); } @@ -219,6 +221,11 @@ void ui_list_notify(UiList *list) { ui_notify(list->observers, list); } +void ui_list_clear_saved_selection(UiList *list) { + ui_list_selection_free(list->saved_selection); + list->saved_selection = NULL; +} + typedef struct { int type; @@ -806,6 +813,15 @@ void uic_range_unbind(UiRange *r) { } void uic_list_unbind(UiList *l) { + // save selection + ui_list_selection_free(l->saved_selection); + if(l->getselection && l->save_selection) { + l->saved_selection = ui_list_get_selection_allocated(l); + } else { + l->saved_selection = NULL; + } + + // unbind l->update = NULL; l->getselection = NULL; l->setselection = NULL; @@ -820,6 +836,23 @@ void uic_generic_unbind(UiGeneric *g) { } + +UiListSelection* ui_list_get_selection_allocated(UiList *list) { + UiListSelection *sel = malloc(sizeof(UiListSelection)); + *sel = ui_list_get_selection(list); + return sel; + +} + +void ui_list_selection_free(UiListSelection *sel) { + if(!sel) { + return; + } + ui_listselection_free(*sel); + free(sel); +} + + UIEXPORT int ui_list_getselection(UiList *list) { int selection = -1; if (list->getselection) { diff --git a/ui/common/types.h b/ui/common/types.h index 2f4a524..8723ce0 100644 --- a/ui/common/types.h +++ b/ui/common/types.h @@ -61,6 +61,9 @@ void uic_range_unbind(UiRange *r); void uic_list_unbind(UiList *l); void uic_generic_unbind(UiGeneric *g); +UIEXPORT UiListSelection* ui_list_get_selection_allocated(UiList *list); +UIEXPORT void ui_list_selection_free(UiListSelection *sel); + void uic_list_register_observer_destructor(UiContext *ctx, UiList *list, UiObserver *observer); #ifdef __cplusplus diff --git a/ui/common/wrapper.c b/ui/common/wrapper.c index 675c688..56194e8 100644 --- a/ui/common/wrapper.c +++ b/ui/common/wrapper.c @@ -98,6 +98,13 @@ void ui_list_set_iter(UiList *list, void *iter) { list->iter = iter; } +void ui_list_set_save_selection(UiList *list, UiBool value) { + list->save_selection = value; +} + +UiBool ui_list_get_save_selection(UiList *list) { + return list->save_selection; +} /* ------------------------------ UiSublist ------------------------------ */ @@ -275,13 +282,6 @@ void ui_sublist_item_set_eventdata(UiSubListItem *item, void *eventdata) { /* ---------------------------- UiListSelection ---------------------------- */ -UiListSelection* ui_list_get_selection_allocated(UiList *list) { - UiListSelection *sel = malloc(sizeof(UiListSelection)); - *sel = ui_list_get_selection(list); - return sel; - -} - int ui_list_selection_get_count(UiListSelection *sel) { return sel->count; } @@ -299,10 +299,6 @@ UIEXPORT void ui_list_set_selected_indices(UiList *list, int *indices, int num) } } -void ui_list_selection_free(UiListSelection *sel) { - ui_listselection_free(*sel); - free(sel); -} /* -------------------------- UiTextChangedEvent -------------------------- */ diff --git a/ui/common/wrapper.h b/ui/common/wrapper.h index eff3282..6f7507c 100644 --- a/ui/common/wrapper.h +++ b/ui/common/wrapper.h @@ -49,6 +49,8 @@ UIEXPORT void ui_mainthread_app_unref(); UIEXPORT void* ui_list_get_data(UiList *list); UIEXPORT void* ui_list_get_iter(UiList *list); UIEXPORT void ui_list_set_iter(UiList *list, void *iter); +UIEXPORT void ui_list_set_save_selection(UiList *list, UiBool value); +UIEXPORT UiBool ui_list_get_save_selection(UiList *list); UIEXPORT UiSubList* ui_sublist_new(void); UIEXPORT void ui_sublist_set_value(UiSubList *sublist, UiList *value); @@ -82,11 +84,9 @@ UIEXPORT int ui_event_get_eventdatatype(UiEvent *event); UIEXPORT int ui_event_get_int(UiEvent *event); UIEXPORT int ui_event_get_set(UiEvent *event); -UIEXPORT UiListSelection* ui_list_get_selection_allocated(UiList *list); UIEXPORT int ui_list_selection_get_count(UiListSelection *sel); UIEXPORT int* ui_list_selection_get_rows(UiListSelection *sel); UIEXPORT void ui_list_set_selected_indices(UiList *list, int *indices, int num); -UIEXPORT void ui_list_selection_free(UiListSelection *sel); UIEXPORT int ui_text_change_event_get_type(UiTextChangeEventData *event); UIEXPORT int ui_text_change_event_get_begin(UiTextChangeEventData *event); diff --git a/ui/gtk/list.c b/ui/gtk/list.c index fd68671..7214687 100644 --- a/ui/gtk/list.c +++ b/ui/gtk/list.c @@ -938,6 +938,9 @@ void ui_listview_update2(UiList *list, int i) { if(i < 0) { cxMapClear(view->bound_rows); ui_update_liststore(view->liststore, list); + free(view->selection.rows); + view->selection.rows = NULL; + view->selection.count = 0; } else { void *value = list->get(list, i); if(value) { diff --git a/ui/ui/toolkit.h b/ui/ui/toolkit.h index 0184d85..0e89071 100644 --- a/ui/ui/toolkit.h +++ b/ui/ui/toolkit.h @@ -419,29 +419,33 @@ typedef void (*ui_list_destroy_func)(UiContext *ctx, UiList *list, void *userdat * abstract list */ struct UiList { - /* destructor */ + // destructor ui_list_destroy_func destroy; - /* get the first element */ + // get the first element void*(*first)(UiList *list); - /* get the next element */ + // get the next element void*(*next)(UiList *list); - /* get the nth element */ + // get the nth element void*(*get)(UiList *list, int i); - /* get the number of elements */ + // get the number of elements int(*count)(UiList *list); - /* iterator changes after first() next() and get() */ + // iterator changes after first() next() and get() void *iter; - /* private - implementation dependent */ + // private - implementation dependent void *data; - /* binding functions */ + // binding functions void (*update)(UiList *list, int i); UiListSelection (*getselection)(UiList *list); void (*setselection)(UiList *list, UiListSelection selection); - /* binding object */ + // binding object void *obj; + // saved selection after unbind + UiListSelection *saved_selection; + // enable selection saving + UiBool save_selection; - /* list of observers */ + // list of observers UiObserver *observers; }; @@ -695,6 +699,7 @@ UIEXPORT UiListSelection ui_list_get_selection(UiList *list); UIEXPORT void ui_list_set_selection(UiList *list, UiListSelection sel); UIEXPORT void ui_list_addobsv(UiList *list, ui_callback f, void *data); UIEXPORT void ui_list_notify(UiList *list); +UIEXPORT void ui_list_clear_saved_selection(UiList *list); UIEXPORT int ui_list_getselection(UiList *list); UIEXPORT void ui_list_setselection(UiList *list, int index);