From: Olaf Wintermann Date: Mon, 17 Mar 2025 11:23:18 +0000 (+0100) Subject: implement paragraph style changes via dropdown menu X-Git-Url: https://uap-core.de/gitweb/?a=commitdiff_plain;h=5161be116796550a9b0f8177bd5d7168598e306a;p=note.git implement paragraph style changes via dropdown menu --- diff --git a/application/editor.h b/application/editor.h index 11c798f..bab1836 100644 --- a/application/editor.h +++ b/application/editor.h @@ -128,6 +128,7 @@ void editor_apply_styles(UiText *text, CxList /* MDDocStyleSection */ *styles); cxmutstr editor_get_markdown(UiText *text, const CxAllocator *a); UiBool editor_set_style(UiText *text, const char *style, UiBool enabled); +void editor_set_paragraph_style(UiText *text, const char *style); #ifdef __cplusplus } diff --git a/application/gtk-text.c b/application/gtk-text.c index 4702038..fb55168 100644 --- a/application/gtk-text.c +++ b/application/gtk-text.c @@ -123,17 +123,9 @@ static void editor_button_released_cb( } } -static void editor_set_cursor_cb( - GtkTextBuffer *buffer, - const GtkTextIter *location, - GtkTextMark *mark, - NoteEditor *editor) -{ - const char *mark_name = gtk_text_mark_get_name(mark); - if(!mark_name || strcmp(mark_name, "insert")) { - return; - } - +// update the paragraph style dropdown list to the style of the current +// cursor position +static void update_cursor_paragraph_style(NoteEditor *editor, GtkTextBuffer *buffer) { GtkTextIter pos; // get current tags // when the buffer has a selection, get the tags from the selection start @@ -163,6 +155,20 @@ static void editor_set_cursor_cb( } } +static void editor_set_cursor_cb( + GtkTextBuffer *buffer, + const GtkTextIter *location, + GtkTextMark *mark, + NoteEditor *editor) +{ + const char *mark_name = gtk_text_mark_get_name(mark); + if(!mark_name || strcmp(mark_name, "insert")) { + return; + } + + update_cursor_paragraph_style(editor, buffer); +} + void editor_try_follow_link(NoteEditor *editor, GtkTextIter *pos) { GSList *tags = gtk_text_iter_get_tags(pos); while(tags) { @@ -316,7 +322,7 @@ void init_tagtable(GtkTextTagTable *table) { gtk_text_tag_table_add(table, tag); tag = gtk_text_tag_new(EDITOR_STYLE_CODE_BLOCK); - g_object_set(tag, "family", "Monospace", "paragraph-background", "#080808", NULL); + g_object_set(tag, "family", "Monospace", "paragraph-background", "#efefef", NULL); g_object_set_data(G_OBJECT(tag), "set_style", (void*)tagstyle_codeblock); gtk_text_tag_table_add(table, tag); @@ -514,3 +520,48 @@ UiBool editor_set_style(UiText *text, const char *style, UiBool enabled) { return TRUE; } + +static void remove_paragraph_styles(GtkTextBuffer *buffer, GtkTextIter *begin, GtkTextIter *end) { + char *para[] = { + EDITOR_STYLE_PARAGRAPH, + EDITOR_STYLE_HEADING1, + EDITOR_STYLE_HEADING2, + EDITOR_STYLE_HEADING3, + EDITOR_STYLE_HEADING4, + EDITOR_STYLE_HEADING5, + EDITOR_STYLE_HEADING6, + EDITOR_STYLE_QUOTE, + EDITOR_STYLE_CODE_BLOCK, + NULL + }; + + for(int i=0;para[i] != NULL;i++) { + gtk_text_buffer_remove_tag_by_name(buffer, para[i], begin, end); + } +} + +void editor_set_paragraph_style(UiText *text, const char *style) { + GtkTextBuffer *buffer = text->data1; + NoteEditor *editor = g_object_get_data(text->obj, "editor"); + + // currently changing the selection's paragraph style is not supported + if(gtk_text_buffer_get_has_selection(buffer)) { + update_cursor_paragraph_style(editor, buffer); + return; + } + + GtkTextMark *cursor = gtk_text_buffer_get_insert(buffer); + if(!cursor) { + fprintf(stderr, "Error: no insert mark\n"); + return; + } + GtkTextIter pos; + gtk_text_buffer_get_iter_at_mark(buffer, &pos, cursor); + GtkTextIter begin = pos; + GtkTextIter end = pos; + gtk_text_iter_set_line_offset(&begin, 0); + gtk_text_iter_forward_to_line_end(&end); + + remove_paragraph_styles(buffer, &begin, &end); + gtk_text_buffer_apply_tag_by_name(buffer, style, &begin, &end); +} diff --git a/application/note.c b/application/note.c index 4f3bd3c..24ae291 100644 --- a/application/note.c +++ b/application/note.c @@ -31,6 +31,20 @@ #include "store.h" #include "editor.h" +static TextNoteParagraphStyles paragraph_styles[] = { + { "Paragraph", EDITOR_STYLE_PARAGRAPH }, + { "Code", EDITOR_STYLE_CODE_BLOCK }, + { "Blockquote", EDITOR_STYLE_QUOTE }, + { "Heading 1", EDITOR_STYLE_HEADING1 }, + { "Heading 2", EDITOR_STYLE_HEADING2 }, + { "Heading 3", EDITOR_STYLE_HEADING3 }, + { "Heading 4", EDITOR_STYLE_HEADING4 }, + { "Heading 5", EDITOR_STYLE_HEADING5 }, + { "Heading 6", EDITOR_STYLE_HEADING6 } +}; + +static size_t num_paragraph_styles = 9; + NoteModel *notemodel_current(UiObject *obj) { MainWindow *win = obj->window; if(win->current_notebook && win->current_notebook->current_note) { @@ -55,15 +69,9 @@ NoteModel* notemodel_create(const CxAllocator *note_allocator) { model->textnote_para = ui_list_new(model->ctx, "note_textnote_para"); // currently only one type of textnote exists, therefore the // paragraph types are static - ui_list_append(model->textnote_para, "Paragraph"); - ui_list_append(model->textnote_para, "Code"); - ui_list_append(model->textnote_para, "Blockquote"); - ui_list_append(model->textnote_para, "Heading 1"); - ui_list_append(model->textnote_para, "Heading 2"); - ui_list_append(model->textnote_para, "Heading 3"); - ui_list_append(model->textnote_para, "Heading 4"); - ui_list_append(model->textnote_para, "Heading 5"); - ui_list_append(model->textnote_para, "Heading 6"); + for(int i=0;itextnote_para, (void*)paragraph_styles[i].label); + } model->textnote_strong = ui_int_new(model->ctx, "note_textnote_strong"); model->textnote_emphasis = ui_int_new(model->ctx, "note_textnote_emphasis"); @@ -137,6 +145,16 @@ void note_update_current_style(NoteModel *note, MDActiveStyles *style) { ui_set(note->textnote_code, style->code); } +void note_set_paragraph_type(NoteModel *note, int style) { + if(style < 0 || style >= num_paragraph_styles) { + fprintf(stderr, "Invalid paragraph style %d\n", style); + return; + } + + const char *style_name = paragraph_styles[style].style; + editor_set_paragraph_style(note->text, style_name); +} + void note_text_style_set_strong(NoteModel *note, UiBool enabled) { if(!editor_set_style(note->text, EDITOR_STYLE_STRONG, enabled)) { ui_set(note->textnote_strong, !enabled); diff --git a/application/note.h b/application/note.h index 8e2bce8..fcaab32 100644 --- a/application/note.h +++ b/application/note.h @@ -36,6 +36,11 @@ extern "C" { #endif +typedef struct TextNoteParagraphStyles { + const char *label; + const char *style; +} TextNoteParagraphStyles; + NoteModel *notemodel_current(UiObject *obj); NoteModel* notemodel_create(const CxAllocator *note_allocator); @@ -48,6 +53,7 @@ void note_save(UiObject *obj, NotebookModel *notebook, Note *note); void note_update_current_style(NoteModel *note, MDActiveStyles *style); +void note_set_paragraph_type(NoteModel *note, int style); void note_text_style_set_strong(NoteModel *note, UiBool enabled); void note_text_style_set_emphasis(NoteModel *note, UiBool enabled); void note_text_style_set_underline(NoteModel *note, UiBool enabled); diff --git a/application/window.c b/application/window.c index 6a4d0e3..779a6cc 100644 --- a/application/window.c +++ b/application/window.c @@ -75,7 +75,7 @@ void window_create() { ui_newline(obj); } ui_hbox(obj, .style_class = "note_toolbar", .margin = 10, .spacing = 4, .fill = UI_OFF) { - ui_combobox(obj, .varname = "note_textnote_para"); + ui_combobox(obj, .varname = "note_textnote_para", .onactivate = action_textnote_paragraph); ui_togglebutton(obj, .icon = "format-text-bold", .varname = "note_textnote_strong", .onchange = action_textnote_style_strong); ui_togglebutton(obj, .icon = "format-text-italic", .varname = "note_textnote_emphasis", .onchange = action_textnote_style_emphasis); ui_togglebutton(obj, .icon = "format-text-underline", .varname = "note_textnote_underline", .onchange = action_textnote_style_underline); @@ -343,3 +343,14 @@ void action_textnote_style_code(UiEvent *event, void *userdata) { note_text_style_set_code(notebook->current_note->model, event->intval); } } + +void action_textnote_paragraph(UiEvent *event, void *userdata) { + if(event->set) { + return; + } + MainWindow *window = event->window; + NotebookModel *notebook = window->current_notebook; + if(notebook && notebook->current_note && notebook->current_note->model) { + note_set_paragraph_type(notebook->current_note->model, event->intval); + } +} diff --git a/application/window.h b/application/window.h index ed470ac..bb21ee1 100644 --- a/application/window.h +++ b/application/window.h @@ -56,6 +56,7 @@ void action_notebook_selected(UiEvent *event, void *userdata); void action_note_selected(UiEvent *event, void *userdata); void action_note_activated(UiEvent *event, void *userdata); +void action_textnote_paragraph(UiEvent *event, void *userdata); void action_textnote_style_strong(UiEvent *event, void *userdata); void action_textnote_style_emphasis(UiEvent *event, void *userdata); void action_textnote_style_underline(UiEvent *event, void *userdata); diff --git a/ui/cocoa/container.m b/ui/cocoa/container.m index 9dc5965..99b18c9 100644 --- a/ui/cocoa/container.m +++ b/ui/cocoa/container.m @@ -67,12 +67,21 @@ if(self.orientation == NSUserInterfaceLayoutOrientationHorizontal) { [view.heightAnchor constraintEqualToAnchor:self.heightAnchor].active = YES; if(!fill) { - [view.widthAnchor constraintEqualToConstant:view.intrinsicContentSize.width].active = YES; + NSSize isize = view.intrinsicContentSize; + [view.widthAnchor constraintEqualToConstant:isize.width].active = YES; } } else { [view.widthAnchor constraintEqualToAnchor:self.widthAnchor].active = YES; if(!fill) { - [view.heightAnchor constraintEqualToConstant:view.intrinsicContentSize.height].active = YES; + NSSize isize = view.intrinsicContentSize; + NSRect frame = view.frame; + CGFloat height = isize.height > 0 ? isize.height : frame.size.height; + if(height == 0) { + printf("debug"); + } + if(height > 0) { + [view.heightAnchor constraintEqualToConstant:height].active = YES; + } } } diff --git a/ui/cocoa/objs.mk b/ui/cocoa/objs.mk index 80f882a..9324579 100644 --- a/ui/cocoa/objs.mk +++ b/ui/cocoa/objs.mk @@ -39,6 +39,7 @@ COCOAOBJ += WindowManager.o COCOAOBJ += window.o COCOAOBJ += Container.o COCOAOBJ += button.o +COCOAOBJ += text.o TOOLKITOBJS += $(COCOAOBJ:%=$(COCOA_OBJPRE)%) TOOLKITSOURCE += $(COCOAOBJ:%.o=cocoa/%.m) diff --git a/ui/cocoa/text.h b/ui/cocoa/text.h new file mode 100644 index 0000000..9bd685f --- /dev/null +++ b/ui/cocoa/text.h @@ -0,0 +1,32 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2025 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. + */ + +#import "toolkit.h" + +#import "../ui/text.h" + diff --git a/ui/cocoa/text.m b/ui/cocoa/text.m new file mode 100644 index 0000000..74d6a79 --- /dev/null +++ b/ui/cocoa/text.m @@ -0,0 +1,43 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2025 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. + */ + +#import "text.h" +#import "EventData.h" +#import "Container.h" +#import + +UIWIDGET ui_textarea_create(UiObject *obj, UiTextAreaArgs args) { + //NSScrollView *scrollview = [[NSScrollView alloc] initWithFrame:(NSRect){ 0, 0, 40, 40}]; + NSTextView *textview = [[NSTextView alloc] initWithFrame:(NSRect){ 0, 0, 40, 40}]; + //scrollview.documentView = textview; + + UiLayout layout = UI_INIT_LAYOUT(args); + ui_container_add(obj, textview, &layout, TRUE); + + return (__bridge void*)textview; +} diff --git a/ui/common/types.c b/ui/common/types.c index 1fdb1b9..dc8d5c3 100644 --- a/ui/common/types.c +++ b/ui/common/types.c @@ -625,7 +625,6 @@ void uic_list_register_observer_destructor(UiContext *ctx, UiList *list, UiObser cxMempoolSetDestructor(destr, (cx_destructor_func)observer_destructor); } - static int ui_set_op = 0; void ui_setop_enable(int set) { @@ -635,4 +634,3 @@ void ui_setop_enable(int set) { int ui_get_setop(void) { return ui_set_op; } - diff --git a/ui/gtk/list.c b/ui/gtk/list.c index 5d7f519..cd27638 100644 --- a/ui/gtk/list.c +++ b/ui/gtk/list.c @@ -352,6 +352,15 @@ UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs args) { return view; } +void ui_listview_select(UIWIDGET listview, int index) { + GtkSelectionModel *model = gtk_list_view_get_model(GTK_LIST_VIEW(listview)); + gtk_selection_model_select_item(model, index, TRUE); +} + +void ui_combobox_select(UIWIDGET dropdown, int index) { + gtk_drop_down_set_selected(GTK_DROP_DOWN(dropdown), index); +} + UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) { UiObject* current = uic_current_obj(obj); @@ -465,6 +474,7 @@ static void listview_event(ui_callback cb, void *cbdata, UiListView *view) { event.window = event.obj->window; event.intval = view->selection.count; event.eventdata = &view->selection; + event.set = ui_get_setop(); if(cb) { cb(&event, cbdata); } @@ -507,6 +517,7 @@ void ui_dropdown_notify(GtkWidget *dropdown, GObject *pspec, gpointer userdata) event.window = event.obj->window; event.intval = index; event.eventdata = eventdata->data; + event.set = ui_get_setop(); view->onactivate(&event, view->onactivatedata); } } @@ -543,6 +554,7 @@ void ui_dropdown_activate(GtkDropDown* self, gpointer userdata) { event.window = event.obj->window; event.intval = view->selection.count; event.eventdata = &view->selection; + event.set = ui_get_setop(); view->onactivate(&event, view->onactivatedata); } } @@ -580,6 +592,7 @@ UiListSelection ui_listview_getselection2(UiList *list) { } void ui_listview_setselection2(UiList *list, UiListSelection selection) { + ui_setop_enable(TRUE); UiListView *view = list->obj; UiListSelection newselection; newselection.count = view->selection.count; @@ -598,6 +611,7 @@ void ui_listview_setselection2(UiList *list, UiListSelection selection) { gtk_selection_model_select_item(view->selectionmodel, selection.rows[i], FALSE); } } + ui_setop_enable(FALSE); } UiListSelection ui_combobox_getselection(UiList *list) { @@ -613,12 +627,14 @@ UiListSelection ui_combobox_getselection(UiList *list) { } void ui_combobox_setselection(UiList *list, UiListSelection selection) { + ui_setop_enable(TRUE); UiListView *view = list->obj; if(selection.count > 0) { gtk_drop_down_set_selected(GTK_DROP_DOWN(view->widget), selection.rows[0]); } else { gtk_drop_down_set_selected(GTK_DROP_DOWN(view->widget), GTK_INVALID_LIST_POSITION); } + ui_setop_enable(FALSE); } #else @@ -842,6 +858,17 @@ UIWIDGET ui_listview_create(UiObject *obj, UiListArgs args) { return scroll_area; } +void ui_listview_select(UIWIDGET listview, int index) { + GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(listview)); + GtkTreePath *path = gtk_tree_path_new_from_indicesv(&index, 1); + gtk_tree_selection_select_path(sel, path); + //g_object_unref(path); +} + +void ui_combobox_select(UIWIDGET dropdown, int index) { + gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown), index); +} + UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) { UiObject* current = uic_current_obj(obj); @@ -1026,11 +1053,13 @@ UiListSelection ui_listview_getselection(UiList *list) { } void ui_listview_setselection(UiList *list, UiListSelection selection) { + ui_setop_enable(TRUE); UiListView *view = list->obj; GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view->widget)); GtkTreePath *path = gtk_tree_path_new_from_indicesv(selection.rows, selection.count); gtk_tree_selection_select_path(sel, path); //g_object_unref(path); + ui_setop_enable(FALSE); } @@ -1117,6 +1146,7 @@ GtkWidget* ui_create_combobox(UiObject *obj, UiModel *model, UiVar *var, char ** event->callback = f; event->value = 0; event->customdata = uicbox; + event.set = ui_get_setop(); g_signal_connect( combobox, @@ -1145,6 +1175,7 @@ void ui_combobox_change_event(GtkComboBox *widget, UiEventData *e) { event.document = event.obj->ctx->document; event.eventdata = eventdata; event.intval = index; + event.set = ui_get_setop(); e->callback(&event, e->userdata); } @@ -1165,10 +1196,12 @@ UiListSelection ui_combobox_getselection(UiList *list) { } void ui_combobox_setselection(UiList *list, UiListSelection selection) { + ui_setop_enable(TRUE); UiListView *combobox = list->obj; if(selection.count > 0) { gtk_combo_box_set_active(GTK_COMBO_BOX(combobox->widget), selection.rows[0]); } + ui_setop_enable(FALSE); } @@ -1190,6 +1223,7 @@ void ui_listview_activate_event( e.document = event->obj->ctx->document; e.eventdata = &selection; e.intval = selection.count > 0 ? selection.rows[0] : -1; + e.set = ui_get_setop(); event->activate(&e, event->activatedata); if(selection.count > 0) { @@ -1209,6 +1243,7 @@ void ui_listview_selection_event( e.document = event->obj->ctx->document; e.eventdata = &selection; e.intval = selection.count > 0 ? selection.rows[0] : -1; + e.set = ui_get_setop(); event->selection(&e, event->selectiondata); if(selection.count > 0) { @@ -1267,6 +1302,7 @@ static GdkContentProvider *ui_listview_dnd_prepare(GtkDragSource *source, double event.document = event.obj->ctx->document; event.eventdata = dnd; event.intval = 0; + event.set = ui_get_setop(); listview->ondragstart(&event, listview->ondragstartdata); } @@ -1302,6 +1338,7 @@ static void ui_listview_drag_end(GtkDragSource *self, GdkDrag *drag, gboolean de event.document = event.obj->ctx->document; event.eventdata = &dnd; event.intval = 0; + event.set = ui_get_setop(); listview->ondragcomplete(&event, listview->ondragcompletedata); } } @@ -1330,6 +1367,7 @@ static gboolean ui_listview_drop( event.document = event.obj->ctx->document; event.eventdata = &dnd; event.intval = 0; + event.set = ui_get_setop(); listview->ondrop(&event, listview->ondropdata); } @@ -1392,6 +1430,7 @@ static void ui_listview_drag_getdata( event.document = event.obj->ctx->document; event.eventdata = &dnd; event.intval = 0; + event.set = ui_get_setop(); listview->ondragstart(&event, listview->ondragstartdata); } } @@ -1416,6 +1455,7 @@ static void ui_listview_drag_end( event.document = event.obj->ctx->document; event.eventdata = &dnd; event.intval = 0; + event.set = ui_get_setop(); listview->ondragcomplete(&event, listview->ondragcompletedata); } } @@ -1461,6 +1501,7 @@ static void ui_listview_drag_data_received( event.document = event.obj->ctx->document; event.eventdata = &dnd; event.intval = 0; + event.set = ui_get_setop(); listview->ondrop(&event, listview->ondropdata); } } @@ -1933,6 +1974,7 @@ void ui_listbox_row_activate(GtkListBox *self, GtkListBoxRow *row, gpointer user event.document = event.obj->ctx->document; event.eventdata = &eventdata; event.intval = data->value0; + event.set = ui_get_setop(); if(data->callback) { data->callback(&event, data->userdata); diff --git a/ui/motif/button.c b/ui/motif/button.c index ff5421c..6ca74ad 100644 --- a/ui/motif/button.c +++ b/ui/motif/button.c @@ -92,6 +92,7 @@ void ui_push_button_callback(Widget widget, UiEventData *event, XtPointer d) { e.window = event->obj->window; e.document = event->obj->ctx->document; e.intval = event->value; + e.set = 0; event->callback(&e, event->userdata); } @@ -173,6 +174,7 @@ static void togglebutton_changed(Widget w, UiVarEventData *event, XmToggleButton e.document = e.obj->ctx->document; e.eventdata = NULL; e.intval = XmToggleButtonGetState(w); + e.set = ui_get_setop(); if(event->callback) { event->callback(&e, event->userdata); @@ -281,6 +283,7 @@ static void radiobutton_changed(Widget w, UiVarEventData *event, XmToggleButtonC e.document = e.obj->ctx->document; e.eventdata = value; e.intval = v; + e.set = ui_get_setop(); if(event->callback) { event->callback(&e, event->userdata); diff --git a/ui/motif/list.c b/ui/motif/list.c index 2bdc35f..5da5a0b 100644 --- a/ui/motif/list.c +++ b/ui/motif/list.c @@ -186,11 +186,13 @@ UiListSelection ui_listview_getselection(UiList *list) { } void ui_listview_setselection(UiList *list, UiListSelection selection) { + ui_setop_enable(TRUE); UiListView *listview = list->obj; XmListDeselectAllItems(listview->widget); for(int i=0;iwidget, selection.rows[i]+1, False); } + ui_setop_enable(FALSE); } void* ui_strmodel_getvalue(void *elm, int column) { diff --git a/ui/ui/tree.h b/ui/ui/tree.h index 9d8ebba..8217cf6 100644 --- a/ui/ui/tree.h +++ b/ui/ui/tree.h @@ -251,6 +251,9 @@ UIEXPORT UIWIDGET ui_table_create(UiObject* obj, UiListArgs args); UIEXPORT UIWIDGET ui_combobox_create(UiObject* obj, UiListArgs args); UIEXPORT UIWIDGET ui_breadcrumbbar_create(UiObject* obj, UiListArgs args); +UIEXPORT void ui_listview_select(UIWIDGET listview, int index); +UIEXPORT void ui_combobox_select(UIWIDGET dropdown, int index); + UIEXPORT UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs args);