ui/gtk/list.c

changeset 1245
4163776eef49
parent 1244
a29b53f97d1a
equal deleted inserted replaced
1244:a29b53f97d1a 1245:4163776eef49
38 38
39 #include <cx/array_list.h> 39 #include <cx/array_list.h>
40 #include <cx/linked_list.h> 40 #include <cx/linked_list.h>
41 41
42 #include "list.h" 42 #include "list.h"
43 #include "tree.h"
43 #include "button.h" 44 #include "button.h"
44 #include "icon.h" 45 #include "icon.h"
45 #include "menu.h" 46 #include "menu.h"
46 #include "dnd.h" 47 #include "dnd.h"
47 48
121 } 122 }
122 123
123 return tableview; 124 return tableview;
124 } 125 }
125 126
126 static UiListView* create_treeview(UiObject *obj, UiTreeArgs *args) {
127 UiListView *treeview = malloc(sizeof(UiListView));
128 memset(treeview, 0, sizeof(UiListView));
129 treeview->obj = obj;
130 treeview->model = args->model;
131 treeview->multiselection = args->multiselection;
132 treeview->onactivate = args->onactivate;
133 treeview->onactivatedata = args->onactivatedata;
134 treeview->onactivate_action = args->onactivate_action ? strdup(args->onactivate_action) : NULL;
135 treeview->onselection = args->onselection;
136 treeview->onselectiondata = args->onselectiondata;
137 treeview->onselection_action = args->onselection_action ? strdup(args->onselection_action) : NULL;
138 treeview->ondragstart = args->ondragstart;
139 treeview->ondragstartdata = args->ondragstartdata;
140 treeview->ondragstart_action = args->ondragstart_action ? strdup(args->ondragstart_action) : NULL;
141 treeview->ondragcomplete = args->ondragcomplete;
142 treeview->ondragcompletedata = args->ondragcompletedata;
143 treeview->ondragcomplete_action = args->ondragcomplete_action ? strdup(args->ondragcomplete_action) : NULL;
144 treeview->ondrop = args->ondrop;
145 treeview->ondropdata = args->ondropdata;
146 treeview->ondrop_action = args->ondrop_action ? strdup(args->ondrop_action) : NULL;
147 treeview->selection.count = 0;
148 treeview->selection.rows = NULL;
149 treeview->current_row = -1;
150
151 #if GTK_CHECK_VERSION(4, 0, 0)
152 treeview->coldata.listview = treeview;
153 treeview->coldata.column = 0;
154 #endif
155
156 if(args->getvalue != NULL) {
157 treeview->getvalue = args->getvalue;
158 treeview->getvaluedata = args->getvaluedata;
159 } else {
160 args->getvalue = ui_null_getvalue;
161 }
162
163 treeview->istreeview = TRUE;
164 treeview->getdepth = args->getdepth;
165 treeview->getdepthdata = args->getdepthdata;
166
167 return treeview;
168 }
169
170 #if GTK_CHECK_VERSION(4, 10, 0) 127 #if GTK_CHECK_VERSION(4, 10, 0)
171 128
172 129
173 /* BEGIN GObject wrapper for generic pointers */ 130 /* BEGIN GObject wrapper for generic pointers */
131
132 typedef struct _ObjWrapper {
133 GObject parent_instance;
134 GListStore *children;
135 void *data;
136 int i;
137 } ObjWrapper;
174 138
175 typedef struct _ObjWrapperClass { 139 typedef struct _ObjWrapperClass {
176 GObjectClass parent_class; 140 GObjectClass parent_class;
177 } ObjWrapperClass; 141 } ObjWrapperClass;
178 142
181 static void obj_wrapper_class_init(ObjWrapperClass *klass) { 145 static void obj_wrapper_class_init(ObjWrapperClass *klass) {
182 146
183 } 147 }
184 148
185 static void obj_wrapper_init(ObjWrapper *self) { 149 static void obj_wrapper_init(ObjWrapper *self) {
150 self->children = NULL;
186 self->data = NULL; 151 self->data = NULL;
187 } 152 }
188 153
189 ObjWrapper* ui_gobj_wrapper_new(void* data, int i) { 154 ObjWrapper* ui_gobj_wrapper_new(void* data, int i) {
190 ObjWrapper *obj = g_object_new(obj_wrapper_get_type(), NULL); 155 ObjWrapper *obj = g_object_new(obj_wrapper_get_type(), NULL);
800 765
801 766
802 767
803 UIWIDGET ui_treeview_create(UiObject *obj, UiTreeArgs *args) { 768 UIWIDGET ui_treeview_create(UiObject *obj, UiTreeArgs *args) {
804 GListStore *ls = g_list_store_new(G_TYPE_OBJECT); 769 GListStore *ls = g_list_store_new(G_TYPE_OBJECT);
805 //g_list_store_append(ls, v1);
806 770
807 // create obj to store all relevant data we need for handling events 771 // create obj to store all relevant data we need for handling events
808 // and list updates 772 // and list updates
809 UiListView *tableview = create_treeview(obj, args); 773 UiListView *treeview = ui_create_treeview(obj, args);
810 774
811 GtkSelectionModel *selection_model = create_selection_model(tableview, ls, args->multiselection); 775 GtkSelectionModel *selection_model = create_selection_model(treeview, ls, args->multiselection);
812 GtkWidget *view = gtk_column_view_new(GTK_SELECTION_MODEL(selection_model)); 776 GtkWidget *view = gtk_column_view_new(GTK_SELECTION_MODEL(selection_model));
813 if(!args->show_header) { 777 if(!args->show_header) {
814 gtk_widget_set_visible(gtk_widget_get_first_child(view), FALSE); 778 gtk_widget_set_visible(gtk_widget_get_first_child(view), FALSE);
815 } 779 }
816 780
817 UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST); 781 UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST);
818 782
819 // init tableview 783 // init tableview
820 tableview->widget = view; 784 treeview->widget = view;
821 tableview->var = var; 785 treeview->var = var;
822 tableview->liststore = ls; 786 treeview->liststore = ls;
823 tableview->selectionmodel = selection_model; 787 treeview->selectionmodel = selection_model;
824 g_signal_connect( 788 g_signal_connect(
825 view, 789 view,
826 "destroy", 790 "destroy",
827 G_CALLBACK(ui_listview_destroy), 791 G_CALLBACK(ui_listview_destroy),
828 tableview); 792 treeview);
829 793
830 794
831 // create columns from UiModel 795 // create columns from UiModel
832 UiModel *model = args->model; 796 UiModel *model = args->model;
833 int columns = 0; 797 int columns = 0;
834 if(model) { 798 if(model) {
835 columns = model->columns; 799 columns = model->columns;
836 ui_model_add_observer(model, ui_listview_update_model, tableview); 800 ui_model_add_observer(model, ui_listview_update_model, treeview);
837 } 801 }
838 802
839 tableview->columns = calloc(columns, sizeof(int)); 803 treeview->columns = calloc(columns, sizeof(int));
840 tableview->numcolumns = columns; 804 treeview->numcolumns = columns;
841 805
842 tableview->bound_rows = cxHashMapCreate(NULL, CX_STORE_POINTERS, 128); 806 treeview->bound_rows = cxHashMapCreate(NULL, CX_STORE_POINTERS, 128);
843 tableview->bound_rows->collection.simple_destructor = (cx_destructor_func)free; 807 treeview->bound_rows->collection.simple_destructor = (cx_destructor_func)free;
844 808
845 int addi = 0; 809 int addi = 0;
846 for(int i=0;i<columns;i++) { 810 for(int i=0;i<columns;i++) {
847 tableview->columns[i] = i+addi; 811 treeview->columns[i] = i+addi;
848 812
849 if(model->types[i] == UI_ICON_TEXT || model->types[i] == UI_ICON_TEXT_FREE) { 813 if(model->types[i] == UI_ICON_TEXT || model->types[i] == UI_ICON_TEXT_FREE) {
850 // icon+text has 2 data columns 814 // icon+text has 2 data columns
851 addi++; 815 addi++;
852 } 816 }
853 817
854 add_column(tableview, i); 818 add_column(treeview, i);
855 } 819 }
856 820
857 // bind listview to list 821 // bind listview to list
858 if(var && var->value) { 822 if(var && var->value) {
859 UiList *list = var->value; 823 UiList *list = var->value;
860 824
861 list->obj = tableview; 825 list->obj = treeview;
862 list->update = ui_listview_update2; 826 list->update = ui_listview_update2;
863 list->getselection = ui_listview_getselection2; 827 list->getselection = ui_listview_getselection2;
864 list->setselection = ui_listview_setselection2; 828 list->setselection = ui_listview_setselection2;
865 829
866 ui_update_liststore(ls, list); 830 ui_update_tree_liststore(ls, list);
867 } 831 }
868 832
869 // event handling 833 // event handling
870 if(args->onactivate || args->onactivate_action) { 834 if(args->onactivate || args->onactivate_action) {
871 g_signal_connect(view, "activate", G_CALLBACK(ui_columnview_activate), tableview); 835 g_signal_connect(view, "activate", G_CALLBACK(ui_columnview_activate), treeview);
872 } 836 }
873 if(args->contextmenu) { 837 if(args->contextmenu) {
874 UIMENU menu = ui_contextmenu_create(args->contextmenu, obj, view); 838 UIMENU menu = ui_contextmenu_create(args->contextmenu, obj, view);
875 ui_widget_set_contextmenu(view, menu); 839 ui_widget_set_contextmenu(view, menu);
876 } 840 }
1062 while(elm) { 1026 while(elm) {
1063 ObjWrapper *obj = ui_gobj_wrapper_new(elm, i++); 1027 ObjWrapper *obj = ui_gobj_wrapper_new(elm, i++);
1064 g_list_store_append(liststore, obj); 1028 g_list_store_append(liststore, obj);
1065 elm = list->next(list); 1029 elm = list->next(list);
1066 } 1030 }
1031 }
1032
1033 void ui_update_tree_liststore(GListStore *liststore, UiList *list) {
1034
1067 } 1035 }
1068 1036
1069 void ui_update_liststore_static(GListStore *liststore, char **elm, size_t nelm) { 1037 void ui_update_liststore_static(GListStore *liststore, char **elm, size_t nelm) {
1070 g_list_store_remove_all(liststore); 1038 g_list_store_remove_all(liststore);
1071 for(int i=0;i<nelm;i++) { 1039 for(int i=0;i<nelm;i++) {
3066 3034
3067 if(data->callback) { 3035 if(data->callback) {
3068 data->callback(&event, data->userdata); 3036 data->callback(&event, data->userdata);
3069 } 3037 }
3070 } 3038 }
3039
3040 /* ------------------------------ SourceList2 ------------------------------ */
3041
3042 static void ui_destroy_sourcelist2(GtkWidget *w, UiListBox2 *v) {
3043 cxListFree(v->rows);
3044 free(v->onactivate_action);
3045 free(v->onbuttonclick_action);
3046 free(v);
3047 }
3048
3049 UIWIDGET ui_sourcelist2_create(UiObject *obj, UiSourceList2Args *args) {
3050 #ifdef UI_GTK3
3051 GtkWidget *listbox = g_object_new(ui_sidebar_list_box_get_type(), NULL);
3052 #else
3053 GtkWidget *listbox = gtk_list_box_new();
3054 #endif
3055 if(!args->style_class) {
3056 #if GTK_MAJOR_VERSION >= 4
3057 WIDGET_ADD_CSS_CLASS(listbox, "navigation-sidebar");
3058 #else
3059 WIDGET_ADD_CSS_CLASS(listbox, "sidebar");
3060 #endif
3061 }
3062 GtkWidget *scroll_area = SCROLLEDWINDOW_NEW();
3063 SCROLLEDWINDOW_SET_CHILD(scroll_area, listbox);
3064
3065 ui_set_name_and_style(listbox, args->name, args->style_class);
3066 ui_set_widget_states(obj->ctx, listbox, args->states);
3067 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end;
3068 UiLayout layout = UI_ARGS2LAYOUT(args);
3069 ct->add(ct, scroll_area, &layout);
3070
3071 UiListBox2 *uilistbox = malloc(sizeof(UiListBox2));
3072 uilistbox->obj = obj;
3073 uilistbox->listbox = GTK_LIST_BOX(listbox);
3074 uilistbox->rows = cxArrayListCreate(NULL, CX_STORE_POINTERS, 64);
3075 uilistbox->getvalue = args->getvalue;
3076 uilistbox->getvaluedata = args->getvaluedata;
3077 uilistbox->getdepth = args->getdepth;
3078 uilistbox->getdepthdata = args->getdepthdata;
3079 uilistbox->onactivate = args->onactivate;
3080 uilistbox->onactivatedata = args->onactivatedata;
3081 uilistbox->onactivate_action = args->onactivate_action ? strdup(args->onactivate_action) : NULL;
3082 uilistbox->onbuttonclick = args->onbuttonclick;
3083 uilistbox->onbuttonclickdata = args->onbuttonclickdata;
3084 uilistbox->onbuttonclick_action = args->onbuttonclick_action ? strdup(args->onbuttonclick_action) : NULL;
3085
3086 UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST);
3087 uilistbox->var = var;
3088 if(var) {
3089 UiList *list = var->value;
3090 list->update = ui_listbox2_update;
3091 list->getselection = ui_listbox2_getselection;
3092 list->setselection = ui_listbox2_setselection;
3093 list->obj = uilistbox;
3094 ui_listbox2_update(list, -1);
3095 }
3096
3097 // register uilistbox for both widgets, so it doesn't matter which
3098 // widget is used later
3099 g_object_set_data(G_OBJECT(scroll_area), "ui_listbox", uilistbox);
3100 g_object_set_data(G_OBJECT(listbox), "ui_listbox", uilistbox);
3101
3102 if(args->contextmenu) {
3103 UIMENU menu = ui_contextmenu_create(args->contextmenu, obj, listbox);
3104 ui_widget_set_contextmenu(listbox, menu);
3105 }
3106
3107 // signals
3108 g_signal_connect(
3109 listbox,
3110 "destroy",
3111 G_CALLBACK(ui_destroy_sourcelist2),
3112 uilistbox);
3113
3114 if(args->onactivate) {
3115 g_signal_connect(
3116 listbox,
3117 "row-activated",
3118 G_CALLBACK(ui_listbox2_row_activate),
3119 NULL);
3120 }
3121
3122 return scroll_area;
3123 }
3124
3125
3126 static int listbox2_update_item(UiListBox2 *listbox, GtkWidget *row, UiList *list, void *elm, int index) {
3127 UiSubListItem item = { NULL, NULL, NULL, NULL, NULL, NULL };
3128 if(listbox->getvalue) {
3129 listbox->getvalue(list,elm, index, &item, listbox->getvaluedata);
3130 }
3131
3132 GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
3133
3134 return 0;
3135 }
3136
3137 static void listbox2_update_all(UiListBox2 *listbox) {
3138 gtk_list_box_remove_all(listbox->listbox);
3139 cxListClear(listbox->rows);
3140 if(!listbox->var) {
3141 return;
3142 }
3143 UiList *list = listbox->var->value;
3144 if(!list) {
3145 return;
3146 }
3147
3148
3149 int index = 0;
3150 void *elm = list->first(list);
3151 while(elm) {
3152 GtkWidget *row = gtk_list_box_row_new();
3153 cxListAdd(listbox->rows, row);
3154 gtk_list_box_append(listbox->listbox, row);
3155 int node_depth = listbox2_update_item(listbox, row, list, elm, index);
3156
3157 elm = list->next(list);
3158 index++;
3159 }
3160 }
3161
3162 void ui_listbox2_row_activate(GtkListBox *self, GtkListBoxRow *row, gpointer user_data) {
3163
3164 }
3165
3166
3167 void ui_listbox2_update(UiList *list, int i) {
3168 UiListBox2 *listbox = list->obj;
3169 if(i >= 0) {
3170 // TODO
3171 } else {
3172 listbox2_update_all(listbox);
3173 }
3174 }
3175
3176 UiListSelection ui_listbox2_getselection(UiList *list) {
3177
3178 }
3179
3180 void ui_listbox2_setselection(UiList *list, UiListSelection selection) {
3181
3182 }

mercurial