Sun, 19 Nov 2017 09:00:16 +0100
adds simple drag and drop support (GTK)
application/main.c | file | annotate | diff | comparison | revisions | |
ui/gtk/dnd.c | file | annotate | diff | comparison | revisions | |
ui/gtk/dnd.h | file | annotate | diff | comparison | revisions | |
ui/gtk/model.c | file | annotate | diff | comparison | revisions | |
ui/gtk/model.h | file | annotate | diff | comparison | revisions | |
ui/gtk/objs.mk | file | annotate | diff | comparison | revisions | |
ui/gtk/toolbar.c | file | annotate | diff | comparison | revisions | |
ui/gtk/toolkit.h | file | annotate | diff | comparison | revisions | |
ui/gtk/tree.c | file | annotate | diff | comparison | revisions | |
ui/gtk/tree.h | file | annotate | diff | comparison | revisions | |
ui/ui/dnd.h | file | annotate | diff | comparison | revisions | |
ui/ui/toolkit.h | file | annotate | diff | comparison | revisions | |
ui/ui/tree.h | file | annotate | diff | comparison | revisions | |
ui/ui/ui.h | file | annotate | diff | comparison | revisions |
--- a/application/main.c Thu Nov 16 12:04:10 2017 +0100 +++ b/application/main.c Sun Nov 19 09:00:16 2017 +0100 @@ -82,6 +82,16 @@ fflush(stdout); } +void list_data_get(UiEvent *event, UiSelection *selection, UiList *l, int i) { + ui_selection_settext(selection, "Hello World!", -1); +} + +void list_drop(UiEvent *event, UiSelection *selection, UiList *l, int i) { + char *text = ui_selection_gettext(selection); + printf("dnd drop: {%s}\n", text); + free(text); +} + Document* create_doc(char *str) { Document *doc = ui_document_new(sizeof(Document)); UiContext *ctx = ui_document_context(doc); @@ -163,8 +173,11 @@ UiModel *model = ui_model(obj->ctx, UI_ICON_TEXT, "name", UI_STRING, "desc", -1); model->getvalue = (ui_getvaluefunc)model_get; + model->drop = list_drop; + model->data_get = list_data_get; UiListCallbacks cb = {NULL, NULL, NULL}; - ui_table_nv(obj, "list", model, cb); + UIWIDGET table = ui_table_nv(obj, "list", model, cb); + ui_table_dragsource(table, 0, "text/plain", NULL); //ui_spinner_setrange(ui_spinnerf_nv(obj, 1, 0, "d"), 0, 1000); ui_spinnerr_nv(obj, "r");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/gtk/dnd.c Sun Nov 19 09:00:16 2017 +0100 @@ -0,0 +1,77 @@ +/* + * 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 <string.h> + +#include "dnd.h" + +void ui_selection_settext(UiSelection *sel, char *str, int len) { + if(!gtk_selection_data_set_text(sel->data, str, len)); +} + +void ui_selection_seturis(UiSelection *sel, char **uris, int nelm) { + char **uriarray = calloc(nelm+1, sizeof(char*)); + for(int i=0;i<nelm;i++) { + uriarray[i] = uris[i]; + } + uriarray[nelm] = NULL; + gtk_selection_data_set_uris(sel->data, uriarray); +} + +char* ui_selection_gettext(UiSelection *sel) { + guchar *text = gtk_selection_data_get_text(sel->data); + if(text) { + char *textcp = strdup((char*)text); + g_free(text); + return textcp; + } + return NULL; +} + +char** ui_selection_geturis(UiSelection *sel, size_t *nelm) { + gchar **uris = gtk_selection_data_get_uris(sel->data); + if(uris) { + size_t al = 32; + char **array = malloc(al * sizeof(char*)); + size_t i = 0; + while(uris[i] != NULL) { + if(i >= al) { + al *= 2; + array = realloc(array, al * sizeof(char*)); + } + array[i] = strdup((char*)uris[i]); + i++; + } + *nelm = i; + g_strfreev(uris); + return array; + } + return NULL; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/gtk/dnd.h Sun Nov 19 09:00:16 2017 +0100 @@ -0,0 +1,47 @@ +/* + * 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. + */ + +#ifndef DND_H +#define DND_H + +#include "../ui/dnd.h" +#include "toolkit.h" + +#ifdef __cplusplus +extern "C" { +#endif + + + + +#ifdef __cplusplus +} +#endif + +#endif /* DND_H */ +
--- a/ui/gtk/model.c Thu Nov 16 12:04:10 2017 +0100 +++ b/ui/gtk/model.c Sun Nov 19 09:00:16 2017 +0100 @@ -31,6 +31,7 @@ #include "model.h" #include "image.h" +#include "toolkit.h" #define IS_UI_LIST_MODEL(obj) \ (G_TYPE_CHECK_INSTANCE_TYPE((obj), list_model_type)) @@ -41,6 +42,9 @@ static void list_model_interface_init(GtkTreeModelIface *i, gpointer data); static void list_model_init(UiListModel *instance, GObjectClass *cl); +static void list_model_dnd_dest_interface_init(GtkTreeDragDestIface *i, gpointer data); +static void list_model_dnd_src_interface_init(GtkTreeDragSourceIface *i, gpointer data); + static GObjectClass list_model_class; static const GTypeInfo list_model_info = { sizeof(GObjectClass), @@ -60,6 +64,17 @@ }; static GType list_model_type; +static const GInterfaceInfo list_model_dnd_dest_interface_info = { + (GInterfaceInitFunc)list_model_dnd_dest_interface_init, + NULL, + NULL +}; +static const GInterfaceInfo list_model_dnd_src_interface_info = { + (GInterfaceInitFunc)list_model_dnd_src_interface_init, + NULL, + NULL +}; + void ui_list_init() { list_model_type = g_type_register_static( G_TYPE_OBJECT, @@ -70,10 +85,19 @@ list_model_type, GTK_TYPE_TREE_MODEL, &list_model_interface_info); + g_type_add_interface_static( + list_model_type, + GTK_TYPE_TREE_DRAG_DEST, + &list_model_dnd_dest_interface_info); + g_type_add_interface_static( + list_model_type, + GTK_TYPE_TREE_DRAG_SOURCE, + &list_model_dnd_src_interface_info); } static void list_model_class_init(GObjectClass *cl, gpointer data) { //cl->finalize = ...; // TODO + } static void list_model_interface_init(GtkTreeModelIface *i, gpointer data) { @@ -91,6 +115,17 @@ i->iter_parent = ui_list_model_iter_parent; } +static void list_model_dnd_dest_interface_init(GtkTreeDragDestIface *i, gpointer data) { + i->drag_data_received = ui_list_model_drag_data_received; + i->row_drop_possible = ui_list_model_row_drop_possible; +} + +static void list_model_dnd_src_interface_init(GtkTreeDragSourceIface *i, gpointer data) { + i->drag_data_delete = ui_list_model_drag_data_delete; + i->drag_data_get = ui_list_model_drag_data_get; + i->row_draggable = ui_list_model_row_draggable; +} + static void list_model_init(UiListModel *instance, GObjectClass *cl) { instance->columntypes = NULL; instance->var = NULL; @@ -128,9 +163,10 @@ value->g_type = G_TYPE_INVALID; } -UiListModel* ui_list_model_new(UiVar *var, UiModel *info) { +UiListModel* ui_list_model_new(UiObject *obj, UiVar *var, UiModel *info) { UiListModel *model = g_object_new(list_model_type, NULL); - model->info = info; + model->obj = obj; + model->model = info; model->var = var; model->columntypes = calloc(sizeof(GType), 2 * info->columns); int ncol = 0; @@ -249,8 +285,8 @@ list->iter = iter->user_data; //list->index = (int)(intptr_t)iter->user_data2; //list->current = iter->user_data3; - if(model->info->getvalue) { - void *data = model->info->getvalue(iter->user_data3, column); + if(model->model->getvalue) { + void *data = model->model->getvalue(iter->user_data3, column); if(model->columntypes[column] == G_TYPE_OBJECT) { UiImage *img = data; ui_model_set_value(model->columntypes[column], img->pixbuf, value); @@ -379,3 +415,114 @@ { return FALSE; } + +// ****** dnd ****** + +gboolean ui_list_model_drag_data_received( + GtkTreeDragDest *drag_dest, + GtkTreePath *dest_path, + GtkSelectionData *selection_data) +{ + //printf("drag received\n"); + UiListModel *model = UI_LIST_MODEL(drag_dest); + if(model->model->drop) { + gint *indices = gtk_tree_path_get_indices(dest_path); + gint row = indices[0]; + UiEvent e; + e.obj = model->obj; + e.window = e.obj->window; + e.document = e.obj->ctx->document; + e.eventdata = NULL; + e.intval = 0; + UiSelection s; + s.data = selection_data; + model->model->drop(&e, &s, model->var->value, row); + } + return TRUE; +} + +gboolean ui_list_model_row_drop_possible( + GtkTreeDragDest *drag_dest, + GtkTreePath *dest_path, + GtkSelectionData *selection_data) +{ + //printf("row_drop_possible\n"); + UiListModel *model = UI_LIST_MODEL(drag_dest); + if(model->model->candrop) { + gint *indices = gtk_tree_path_get_indices(dest_path); + gint row = indices[0]; + UiEvent e; + e.obj = model->obj; + e.window = e.obj->window; + e.document = e.obj->ctx->document; + e.eventdata = NULL; + e.intval = 0; + UiSelection s; + s.data = selection_data; + return model->model->candrop(&e, &s, model->var->value, row); + } + return TRUE; +} + +gboolean ui_list_model_row_draggable( + GtkTreeDragSource *drag_source, + GtkTreePath *path) +{ + //printf("row_draggable\n"); + UiListModel *model = UI_LIST_MODEL(drag_source); + if(model->model->candrag) { + gint *indices = gtk_tree_path_get_indices(path); + gint row = indices[0]; + UiEvent e; + e.obj = model->obj; + e.window = e.obj->window; + e.document = e.obj->ctx->document; + e.eventdata = NULL; + e.intval = 0; + return model->model->candrag(&e, model->var->value, row); + } + return TRUE; +} + +gboolean ui_list_model_drag_data_get( + GtkTreeDragSource *drag_source, + GtkTreePath *path, + GtkSelectionData *selection_data) +{ + //printf("drag_data_get\n"); + UiListModel *model = UI_LIST_MODEL(drag_source); + if(model->model->data_get) { + gint *indices = gtk_tree_path_get_indices(path); + gint row = indices[0]; + UiEvent e; + e.obj = model->obj; + e.window = e.obj->window; + e.document = e.obj->ctx->document; + e.eventdata = NULL; + e.intval = 0; + UiSelection s; + s.data = selection_data; + model->model->data_get(&e, &s, model->var->value, row); + } + return TRUE; +} + +gboolean ui_list_model_drag_data_delete( + GtkTreeDragSource *drag_source, + GtkTreePath *path) +{ + //printf("drag_data_delete\n"); + UiListModel *model = UI_LIST_MODEL(drag_source); + if(model->model->data_get) { + gint *indices = gtk_tree_path_get_indices(path); + gint row = indices[0]; + UiEvent e; + e.obj = model->obj; + e.window = e.obj->window; + e.document = e.obj->ctx->document; + e.eventdata = NULL; + e.intval = 0; + model->model->data_delete(&e, model->var->value, row); + } + return TRUE; +}
--- a/ui/gtk/model.h Thu Nov 16 12:04:10 2017 +0100 +++ b/ui/gtk/model.h Sun Nov 19 09:00:16 2017 +0100 @@ -43,12 +43,13 @@ * UiList to GtkTreeModel wrapper */ struct UiListModel { - GObject object; - UiModel *info; - UiVar *var; - GType *columntypes; - int numcolumns; - int stamp; + GObject object; + UiObject *obj; + UiModel *model; + UiVar *var; + GType *columntypes; + int numcolumns; + int stamp; }; /* @@ -59,7 +60,7 @@ /* * Creates a UiListModel for a given UiList */ -UiListModel* ui_list_model_new(UiVar *var, UiModel *info); +UiListModel* ui_list_model_new(UiObject *obj, UiVar *var, UiModel *info); // interface functions @@ -113,6 +114,31 @@ GtkTreeIter *iter, GtkTreeIter *child); +/* dnd */ + +gboolean ui_list_model_drag_data_received( + GtkTreeDragDest *drag_dest, + GtkTreePath *dest, + GtkSelectionData *selection_data); + +gboolean ui_list_model_row_drop_possible( + GtkTreeDragDest *drag_dest, + GtkTreePath *dest_path, + GtkSelectionData *selection_data); + +gboolean ui_list_model_row_draggable( + GtkTreeDragSource *drag_source, + GtkTreePath *path); + +gboolean ui_list_model_drag_data_get( + GtkTreeDragSource *drag_source, + GtkTreePath *path, + GtkSelectionData *selection_data); + +gboolean ui_list_model_drag_data_delete( + GtkTreeDragSource *drag_source, + GtkTreePath *path); + #ifdef __cplusplus } #endif
--- a/ui/gtk/objs.mk Thu Nov 16 12:04:10 2017 +0100 +++ b/ui/gtk/objs.mk Sun Nov 19 09:00:16 2017 +0100 @@ -44,6 +44,7 @@ GTKOBJ += graphics.o GTKOBJ += range.o GTKOBJ += entry.o +GTKOBJ += dnd.o TOOLKITOBJS += $(GTKOBJ:%=$(GTK_OBJPRE)%) TOOLKITSOURCE += $(GTKOBJ:%.o=gtk/%.c)
--- a/ui/gtk/toolbar.c Thu Nov 16 12:04:10 2017 +0100 +++ b/ui/gtk/toolbar.c Sun Nov 19 09:00:16 2017 +0100 @@ -360,7 +360,7 @@ void add_toolbar_combobox(GtkToolbar *tb, UiToolbarComboBox *cb, UiObject *obj) { UiModel *modelinfo = ui_model(obj->ctx, UI_STRING, "", -1); modelinfo->getvalue = cb->getvalue; - UiListModel *model = ui_list_model_new(cb->var, modelinfo); + UiListModel *model = ui_list_model_new(obj, cb->var, modelinfo); GtkWidget *combobox = ui_create_combobox(obj, model, cb->callback, cb->userdata); GtkToolItem *item = gtk_tool_item_new(); @@ -373,7 +373,7 @@ if(var) { UiModel *modelinfo = ui_model(obj->ctx, UI_STRING, "", -1); modelinfo->getvalue = cb->getvalue; - UiListModel *model = ui_list_model_new(var, modelinfo); + UiListModel *model = ui_list_model_new(obj, var, modelinfo); GtkWidget *combobox = ui_create_combobox(obj, model, cb->callback, cb->userdata); GtkToolItem *item = gtk_tool_item_new();
--- a/ui/gtk/toolkit.h Thu Nov 16 12:04:10 2017 +0100 +++ b/ui/gtk/toolkit.h Sun Nov 19 09:00:16 2017 +0100 @@ -59,6 +59,10 @@ void *finish_data; } UiJob; +struct UiSelection { + GtkSelectionData *data; +}; + typedef enum UiOrientation UiOrientation; enum UiOrientation { UI_HORIZONTAL = 0, UI_VERTICAL };
--- a/ui/gtk/tree.c Thu Nov 16 12:04:10 2017 +0100 +++ b/ui/gtk/tree.c Sun Nov 19 09:00:16 2017 +0100 @@ -29,6 +29,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <stdarg.h> #include "../common/context.h" #include "../common/object.h" @@ -67,11 +68,11 @@ UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1); model->getvalue = getvalue; UiList *list = var->value; - UiListModel *listmodel = ui_list_model_new(var, model); + UiListModel *listmodel = ui_list_model_new(obj, var, model); gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(listmodel)); UiListView *listview = malloc(sizeof(UiListView)); - listview->ctx = obj->ctx; + listview->obj = obj; listview->widget = view; listview->var = var; listview->model = model; @@ -135,10 +136,42 @@ return NULL; } +static void drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer udata) { + printf("drag begin\n"); + +} + +static void drag_end( + GtkWidget *widget, + GdkDragContext *context, + guint time, + gpointer udata) +{ + printf("drag end\n"); + +} + +static gboolean drag_failed( + GtkWidget *widget, + GdkDragContext *context, + GtkDragResult result, + gpointer udata) +{ + printf("drag failed: %d\n", result); + +} + +static GtkTargetEntry targetentries[] = + { + { "STRING", 0, 0 }, + { "text/plain", 0, 1 }, + { "text/uri-list", 0, 2 }, + }; UIWIDGET ui_table_var(UiObject *obj, UiVar *var, UiModel *model, UiListCallbacks cb) { // create treeview GtkWidget *view = gtk_tree_view_new(); + int addi = 0; for(int i=0;i<model->columns;i++) { GtkTreeViewColumn *column = NULL; @@ -178,13 +211,17 @@ #endif UiList *list = var->value; - UiListModel *listmodel = ui_list_model_new(var, model); + UiListModel *listmodel = ui_list_model_new(obj, var, model); gtk_tree_view_set_model(GTK_TREE_VIEW(view), GTK_TREE_MODEL(listmodel)); + //g_signal_connect(view, "drag-begin", G_CALLBACK(drag_begin), NULL); + //g_signal_connect(view, "drag-end", G_CALLBACK(drag_end), NULL); + //g_signal_connect(view, "drag-failed", G_CALLBACK(drag_failed), NULL); + // add TreeView as observer to the UiList to update the TreeView if the // data changes UiListView *tableview = malloc(sizeof(UiListView)); - tableview->ctx = obj->ctx; + tableview->obj = obj; tableview->widget = view; tableview->var = var; tableview->model = model; @@ -260,15 +297,90 @@ return NULL; } +GtkWidget* ui_get_tree_widget(UIWIDGET widget) { + GList *c = gtk_container_get_children(GTK_CONTAINER(widget)); + if(c) { + return c->data; + } + return NULL; +} + +static char** targets2array(char *target0, va_list ap, int *nelm) { + int al = 16; + char **targets = calloc(16, sizeof(char*)); + targets[0] = target0; + + int i = 1; + char *target; + while((target = va_arg(ap, char*)) != NULL) { + if(i >= al) { + al *= 2; + targets = realloc(targets, al*sizeof(char*)); + } + targets[i] = target; + i++; + } + + *nelm = i; + return targets; +} + +static GtkTargetEntry* targetstr2gtktargets(char **str, int nelm) { + GtkTargetEntry *targets = calloc(nelm, sizeof(GtkTargetEntry)); + for(int i=0;i<nelm;i++) { + targets[i].target = str[i]; + } + return targets; +} + +void ui_table_dragsource(UIWIDGET tablewidget, int actions, char *target0, ...) { + va_list ap; + int nelm; + char **targets = targets2array(target0, ap, &nelm); + va_end(ap); + ui_table_dragsource_a(tablewidget, actions, targets, nelm); + free(targets); +} + +void ui_table_dragsource_a(UIWIDGET tablewidget, int actions, char **targets, int nelm) { + GtkTargetEntry* t = targetstr2gtktargets(targets, nelm); + gtk_tree_view_enable_model_drag_source( + GTK_TREE_VIEW(ui_get_tree_widget(tablewidget)), + GDK_BUTTON1_MASK, + t, + nelm, + GDK_ACTION_COPY|GDK_ACTION_MOVE|GDK_ACTION_LINK); + free(t); +} + +void ui_table_dragdest(UIWIDGET tablewidget, int actions, char *target0, ...) { + va_list ap; + int nelm; + char **targets = targets2array(target0, ap, &nelm); + va_end(ap); + ui_table_dragdest_a(tablewidget, actions, targets, nelm); + free(targets); +} + +void ui_table_dragdest_a(UIWIDGET tablewidget, int actions, char **targets, int nelm) { + GtkTargetEntry* t = targetstr2gtktargets(targets, nelm); + gtk_tree_view_enable_model_drag_dest( + GTK_TREE_VIEW(ui_get_tree_widget(tablewidget)), + t, + nelm, + GDK_ACTION_COPY|GDK_ACTION_MOVE|GDK_ACTION_LINK); + free(t); +} + void ui_listview_update(UiList *list, int i) { UiListView *view = list->obj; - UiListModel *model = ui_list_model_new(view->var, view->model); + UiListModel *model = ui_list_model_new(view->obj, view->var, view->model); gtk_tree_view_set_model(GTK_TREE_VIEW(view->widget), GTK_TREE_MODEL(model)); // TODO: free old model } void ui_listview_destroy(GtkWidget *w, UiListView *v) { - ui_destroy_boundvar(v->ctx, v->var); + ui_destroy_boundvar(v->obj->ctx, v->var); // TODO: destroy model? free(v); } @@ -375,7 +487,7 @@ UIWIDGET ui_combobox_var(UiObject *obj, UiVar *var, ui_getvaluefunc getvalue, ui_callback f, void *udata) { UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1); model->getvalue = getvalue; - UiListModel *listmodel = ui_list_model_new(var, model); + UiListModel *listmodel = ui_list_model_new(obj, var, model); GtkWidget *combobox = ui_create_combobox(obj, listmodel, f, udata); UiContainer *ct = uic_get_current_container(obj); @@ -386,10 +498,10 @@ GtkWidget *combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model)); UiListView *uicbox = malloc(sizeof(UiListView)); - uicbox->ctx = obj->ctx; + uicbox->obj = obj; uicbox->widget = combobox; uicbox->var = model->var; - uicbox->model = model->info; + uicbox->model = model->model; g_signal_connect( combobox, @@ -442,7 +554,7 @@ void ui_combobox_modelupdate(UiList *list, int i) { UiListView *view = list->obj; - UiListModel *model = ui_list_model_new(view->var, view->model); + UiListModel *model = ui_list_model_new(view->obj, view->var, view->model); gtk_combo_box_set_model(GTK_COMBO_BOX(view->widget), GTK_TREE_MODEL(model)); }
--- a/ui/gtk/tree.h Thu Nov 16 12:04:10 2017 +0100 +++ b/ui/gtk/tree.h Sun Nov 19 09:00:16 2017 +0100 @@ -38,7 +38,8 @@ #endif typedef struct UiListView { - UiContext *ctx; + UiObject *obj; + //UiContext *ctx; GtkWidget *widget; UiVar *var; UiModel *model; @@ -56,6 +57,8 @@ UIWIDGET ui_listview_var(UiObject *obj, UiVar *var, ui_getvaluefunc getvalue, ui_callback f, void *udata); UIWIDGET ui_table_var(UiObject *obj, UiVar *var, UiModel *model, UiListCallbacks cb); +GtkWidget* ui_get_tree_widget(UIWIDGET widget); + void ui_listview_update(UiList *list, int i); void ui_listview_destroy(GtkWidget *w, UiListView *v);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ui/ui/dnd.h Sun Nov 19 09:00:16 2017 +0100 @@ -0,0 +1,52 @@ +/* + * 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. + */ + +#ifndef UI_DND_H +#define UI_DND_H + +#include "toolkit.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define UI_DND_FILE_TARGET "XdndDirectSave0" + +void ui_selection_settext(UiSelection *sel, char *str, int len); +void ui_selection_seturis(UiSelection *sel, char **uris, int nelm); + +char* ui_selection_gettext(UiSelection *sel); +char** ui_selection_geturis(UiSelection *sel, size_t *nelm); + + +#ifdef __cplusplus +} +#endif + +#endif /* UI_DND_H */ +
--- a/ui/ui/toolkit.h Thu Nov 16 12:04:10 2017 +0100 +++ b/ui/ui/toolkit.h Sun Nov 19 09:00:16 2017 +0100 @@ -108,6 +108,8 @@ typedef struct UiIcon UiIcon; typedef struct UiImage UiImage; + +typedef struct UiSelection UiSelection; /* end opaque types */ typedef struct UiTabbedPane UiTabbedPane;
--- a/ui/ui/tree.h Thu Nov 16 12:04:10 2017 +0100 +++ b/ui/ui/tree.h Sun Nov 19 09:00:16 2017 +0100 @@ -73,6 +73,12 @@ * TODO: return */ void*(*getvalue)(void*, int); + + UiBool(*candrop)(UiEvent*, UiSelection*, UiList*, int); + void(*drop)(UiEvent*, UiSelection*, UiList*, int); + UiBool(*candrag)(UiEvent*, UiList*, int); + void(*data_get)(UiEvent*, UiSelection*, UiList*, int); + void(*data_delete)(UiEvent*, UiList*, int); }; struct UiListCallbacks { @@ -87,7 +93,7 @@ ui_callback selection; /* - * userdata for both callback + * userdata for all callbacks */ void *userdata; }; @@ -114,6 +120,11 @@ UIWIDGET ui_table(UiObject *obj, UiList *data, UiModel *model, UiListCallbacks cb); UIWIDGET ui_table_nv(UiObject *obj, char *varname, UiModel *model, UiListCallbacks cb); +void ui_table_dragsource(UIWIDGET tablewidget, int actions, char *target0, ...); +void ui_table_dragsource_a(UIWIDGET tablewidget, int actions, char **targets, int nelm); +void ui_table_dragdest(UIWIDGET tablewidget, int actions, char *target0, ...); +void ui_table_dragdest_a(UIWIDGET tablewidget, int actions, char **targets, int nelm); + UIWIDGET ui_combobox(UiObject *obj, UiList *list, ui_getvaluefunc getvalue, ui_callback f, void *udata); UIWIDGET ui_combobox_str(UiObject *obj, UiList *list, ui_callback f, void *udata); UIWIDGET ui_combobox_nv(UiObject *obj, char *varname, ui_getvaluefunc getvalue, ui_callback f, void *udata);