Fri, 15 Nov 2024 21:16:18 +0100
add UiObject reference counting (GTK)
/* * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. * * Copyright 2017 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. */ #include <stdio.h> #include <stdlib.h> #include <ui/ui.h> #include <cx/buffer.h> #include <cx/utils.h> typedef struct { UiString *str1; UiString *str2; UiString *path; UiText *text; UiDouble *progress; UiList *list; UiList *menulist; UiInteger *radio; UiInteger *tabview; UiGeneric *image; } MyDocument; MyDocument *doc1; MyDocument *doc2; UIWIDGET tabview; static UiCondVar *cond; static int thr_end = 0; static int thr_started = 0; int threadfunc(void *data) { printf("thr wait for data...\n"); ui_condvar_wait(cond); printf("thr data received: {%s} [%d]\n", cond->data, cond->intdata); ui_condvar_destroy(cond); cond = NULL; return 0; } void action_start_thread(UiEvent *event, void *data) { if(!thr_started) { cond = ui_condvar_create(); ui_job(event->obj, threadfunc, NULL, NULL, NULL); thr_started = 1; } } void action_notify_thread(UiEvent *event, void *data) { if(!thr_end) { ui_condvar_signal(cond, "hello thread", 123); thr_end = 1; } } void action_menu(UiEvent *event, void *userdata) { } void action_file_selected(UiEvent *event, void *userdata) { UiFileList *files = event->eventdata; MyDocument *doc = event->document; printf("files: %d\n", (int)files->nfiles); if(files->nfiles > 0) { printf("selected file: %s\n", files->files[0]); ui_image_load_file(doc->image, files->files[0]); } } void action_button(UiEvent *event, void *userdata) { ui_openfiledialog(event->obj, UI_FILEDIALOG_SELECT_SINGLE, action_file_selected, NULL); } void action_switch(UiEvent *event, void *userdata) { } void action_toolbar_button(UiEvent *event, void *userdata) { printf("toolbar button\n"); ui_dialog(event->obj, .title = "Dialog Title", .content = "Content Label", .button1_label = "btn1", .button2_label = "btn2", .input = TRUE, .closebutton_label = "Cancel"); } void action_dialog_button(UiEvent *event, void *userdata) { ui_close(event->obj); } void action_toolbar_dialog(UiEvent *event, void *userdata) { UiObject *dialog = ui_dialog_window(event->obj, .title = "Dialog Window", .lbutton1 = "Cancel 1", .lbutton2 = "Btn2", .rbutton3 = "Btn3", .rbutton4 = "Login 4", .onclick = action_dialog_button, .default_button = 4, .show_closebutton = UI_OFF); ui_vbox(dialog, .margin = 10, .spacing = 10) { ui_label(dialog, .label = "Enter password:"); ui_passwordfield(dialog, .varname = "password"); } ui_show(dialog); } void action_toolbar_newwindow(UiEvent *event, void *userdata) { UiObject *obj = ui_simple_window("New Window", NULL); ui_headerbar0(obj) { ui_headerbar_start(obj) { ui_button(obj, .label = "Open"); } ui_headerbar_end(obj) { ui_button(obj, .label = "Test"); } } ui_textarea(obj, .varname="text"); ui_show(obj); } MyDocument* create_doc(void) { MyDocument *doc = ui_document_new(sizeof(MyDocument)); UiContext *docctx = ui_document_context(doc); doc->str1 = ui_string_new(docctx, "str1"); doc->str1 = ui_string_new(docctx, "str2"); doc->path = ui_string_new(docctx, "path"); doc->progress = ui_double_new(docctx, "progress"); doc->list = ui_list_new(docctx, "list"); ui_list_append(doc->list, "test1"); ui_list_append(doc->list, "test2"); ui_list_append(doc->list, "test3"); doc->radio = ui_int_new(docctx, "radio"); doc->tabview = ui_int_new(docctx, "tabview"); doc->image = ui_generic_new(docctx, "image"); //doc->text = ui_text_new(docctx, "text"); return doc; } UiIcon *icon = NULL; static void* list_getvalue(void *elm, int col) { /* if(col == 0) { if(!icon) { icon = ui_icon("folder", 24); } return icon; } */ char *str = elm; return col == 0 ? str : "x"; } static UiList *menu_list; int new_item_count = 0; void action_add_menu_item(UiEvent *event, void *userdata) { char str[64]; snprintf(str, 64, "new item %d", new_item_count++); ui_list_append(menu_list, strdup(str)); ui_list_notify(menu_list); } void action_menu_list(UiEvent *event, void *userdata) { printf("menu list item: %d\n", event->intval); } static int tab_x = 0; void action_tab2_button(UiEvent *event, void *userdata) { MyDocument *doc = event->document; printf("current page: %d\n", (int)ui_get(doc->tabview)); ui_set(doc->tabview, 0); } void action_group1(UiEvent *event, void *userdata) { UiContext *ctx = event->obj->ctx; if(userdata) { ui_unset_group(ctx, 1); } else { ui_set_group(ctx, 1); } } void action_group2(UiEvent *event, void *userdata) { UiContext *ctx = event->obj->ctx; if(userdata) { ui_unset_group(ctx, 2); } else { ui_set_group(ctx, 2); } } static UiObject *ref_window; void action_button_ref(UiEvent *event, void *userdata) { UiObject *obj = event->obj; printf("action_button_ref: %u\n", obj->ref); ui_object_ref(obj); ref_window = obj; } void action_button_unref(UiEvent *event, void *userdata) { UiObject *obj = userdata; printf("action_button_unref: %u\n", obj->ref); ui_object_unref(obj); } void action_toolbar_unrefwindow(UiEvent *event, void *userdata) { UiObject *obj = ui_simple_window("Unref", NULL); ui_grid(obj, .margin = 20) { ui_button(obj, .label = "Unref", .onclick = action_button_unref, .onclickdata = ref_window); } ui_show(obj); } void application_startup(UiEvent *event, void *data) { // global list UiContext *global = ui_global_context(); menu_list = ui_list_new(global, "menulist"); ui_list_append(menu_list, "menu list item 1"); ui_list_append(menu_list, "menu list item 2"); ui_list_append(menu_list, "menu list item 3"); UiObject *obj = ui_window("Test", NULL); MyDocument *doc = create_doc(); ui_attach_document(obj->ctx, doc); ui_tabview(obj, .spacing=10, .margin=10, .tabview = UI_TABVIEW_NAVIGATION_SIDE, .varname="tabview") { ui_tab(obj, "Tab 1") { ui_vbox(obj, .fill = UI_OFF, .margin = 15, .spacing = 15) { ui_button(obj, .label = "Test Button", .icon = "application-x-generic", .onclick = action_button); ui_togglebutton(obj, .label = "Toggle"); ui_checkbox(obj, .label = "My Checkbox"); } ui_grid(obj, .fill = UI_OFF, .columnspacing = 15, .rowspacing = 15, .margin = 15) { ui_button(obj, .label = "Activate Group 1", .hexpand = TRUE, .onclick = action_group1); ui_button(obj, .label = "Disable Group 1", .onclick = action_group1, .onclickdata = "disable"); ui_newline(obj); ui_button(obj, .label = "Activate Group 2", .hexpand = TRUE, .onclick = action_group2); ui_button(obj, .label = "Disable Group 2", .onclick = action_group2, .onclickdata = "disable"); ui_newline(obj); ui_button(obj, .label = "Groups 1,2", .colspan = 2, .groups = UI_GROUPS(1, 2)); ui_newline(obj); ui_label(obj, .label = "Label Col 1", .align = UI_ALIGN_LEFT); ui_label(obj, .label = "Label Col 2", .style = UI_LABEL_STYLE_TITLE, .align = UI_ALIGN_RIGHT); ui_newline(obj); ui_spinner(obj, .step = 5); ui_newline(obj); ui_progressbar(obj, .colspan = 2, .varname = "progress"); ui_set(doc->progress, 0.75); ui_newline(obj); ui_textfield(obj, .value = doc->str1); ui_newline(obj); //ui_button(obj, .label="Test"); ui_path_textfield(obj, .varname = "path"); ui_set(doc->path, "/test/path/longdirectoryname/123"); ui_newline(obj); //UiModel *model = ui_model(obj->ctx, UI_ICON_TEXT, "Col 1", UI_STRING, "Col 2", -1); //model->getvalue = list_getvalue; ui_combobox(obj, .hexpand = true, .vexpand = false, .colspan = 2, .varname = "list", .getvalue = list_getvalue); ui_newline(obj); ui_hbox0(obj) { ui_radiobutton(obj, .label = "Radio 1", .varname = "radio"); ui_radiobutton(obj, .label = "Radio 2", .varname = "radio"); ui_radiobutton(obj, .label = "Radio 3", .varname = "radio"); } } } ui_tab(obj, "Tab 2") { ui_button(obj, .label = "Button 1 Start Thread", .onclick=action_start_thread); ui_button(obj, .label = "Button 2 Notify Thread", .onclick=action_notify_thread); ui_button(obj, .label = "Obj Ref", .onclick=action_button_ref); ui_button(obj, .label = "Obj Unref", .onclick=action_button_unref, .onclickdata = obj); ui_button(obj, .label = "Button 5", .onclick=action_tab2_button); ui_button(obj, .label = "Button 6", .onclick=action_tab2_button); } ui_tab(obj, "Tab 3") { UiTabViewArgs args = {0}; UI_CTN(obj, tabview=ui_tabview_create(obj, args)) { UiObject *tab1 = ui_tabview_add(tabview, "Sub 1", -1); ui_button(tab1, .label = "Button 1"); UiObject *tab2 = ui_tabview_add(tabview, "Sub 2", -1); ui_button(tab2, .label = "Button 2"); } } ui_tab(obj, "Tab 4") { ui_textarea(obj, .varname = "text"); } ui_tab(obj, "Tab 5") { ui_button(obj, .label = "Test Button", .icon = "application-x-generic", .onclick = action_button); ui_imageviewer(obj, .varname = "image", .style_class = "imageviewer"); } ui_tab(obj, "Tab 6") { ui_scrolledwindow(obj, .fill = UI_ON) { ui_expander(obj, .label = "Expander", .margin = 10, .spacing = 10) { ui_label(obj, .label = "Test"); ui_button(obj, .label = "Button"); } ui_frame(obj, .label = "Frame", .margin = 10, .spacing = 10) { ui_label(obj, .label = "Title", .style = UI_LABEL_STYLE_TITLE); ui_label(obj, .label = "Sub-Title", .style = UI_LABEL_STYLE_SUBTITLE); ui_label(obj, .label = "Dim Label", .style = UI_LABEL_STYLE_DIM); ui_label(obj, .label = "No Style"); } for(int i=0;i<100;i++) { char labelstr[32]; snprintf(labelstr, 32, "button %d", i); ui_button(obj, .label = labelstr); } } } } /* */ ui_show(obj); } int main(int argc, char** argv) { ui_init("app1", argc, argv); ui_onstartup(application_startup, NULL); // menu ui_menu("File") { ui_menuitem(.label = "Test"); } ui_toolbar_item("Test", .label = "Test", .onclick = action_toolbar_button); ui_toolbar_item("Test2", .label = "New Window", .onclick = action_toolbar_newwindow); ui_toolbar_item("Test3", .label = "Dialog", .onclick = action_toolbar_dialog); ui_toolbar_item("Test4", .label = "Unref Window", .onclick = action_toolbar_unrefwindow); ui_toolbar_item("Test5", .label = "Test 5", .onclick = action_toolbar_button); ui_toolbar_item("Test6", .label = "Test 6", .onclick = action_toolbar_button); ui_toolbar_toggleitem("Toggle", .label = "Toggle", .onchange = action_toolbar_button); ui_toolbar_menu("Menu", .label = "Menu") { ui_menuitem("Secondary Test", .onclick = action_toolbar_button, NULL); ui_menu("Secondary Sub") { ui_menuitem("Secondary subitem", NULL, NULL); } ui_menuseparator(); ui_menu_itemlist(.varname = "menulist", .onselect=action_menu_list); ui_menuseparator(); ui_menuitem("last", .onclick = action_add_menu_item); } ui_toolbar_appmenu() { ui_menuitem("New"); ui_menuitem("Open"); ui_menuitem("Save"); ui_menuseparator(); ui_menuitem("Close"); } ui_toolbar_add_default("Test", UI_TOOLBAR_LEFT); ui_toolbar_add_default("Test6", UI_TOOLBAR_LEFT); ui_toolbar_add_default("Toggle", UI_TOOLBAR_LEFT); ui_toolbar_add_default("Menu", UI_TOOLBAR_LEFT); ui_toolbar_add_default("Test2", UI_TOOLBAR_CENTER); ui_toolbar_add_default("Test3", UI_TOOLBAR_CENTER); ui_toolbar_add_default("Test4", UI_TOOLBAR_RIGHT); ui_toolbar_add_default("Test5", UI_TOOLBAR_RIGHT); ui_main(); return (EXIT_SUCCESS); }