ui/gtk/list.c

changeset 438
7b1d715e5c11
parent 437
f02a62de0328
child 439
bf7084544cb1
equal deleted inserted replaced
437:f02a62de0328 438:7b1d715e5c11
45 45
46 46
47 void* ui_strmodel_getvalue(void *elm, int column) { 47 void* ui_strmodel_getvalue(void *elm, int column) {
48 return column == 0 ? elm : NULL; 48 return column == 0 ? elm : NULL;
49 } 49 }
50
51 /*
52 static GtkTargetEntry targetentries[] =
53 {
54 { "STRING", 0, 0 },
55 { "text/plain", 0, 1 },
56 { "text/uri-list", 0, 2 },
57 };
58 */
59
60 #if GTK_CHECK_VERSION(4, 10, 0)
61
62
63 /* BEGIN GObject wrapper for generic pointers */
64
65 typedef struct _ObjWrapper {
66 GObject parent_instance;
67 void *data;
68 } ObjWrapper;
69
70 typedef struct _ObjWrapperClass {
71 GObjectClass parent_class;
72 } ObjWrapperClass;
73
74 G_DEFINE_TYPE(ObjWrapper, obj_wrapper, G_TYPE_OBJECT)
75
76 static void obj_wrapper_class_init(ObjWrapperClass *klass) {
77
78 }
79
80 static void obj_wrapper_init(ObjWrapper *self) {
81 self->data = NULL;
82 }
83
84 ObjWrapper* obj_wrapper_new(void* data) {
85 ObjWrapper *obj = g_object_new(obj_wrapper_get_type(), NULL);
86 obj->data = data;
87 return obj;
88 }
89
90 /* END GObject wrapper for generic pointers */
91
92 static void column_factory_setup(GtkListItemFactory *factory, GtkListItem *item, gpointer userdata) {
93 UiColData *col = userdata;
94 UiModel *model = col->listview->model;
95 UiModelType type = model->types[col->model_column];
96 if(type == UI_ICON_TEXT || type == UI_ICON_TEXT_FREE) {
97 GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
98 GtkWidget *image = gtk_image_new();
99 GtkWidget *label = gtk_label_new(NULL);
100 BOX_ADD(hbox, image);
101 BOX_ADD(hbox, label);
102 gtk_list_item_set_child(item, hbox);
103 g_object_set_data(G_OBJECT(hbox), "image", image);
104 g_object_set_data(G_OBJECT(hbox), "label", label);
105 } else if(type == UI_ICON) {
106 GtkWidget *image = gtk_image_new();
107 gtk_list_item_set_child(item, image);
108 } else {
109 GtkWidget *label = gtk_label_new(NULL);
110 gtk_label_set_xalign(GTK_LABEL(label), 0);
111 gtk_list_item_set_child(item, label);
112 }
113 }
114
115 static void column_factory_bind( GtkListItemFactory *factory, GtkListItem *item, gpointer userdata) {
116 UiColData *col = userdata;
117
118 ObjWrapper *obj = gtk_list_item_get_item(item);
119 UiModel *model = col->listview->model;
120 UiModelType type = model->types[col->model_column];
121
122 void *data = model->getvalue(obj->data, col->data_column);
123 GtkWidget *child = gtk_list_item_get_child(item);
124
125 bool freevalue = TRUE;
126 switch(type) {
127 case UI_STRING: {
128 freevalue = FALSE;
129 }
130 case UI_STRING_FREE: {
131 gtk_label_set_label(GTK_LABEL(child), data);
132 if(freevalue) {
133 free(data);
134 }
135 break;
136 }
137 case UI_INTEGER: {
138 intptr_t intvalue = (intptr_t)data;
139 char buf[32];
140 snprintf(buf, 32, "%d", (int)intvalue);
141 gtk_label_set_label(GTK_LABEL(child), buf);
142 break;
143 }
144 case UI_ICON: {
145 UiIcon *icon = data;
146 if(icon) {
147 gtk_image_set_from_paintable(GTK_IMAGE(child), GDK_PAINTABLE(icon->info));
148 }
149 break;
150 }
151 case UI_ICON_TEXT: {
152 freevalue = FALSE;
153 }
154 case UI_ICON_TEXT_FREE: {
155 void *data2 = model->getvalue(obj->data, col->data_column+1);
156 GtkWidget *image = g_object_get_data(G_OBJECT(child), "image");
157 GtkWidget *label = g_object_get_data(G_OBJECT(child), "label");
158 if(data && image) {
159 UiIcon *icon = data;
160 gtk_image_set_from_paintable(GTK_IMAGE(image), GDK_PAINTABLE(icon->info));
161 }
162 if(data2 && label) {
163 gtk_label_set_label(GTK_LABEL(label), data2);
164 }
165 if(freevalue) {
166 free(data2);
167 }
168 break;
169 }
170 }
171 }
172
173 static GtkSelectionModel* create_selection_model(UiListView *listview, GListStore *liststore, bool multiselection) {
174 GtkSelectionModel *selection_model;
175 if(multiselection) {
176 selection_model = GTK_SELECTION_MODEL(gtk_multi_selection_new(G_LIST_MODEL(liststore)));
177 } else {
178 selection_model = GTK_SELECTION_MODEL(gtk_single_selection_new(G_LIST_MODEL(liststore)));
179 }
180 g_signal_connect(selection_model, "selection-changed", G_CALLBACK(ui_listview_selection_changed), listview);
181 return selection_model;
182 }
183
184 static UiListView* create_listview(UiObject *obj, UiListArgs args) {
185 UiListView *tableview = malloc(sizeof(UiListView));
186 memset(tableview, 0, sizeof(UiListView));
187 tableview->obj = obj;
188 tableview->model = args.model;
189 tableview->onactivate = args.onactivate;
190 tableview->onactivatedata = args.onactivatedata;
191 tableview->onselection = args.onselection;
192 tableview->onselectiondata = args.onselectiondata;
193 tableview->ondragstart = args.ondragstart;
194 tableview->ondragstartdata = args.ondragstartdata;
195 tableview->ondragcomplete = args.ondragcomplete;
196 tableview->ondragcompletedata = args.ondragcompletedata;
197 tableview->ondrop = args.ondrop;
198 tableview->ondropdata = args.ondropsdata;
199 tableview->selection.count = 0;
200 tableview->selection.rows = NULL;
201 return tableview;
202 }
203
204 UIWIDGET ui_listview_create(UiObject *obj, UiListArgs args) {
205 UiObject* current = uic_current_obj(obj);
206
207 // to simplify things and share code with ui_tableview_create, we also
208 // use a UiModel for the listview
209 UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1);
210 model->getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue;
211 args.model = model;
212
213 GListStore *ls = g_list_store_new(G_TYPE_OBJECT);
214 UiListView *listview = create_listview(obj, args);
215
216 listview->columns = malloc(sizeof(UiColData));
217 listview->columns->listview = listview;
218 listview->columns->data_column = 0;
219 listview->columns->model_column = 0;
220
221 GtkListItemFactory *factory = gtk_signal_list_item_factory_new();
222 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), listview->columns);
223 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), listview->columns);
224
225 GtkSelectionModel *selection_model = create_selection_model(listview, ls, args.multiselection);
226 GtkWidget *view = gtk_list_view_new(GTK_SELECTION_MODEL(selection_model), factory);
227
228 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST);
229
230 // init listview
231 listview->widget = view;
232 listview->var = var;
233 listview->liststore = ls;
234 listview->selectionmodel = selection_model;
235 g_signal_connect(
236 view,
237 "destroy",
238 G_CALLBACK(ui_listview_destroy),
239 listview);
240
241 // bind listview to list
242 if(var && var->value) {
243 UiList *list = var->value;
244
245 list->obj = listview;
246 list->update = ui_listview_update2;
247 list->getselection = ui_listview_getselection2;
248 list->setselection = ui_listview_setselection2;
249
250 ui_update_liststore(ls, list);
251 }
252
253 // event handling
254 if(args.onactivate) {
255 // columnview and listview can use the same callback function, because
256 // the first parameter (which is technically a different pointer type)
257 // is ignored
258 g_signal_connect(view, "activate", G_CALLBACK(ui_columnview_activate), listview);
259 }
260
261 // add widget to parent
262 GtkWidget *scroll_area = SCROLLEDWINDOW_NEW();
263 gtk_scrolled_window_set_policy(
264 GTK_SCROLLED_WINDOW(scroll_area),
265 GTK_POLICY_AUTOMATIC,
266 GTK_POLICY_AUTOMATIC); // GTK_POLICY_ALWAYS
267 SCROLLEDWINDOW_SET_CHILD(scroll_area, view);
268
269 UI_APPLY_LAYOUT1(current, args);
270 current->container->add(current->container, scroll_area, FALSE);
271
272 // ct->current should point to view, not scroll_area, to make it possible
273 // to add a context menu
274 current->container->current = view;
275
276 return scroll_area;
277 }
278
279 UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs args) {
280 UiObject* current = uic_current_obj(obj);
281
282 // to simplify things and share code with ui_tableview_create, we also
283 // use a UiModel for the listview
284 UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1);
285 model->getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue;
286 args.model = model;
287
288 GListStore *ls = g_list_store_new(G_TYPE_OBJECT);
289 UiListView *listview = create_listview(obj, args);
290
291 listview->columns = malloc(sizeof(UiColData));
292 listview->columns->listview = listview;
293 listview->columns->data_column = 0;
294 listview->columns->model_column = 0;
295
296 GtkListItemFactory *factory = gtk_signal_list_item_factory_new();
297 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), listview->columns);
298 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), listview->columns);
299
300 GtkWidget *view = gtk_drop_down_new(G_LIST_MODEL(ls), NULL);
301 gtk_drop_down_set_factory(GTK_DROP_DOWN(view), factory);
302
303 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST);
304
305 // init listview
306 listview->widget = view;
307 listview->var = var;
308 listview->liststore = ls;
309 listview->selectionmodel = NULL;
310 g_signal_connect(
311 view,
312 "destroy",
313 G_CALLBACK(ui_listview_destroy),
314 listview);
315
316 // bind listview to list
317 if(var && var->value) {
318 UiList *list = var->value;
319
320 list->obj = listview;
321 list->update = ui_listview_update2;
322 list->getselection = ui_combobox_getselection;
323 list->setselection = ui_combobox_setselection;
324
325 ui_update_liststore(ls, list);
326 }
327
328 // event handling
329 if(args.onactivate) {
330 g_signal_connect(view, "activate", G_CALLBACK(ui_columnview_activate), listview);
331 }
332
333 // add widget to parent
334 UI_APPLY_LAYOUT1(current, args);
335 current->container->add(current->container, view, FALSE);
336 return view;
337 }
338
339 UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) {
340 UiObject* current = uic_current_obj(obj);
341
342 GListStore *ls = g_list_store_new(G_TYPE_OBJECT);
343 //g_list_store_append(ls, v1);
344
345 // create obj to store all relevant data we need for handling events
346 // and list updates
347 UiListView *tableview = create_listview(obj, args);
348
349 GtkSelectionModel *selection_model = create_selection_model(tableview, ls, args.multiselection);
350 GtkWidget *view = gtk_column_view_new(GTK_SELECTION_MODEL(selection_model));
351
352 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST);
353
354 // init tableview
355 tableview->widget = view;
356 tableview->var = var;
357 tableview->liststore = ls;
358 tableview->selectionmodel = selection_model;
359 g_signal_connect(
360 view,
361 "destroy",
362 G_CALLBACK(ui_listview_destroy),
363 tableview);
364
365
366 // create columns from UiModel
367 UiModel *model = args.model;
368 int columns = model ? model->columns : 0;
369
370 tableview->columns = calloc(columns, sizeof(UiColData));
371
372 int addi = 0;
373 for(int i=0;i<columns;i++) {
374 tableview->columns[i].listview = tableview;
375 tableview->columns[i].model_column = i;
376 tableview->columns[i].data_column = i+addi;
377
378 if(model->types[i] == UI_ICON_TEXT || model->types[i] == UI_ICON_TEXT_FREE) {
379 // icon+text has 2 data columns
380 addi++;
381 }
382
383 GtkListItemFactory *factory = gtk_signal_list_item_factory_new();
384 UiColData *col = &tableview->columns[i];
385 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), col);
386 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), col);
387
388 GtkColumnViewColumn *column = gtk_column_view_column_new(model->titles[i], factory);
389 gtk_column_view_column_set_resizable(column, true);
390 gtk_column_view_append_column(GTK_COLUMN_VIEW(view), column);
391 }
392
393 // bind listview to list
394 if(var && var->value) {
395 UiList *list = var->value;
396
397 list->obj = tableview;
398 list->update = ui_listview_update2;
399 list->getselection = ui_listview_getselection2;
400 list->setselection = ui_listview_setselection2;
401
402 ui_update_liststore(ls, list);
403 }
404
405 // event handling
406 if(args.onactivate) {
407 g_signal_connect(view, "activate", G_CALLBACK(ui_columnview_activate), tableview);
408 }
409
410 // add widget to parent
411 GtkWidget *scroll_area = SCROLLEDWINDOW_NEW();
412 gtk_scrolled_window_set_policy(
413 GTK_SCROLLED_WINDOW(scroll_area),
414 GTK_POLICY_AUTOMATIC,
415 GTK_POLICY_AUTOMATIC); // GTK_POLICY_ALWAYS
416 SCROLLEDWINDOW_SET_CHILD(scroll_area, view);
417
418 UI_APPLY_LAYOUT1(current, args);
419 current->container->add(current->container, scroll_area, FALSE);
420
421 // ct->current should point to view, not scroll_area, to make it possible
422 // to add a context menu
423 current->container->current = view;
424
425 return scroll_area;
426 }
427
428 static UiListSelection selectionmodel_get_selection(GtkSelectionModel *model) {
429 UiListSelection sel = { 0, NULL };
430 GtkBitset *bitset = gtk_selection_model_get_selection(model);
431 int n = gtk_bitset_get_size(bitset);
432 printf("bitset %d\n", n);
433
434 gtk_bitset_unref(bitset);
435 return sel;
436 }
437
438 static void listview_event(ui_callback cb, void *cbdata, UiListView *view) {
439 UiEvent event;
440 event.obj = view->obj;
441 event.document = event.obj->ctx->document;
442 event.window = event.obj->window;
443 event.intval = view->selection.count;
444 event.eventdata = &view->selection;
445 if(cb) {
446 cb(&event, cbdata);
447 }
448 }
449
450 void ui_columnview_activate(void *ignore, guint position, gpointer userdata) {
451 UiListView *view = userdata;
452 listview_event(view->onactivate, view->onactivatedata, view);
453 }
454
455 void ui_listview_selection_changed(GtkSelectionModel* self, guint position, guint n_items, gpointer userdata) {
456 UiListView *view = userdata;
457 free(view->selection.rows);
458 view->selection.count = 0;
459 view->selection.rows = NULL;
460
461 CX_ARRAY_DECLARE(int, newselection);
462 cx_array_initialize(newselection, 8);
463
464 size_t nitems = g_list_model_get_n_items(G_LIST_MODEL(view->liststore));
465
466 for(size_t i=0;i<nitems;i++) {
467 if(gtk_selection_model_is_selected(view->selectionmodel, i)) {
468 int s = (int)i;
469 cx_array_simple_add(newselection, s);
470 }
471 }
472
473 if(newselection_size > 0) {
474 view->selection.count = newselection_size;
475 view->selection.rows = newselection;
476 } else {
477 free(newselection);
478 }
479
480 listview_event(view->onselection, view->onselectiondata, view);
481 }
482
483 void ui_dropdown_activate(GtkDropDown* self, gpointer userdata) {
484 UiListView *view = userdata;
485 guint selection = gtk_drop_down_get_selected(GTK_DROP_DOWN(view->widget));
486 UiListSelection sel = { 0, NULL };
487 int sel2 = (int)selection;
488 if(selection != GTK_INVALID_LIST_POSITION) {
489 sel.count = 1;
490 sel.rows = &sel2;
491 }
492
493 if(view->onactivate) {
494 UiEvent event;
495 event.obj = view->obj;
496 event.document = event.obj->ctx->document;
497 event.window = event.obj->window;
498 event.intval = view->selection.count;
499 event.eventdata = &view->selection;
500 view->onactivate(&event, view->onactivatedata);
501 }
502 }
503
504 void ui_update_liststore(GListStore *liststore, UiList *list) {
505 g_list_store_remove_all(liststore);
506 void *elm = list->first(list);
507 while(elm) {
508 ObjWrapper *obj = obj_wrapper_new(elm);
509 g_list_store_append(liststore, obj);
510 elm = list->next(list);
511 }
512 }
513
514 void ui_listview_update2(UiList *list, int i) {
515 UiListView *view = list->obj;
516 ui_update_liststore(view->liststore, view->var->value);
517 }
518
519 UiListSelection ui_listview_getselection2(UiList *list) {
520 UiListView *view = list->obj;
521 UiListSelection selection;
522 selection.count = view->selection.count;
523 selection.rows = calloc(selection.count, sizeof(int));
524 memcpy(selection.rows, view->selection.rows, selection.count*sizeof(int));
525 return selection;
526 }
527
528 void ui_listview_setselection2(UiList *list, UiListSelection selection) {
529 UiListView *view = list->obj;
530 UiListSelection newselection;
531 newselection.count = view->selection.count;
532 if(selection.count > 0) {
533 newselection.rows = calloc(newselection.count, sizeof(int));
534 memcpy(newselection.rows, selection.rows, selection.count*sizeof(int));
535 } else {
536 newselection.rows = NULL;
537 }
538 free(view->selection.rows);
539 view->selection = newselection;
540
541 gtk_selection_model_unselect_all(view->selectionmodel);
542 if(selection.count > 0) {
543 for(int i=0;i<selection.count;i++) {
544 gtk_selection_model_select_item(view->selectionmodel, selection.rows[i], FALSE);
545 }
546 }
547 }
548
549 UiListSelection ui_combobox_getselection(UiList *list) {
550 UiListView *view = list->obj;
551 guint selection = gtk_drop_down_get_selected(GTK_DROP_DOWN(view->widget));
552 UiListSelection sel = { 0, NULL };
553 if(selection != GTK_INVALID_LIST_POSITION) {
554 sel.count = 1;
555 sel.rows = malloc(sizeof(int));
556 sel.rows[0] = (int)selection;
557 }
558 return sel;
559 }
560
561 void ui_combobox_setselection(UiList *list, UiListSelection selection) {
562 UiListView *view = list->obj;
563 if(selection.count > 0) {
564 gtk_drop_down_set_selected(GTK_DROP_DOWN(view->widget), selection.rows[0]);
565 } else {
566 gtk_drop_down_set_selected(GTK_DROP_DOWN(view->widget), GTK_INVALID_LIST_POSITION);
567 }
568 }
569
570 #else
50 571
51 static GtkListStore* create_list_store(UiList *list, UiModel *model) { 572 static GtkListStore* create_list_store(UiList *list, UiModel *model) {
52 int columns = model->columns; 573 int columns = model->columns;
53 GType types[2*columns]; 574 GType types[2*columns];
54 int c = 0; 575 int c = 0;
262 current->container->current = view; 783 current->container->current = view;
263 784
264 return scroll_area; 785 return scroll_area;
265 } 786 }
266 787
267 /*
268 static void drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer udata) {
269 printf("drag begin\n");
270
271 }
272
273 static void drag_end(
274 GtkWidget *widget,
275 GdkDragContext *context,
276 guint time,
277 gpointer udata)
278 {
279 printf("drag end\n");
280
281 }
282 */
283
284 /*
285 static GtkTargetEntry targetentries[] =
286 {
287 { "STRING", 0, 0 },
288 { "text/plain", 0, 1 },
289 { "text/uri-list", 0, 2 },
290 };
291 */
292
293 #if GTK_CHECK_VERSION(4, 10, 0)
294
295
296 /* BEGIN GObject wrapper for generic pointers */
297
298 typedef struct _ObjWrapper {
299 GObject parent_instance;
300 void *data;
301 } ObjWrapper;
302
303 typedef struct _ObjWrapperClass {
304 GObjectClass parent_class;
305 } ObjWrapperClass;
306
307 G_DEFINE_TYPE(ObjWrapper, obj_wrapper, G_TYPE_OBJECT)
308
309 static void obj_wrapper_class_init(ObjWrapperClass *klass) {
310
311 }
312
313 static void obj_wrapper_init(ObjWrapper *self) {
314 self->data = NULL;
315 }
316
317 ObjWrapper* obj_wrapper_new(void* data) {
318 ObjWrapper *obj = g_object_new(obj_wrapper_get_type(), NULL);
319 obj->data = data;
320 return obj;
321 }
322
323 /* END GObject wrapper for generic pointers */
324
325 static void column_factory_setup(GtkListItemFactory *factory, GtkListItem *item, gpointer userdata) {
326 UiColData *col = userdata;
327 UiModel *model = col->listview->model;
328 UiModelType type = model->types[col->model_column];
329 if(type == UI_ICON_TEXT || type == UI_ICON_TEXT_FREE) {
330 GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6);
331 GtkWidget *image = gtk_image_new();
332 GtkWidget *label = gtk_label_new(NULL);
333 BOX_ADD(hbox, image);
334 BOX_ADD(hbox, label);
335 gtk_list_item_set_child(item, hbox);
336 g_object_set_data(G_OBJECT(hbox), "image", image);
337 g_object_set_data(G_OBJECT(hbox), "label", label);
338 } else if(type == UI_ICON) {
339 GtkWidget *image = gtk_image_new();
340 gtk_list_item_set_child(item, image);
341 } else {
342 GtkWidget *label = gtk_label_new(NULL);
343 gtk_label_set_xalign(GTK_LABEL(label), 0);
344 gtk_list_item_set_child(item, label);
345 }
346 }
347
348 static void column_factory_bind( GtkListItemFactory *factory, GtkListItem *item, gpointer userdata) {
349 UiColData *col = userdata;
350
351 ObjWrapper *obj = gtk_list_item_get_item(item);
352 UiModel *model = col->listview->model;
353 UiModelType type = model->types[col->model_column];
354
355 void *data = model->getvalue(obj->data, col->data_column);
356 GtkWidget *child = gtk_list_item_get_child(item);
357
358 bool freevalue = TRUE;
359 switch(type) {
360 case UI_STRING: {
361 freevalue = FALSE;
362 }
363 case UI_STRING_FREE: {
364 gtk_label_set_label(GTK_LABEL(child), data);
365 if(freevalue) {
366 free(data);
367 }
368 break;
369 }
370 case UI_INTEGER: {
371 intptr_t intvalue = (intptr_t)data;
372 char buf[32];
373 snprintf(buf, 32, "%d", (int)intvalue);
374 gtk_label_set_label(GTK_LABEL(child), buf);
375 break;
376 }
377 case UI_ICON: {
378 UiIcon *icon = data;
379 if(icon) {
380 gtk_image_set_from_paintable(GTK_IMAGE(child), GDK_PAINTABLE(icon->info));
381 }
382 break;
383 }
384 case UI_ICON_TEXT: {
385 freevalue = FALSE;
386 }
387 case UI_ICON_TEXT_FREE: {
388 void *data2 = model->getvalue(obj->data, col->data_column+1);
389 GtkWidget *image = g_object_get_data(G_OBJECT(child), "image");
390 GtkWidget *label = g_object_get_data(G_OBJECT(child), "label");
391 if(data && image) {
392 UiIcon *icon = data;
393 gtk_image_set_from_paintable(GTK_IMAGE(image), GDK_PAINTABLE(icon->info));
394 }
395 if(data2 && label) {
396 gtk_label_set_label(GTK_LABEL(label), data2);
397 }
398 if(freevalue) {
399 free(data2);
400 }
401 break;
402 }
403 }
404 }
405
406 UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) {
407 UiObject* current = uic_current_obj(obj);
408
409 GListStore *ls = g_list_store_new(G_TYPE_OBJECT);
410 //g_list_store_append(ls, v1);
411
412 GtkSelectionModel *selection_model;
413 if(args.multiselection) {
414 selection_model = GTK_SELECTION_MODEL(gtk_multi_selection_new(G_LIST_MODEL(ls)));
415 } else {
416 selection_model = GTK_SELECTION_MODEL(gtk_single_selection_new(G_LIST_MODEL(ls)));
417 }
418
419 GtkWidget *view = gtk_column_view_new(GTK_SELECTION_MODEL(selection_model));
420
421 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST);
422
423 // create obj to store all relevant data we need for handling events
424 // and list updates
425 UiListView *tableview = malloc(sizeof(UiListView));
426 tableview->obj = obj;
427 tableview->widget = view;
428 tableview->var = var;
429 tableview->model = args.model;
430 tableview->liststore = ls;
431 tableview->selectionmodel = selection_model;
432 tableview->onactivate = args.onactivate;
433 tableview->onactivatedata = args.onactivatedata;
434 tableview->onselection = args.onselection;
435 tableview->onselectiondata = args.onselectiondata;
436 tableview->ondragstart = args.ondragstart;
437 tableview->ondragstartdata = args.ondragstartdata;
438 tableview->ondragcomplete = args.ondragcomplete;
439 tableview->ondragcompletedata = args.ondragcompletedata;
440 tableview->ondrop = args.ondrop;
441 tableview->ondropdata = args.ondropsdata;
442 tableview->selection.count = 0;
443 tableview->selection.rows = NULL;
444 g_signal_connect(
445 view,
446 "destroy",
447 G_CALLBACK(ui_listview_destroy),
448 tableview);
449
450
451 // create columns from UiModel
452 UiModel *model = args.model;
453 int columns = model ? model->columns : 0;
454
455 tableview->columns = calloc(columns, sizeof(UiColData));
456
457 int addi = 0;
458 for(int i=0;i<columns;i++) {
459 tableview->columns[i].listview = tableview;
460 tableview->columns[i].model_column = i;
461 tableview->columns[i].data_column = i+addi;
462
463 if(model->types[i] == UI_ICON_TEXT || model->types[i] == UI_ICON_TEXT_FREE) {
464 // icon+text has 2 data columns
465 addi++;
466 }
467
468 GtkListItemFactory *factory = gtk_signal_list_item_factory_new();
469 UiColData *col = &tableview->columns[i];
470 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), col);
471 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), col);
472
473 GtkColumnViewColumn *column = gtk_column_view_column_new(model->titles[i], factory);
474 gtk_column_view_column_set_resizable(column, true);
475 gtk_column_view_append_column(GTK_COLUMN_VIEW(view), column);
476 }
477
478 // bind listview to list
479 if(var && var->value) {
480 UiList *list = var->value;
481
482 list->obj = tableview;
483 list->update = ui_listview_update2;
484 list->getselection = ui_listview_getselection2;
485 list->setselection = ui_listview_setselection2;
486
487 ui_update_liststore(ls, list);
488 }
489
490 // event handling
491 if(args.onactivate) {
492 g_signal_connect(view, "activate", G_CALLBACK(ui_columnview_activate), tableview);
493 }
494 // always handle selection-changed, to keep track of the current selection
495 g_signal_connect(selection_model, "selection-changed", G_CALLBACK(ui_listview_selection_changed), tableview);
496
497 // add widget to parent
498 GtkWidget *scroll_area = SCROLLEDWINDOW_NEW();
499 gtk_scrolled_window_set_policy(
500 GTK_SCROLLED_WINDOW(scroll_area),
501 GTK_POLICY_AUTOMATIC,
502 GTK_POLICY_AUTOMATIC); // GTK_POLICY_ALWAYS
503 SCROLLEDWINDOW_SET_CHILD(scroll_area, view);
504
505 UI_APPLY_LAYOUT1(current, args);
506 current->container->add(current->container, scroll_area, FALSE);
507
508 // ct->current should point to view, not scroll_area, to make it possible
509 // to add a context menu
510 current->container->current = view;
511
512 return scroll_area;
513 }
514
515 static UiListSelection selectionmodel_get_selection(GtkSelectionModel *model) {
516 UiListSelection sel = { 0, NULL };
517 GtkBitset *bitset = gtk_selection_model_get_selection(model);
518 int n = gtk_bitset_get_size(bitset);
519 printf("bitset %d\n", n);
520
521 gtk_bitset_unref(bitset);
522 return sel;
523 }
524
525 static void listview_event(ui_callback cb, void *cbdata, UiListView *view) {
526 UiEvent event;
527 event.obj = view->obj;
528 event.document = event.obj->ctx->document;
529 event.window = event.obj->window;
530 event.intval = view->selection.count;
531 event.eventdata = &view->selection;
532 if(cb) {
533 cb(&event, cbdata);
534 }
535 }
536
537 void ui_columnview_activate(GtkColumnView* self, guint position, gpointer userdata) {
538 UiListView *view = userdata;
539 listview_event(view->onactivate, view->onactivatedata, view);
540 }
541
542 void ui_listview_selection_changed(GtkSelectionModel* self, guint position, guint n_items, gpointer userdata) {
543 UiListView *view = userdata;
544 free(view->selection.rows);
545 view->selection.count = 0;
546 view->selection.rows = NULL;
547
548 CX_ARRAY_DECLARE(int, newselection);
549 cx_array_initialize(newselection, 8);
550
551 size_t nitems = g_list_model_get_n_items(G_LIST_MODEL(view->liststore));
552
553 for(size_t i=0;i<nitems;i++) {
554 if(gtk_selection_model_is_selected(view->selectionmodel, i)) {
555 int s = (int)i;
556 cx_array_simple_add(newselection, s);
557 }
558 }
559
560 if(newselection_size > 0) {
561 view->selection.count = newselection_size;
562 view->selection.rows = newselection;
563 } else {
564 free(newselection);
565 }
566
567 listview_event(view->onselection, view->onselectiondata, view);
568 }
569
570 void ui_update_liststore(GListStore *liststore, UiList *list) {
571 g_list_store_remove_all(liststore);
572 void *elm = list->first(list);
573 while(elm) {
574 ObjWrapper *obj = obj_wrapper_new(elm);
575 g_list_store_append(liststore, obj);
576 elm = list->next(list);
577 }
578 }
579
580 void ui_listview_update2(UiList *list, int i) {
581 UiListView *view = list->obj;
582 ui_update_liststore(view->liststore, view->var->value);
583 }
584
585 UiListSelection ui_listview_getselection2(UiList *list) {
586 UiListView *view = list->obj;
587 UiListSelection selection;
588 selection.count = view->selection.count;
589 selection.rows = calloc(selection.count, sizeof(int));
590 memcpy(selection.rows, view->selection.rows, selection.count*sizeof(int));
591 return selection;
592 }
593
594 void ui_listview_setselection2(UiList *list, UiListSelection selection) {
595 UiListView *view = list->obj;
596 UiListSelection newselection;
597 newselection.count = view->selection.count;
598 if(selection.count > 0) {
599 newselection.rows = calloc(newselection.count, sizeof(int));
600 memcpy(newselection.rows, selection.rows, selection.count*sizeof(int));
601 } else {
602 newselection.rows = NULL;
603 }
604 free(view->selection.rows);
605 view->selection = newselection;
606
607 gtk_selection_model_unselect_all(view->selectionmodel);
608 if(selection.count > 0) {
609 for(int i=0;i<selection.count;i++) {
610 gtk_selection_model_select_item(view->selectionmodel, selection.rows[i], FALSE);
611 }
612 }
613 }
614
615 #else
616
617 UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) { 788 UIWIDGET ui_table_create(UiObject *obj, UiListArgs args) {
618 UiObject* current = uic_current_obj(obj); 789 UiObject* current = uic_current_obj(obj);
619 790
620 // create treeview 791 // create treeview
621 GtkWidget *view = gtk_tree_view_new(); 792 GtkWidget *view = gtk_tree_view_new();
778 949
779 return scroll_area; 950 return scroll_area;
780 } 951 }
781 952
782 953
954
955 void ui_listview_update(UiList *list, int i) {
956 UiListView *view = list->obj;
957 GtkListStore *store = create_list_store(list, view->model);
958 gtk_tree_view_set_model(GTK_TREE_VIEW(view->widget), GTK_TREE_MODEL(store));
959 g_object_unref(G_OBJECT(store));
960 }
961
962 UiListSelection ui_listview_getselection(UiList *list) {
963 UiListView *view = list->obj;
964 UiListSelection selection = ui_listview_selection(
965 gtk_tree_view_get_selection(GTK_TREE_VIEW(view->widget)),
966 NULL);
967 return selection;
968 }
969
970 void ui_listview_setselection(UiList *list, UiListSelection selection) {
971 UiListView *view = list->obj;
972 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view->widget));
973 GtkTreePath *path = gtk_tree_path_new_from_indicesv(selection.rows, selection.count);
974 gtk_tree_selection_select_path(sel, path);
975 //g_object_unref(path);
976 }
977
978
979
980 /* --------------------------- ComboBox --------------------------- */
981
982 UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs args) {
983 UiObject* current = uic_current_obj(obj);
984
985 UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1);
986 model->getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue;
987
988 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST);
989
990 GtkWidget *combobox = ui_create_combobox(obj, model, var, args.onactivate, args.onactivatedata);
991 ui_set_name_and_style(combobox, args.name, args.style_class);
992 ui_set_widget_groups(obj->ctx, combobox, args.groups);
993 UI_APPLY_LAYOUT1(current, args);
994 current->container->add(current->container, combobox, FALSE);
995 current->container->current = combobox;
996 return combobox;
997 }
998
999 GtkWidget* ui_create_combobox(UiObject *obj, UiModel *model, UiVar *var, ui_callback f, void *udata) {
1000 GtkWidget *combobox = gtk_combo_box_new();
1001
1002 UiListView *uicbox = malloc(sizeof(UiListView));
1003 uicbox->obj = obj;
1004 uicbox->widget = combobox;
1005
1006 UiList *list = var ? var->value : NULL;
1007 GtkListStore *listmodel = create_list_store(list, model);
1008
1009 if(listmodel) {
1010 gtk_combo_box_set_model(GTK_COMBO_BOX(combobox), GTK_TREE_MODEL(listmodel));
1011 g_object_unref(listmodel);
1012 }
1013
1014 uicbox->var = var;
1015 uicbox->model = model;
1016
1017 g_signal_connect(
1018 combobox,
1019 "destroy",
1020 G_CALLBACK(ui_combobox_destroy),
1021 uicbox);
1022
1023 // bind var
1024 if(list) {
1025 list->update = ui_combobox_modelupdate;
1026 list->getselection = ui_combobox_getselection;
1027 list->setselection = ui_combobox_setselection;
1028 list->obj = uicbox;
1029 }
1030
1031 GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
1032 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), renderer, TRUE);
1033 gtk_cell_layout_set_attributes(
1034 GTK_CELL_LAYOUT(combobox),
1035 renderer,
1036 "text",
1037 0,
1038 NULL);
1039 gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), 0);
1040
1041 // add callback
1042 if(f) {
1043 UiEventData *event = ui_malloc(obj->ctx, sizeof(UiEventData));
1044 event->obj = obj;
1045 event->userdata = udata;
1046 event->callback = f;
1047 event->value = 0;
1048 event->customdata = NULL;
1049
1050 g_signal_connect(
1051 combobox,
1052 "changed",
1053 G_CALLBACK(ui_combobox_change_event),
1054 event);
1055 }
1056
1057 return combobox;
1058 }
1059
1060 void ui_combobox_change_event(GtkComboBox *widget, UiEventData *e) {
1061 UiEvent event;
1062 event.obj = e->obj;
1063 event.window = event.obj->window;
1064 event.document = event.obj->ctx->document;
1065 event.eventdata = NULL;
1066 event.intval = gtk_combo_box_get_active(widget);
1067 e->callback(&event, e->userdata);
1068 }
1069
1070 void ui_combobox_modelupdate(UiList *list, int i) {
1071 UiListView *view = list->obj;
1072 GtkListStore *store = create_list_store(view->var->value, view->model);
1073 gtk_combo_box_set_model(GTK_COMBO_BOX(view->widget), GTK_TREE_MODEL(store));
1074 g_object_unref(store);
1075 }
1076
1077 UiListSelection ui_combobox_getselection(UiList *list) {
1078 UiListView *combobox = list->obj;
1079 UiListSelection ret;
1080 ret.rows = malloc(sizeof(int*));
1081 ret.count = 1;
1082 ret.rows[0] = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox->widget));
1083 return ret;
1084 }
1085
1086 void ui_combobox_setselection(UiList *list, UiListSelection selection) {
1087 UiListView *combobox = list->obj;
1088 if(selection.count > 0) {
1089 gtk_combo_box_set_active(GTK_COMBO_BOX(combobox->widget), selection.rows[0]);
1090 }
1091 }
1092
1093
1094
1095
1096 void ui_listview_activate_event(
1097 GtkTreeView *treeview,
1098 GtkTreePath *path,
1099 GtkTreeViewColumn *column,
1100 UiTreeEventData *event)
1101 {
1102 UiListSelection selection = ui_listview_selection(
1103 gtk_tree_view_get_selection(treeview),
1104 event);
1105
1106 UiEvent e;
1107 e.obj = event->obj;
1108 e.window = event->obj->window;
1109 e.document = event->obj->ctx->document;
1110 e.eventdata = &selection;
1111 e.intval = selection.count > 0 ? selection.rows[0] : -1;
1112 event->activate(&e, event->activatedata);
1113
1114 if(selection.count > 0) {
1115 free(selection.rows);
1116 }
1117 }
1118
1119 void ui_listview_selection_event(
1120 GtkTreeSelection *treeselection,
1121 UiTreeEventData *event)
1122 {
1123 UiListSelection selection = ui_listview_selection(treeselection, event);
1124
1125 UiEvent e;
1126 e.obj = event->obj;
1127 e.window = event->obj->window;
1128 e.document = event->obj->ctx->document;
1129 e.eventdata = &selection;
1130 e.intval = selection.count > 0 ? selection.rows[0] : -1;
1131 event->selection(&e, event->selectiondata);
1132
1133 if(selection.count > 0) {
1134 free(selection.rows);
1135 }
1136 }
1137
1138 UiListSelection ui_listview_selection(
1139 GtkTreeSelection *selection,
1140 UiTreeEventData *event)
1141 {
1142 GList *rows = gtk_tree_selection_get_selected_rows(selection, NULL);
1143
1144 UiListSelection ls;
1145 ls.count = g_list_length(rows);
1146 ls.rows = calloc(ls.count, sizeof(int));
1147 GList *r = rows;
1148 int i = 0;
1149 while(r) {
1150 GtkTreePath *path = r->data;
1151 ls.rows[i] = ui_tree_path_list_index(path);
1152 r = r->next;
1153 i++;
1154 }
1155 return ls;
1156 }
1157
1158 int ui_tree_path_list_index(GtkTreePath *path) {
1159 int depth = gtk_tree_path_get_depth(path);
1160 if(depth == 0) {
1161 fprintf(stderr, "UiError: treeview selection: depth == 0\n");
1162 return -1;
1163 }
1164 int *indices = gtk_tree_path_get_indices(path);
1165 return indices[depth - 1];
1166 }
1167
1168
783 #endif 1169 #endif
784 1170
785 1171
786 #if GTK_MAJOR_VERSION >= 4 1172 #if GTK_MAJOR_VERSION >= 4
787 1173
1090 nelm, 1476 nelm,
1091 GDK_ACTION_COPY|GDK_ACTION_MOVE|GDK_ACTION_LINK); 1477 GDK_ACTION_COPY|GDK_ACTION_MOVE|GDK_ACTION_LINK);
1092 free(t); 1478 free(t);
1093 } 1479 }
1094 */ 1480 */
1095
1096 void ui_listview_update(UiList *list, int i) {
1097 UiListView *view = list->obj;
1098 GtkListStore *store = create_list_store(list, view->model);
1099 gtk_tree_view_set_model(GTK_TREE_VIEW(view->widget), GTK_TREE_MODEL(store));
1100 g_object_unref(G_OBJECT(store));
1101 }
1102
1103 UiListSelection ui_listview_getselection(UiList *list) {
1104 UiListView *view = list->obj;
1105 UiListSelection selection = ui_listview_selection(
1106 gtk_tree_view_get_selection(GTK_TREE_VIEW(view->widget)),
1107 NULL);
1108 return selection;
1109 }
1110
1111 void ui_listview_setselection(UiList *list, UiListSelection selection) {
1112 UiListView *view = list->obj;
1113 GtkTreeSelection *sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(view->widget));
1114 GtkTreePath *path = gtk_tree_path_new_from_indicesv(selection.rows, selection.count);
1115 gtk_tree_selection_select_path(sel, path);
1116 //g_object_unref(path);
1117 }
1118 1481
1119 void ui_listview_destroy(GtkWidget *w, UiListView *v) { 1482 void ui_listview_destroy(GtkWidget *w, UiListView *v) {
1120 //gtk_tree_view_set_model(GTK_TREE_VIEW(w), NULL); 1483 //gtk_tree_view_set_model(GTK_TREE_VIEW(w), NULL);
1121 ui_destroy_boundvar(v->obj->ctx, v->var); 1484 ui_destroy_boundvar(v->obj->ctx, v->var);
1122 #if GTK_CHECK_VERSION(4, 10, 0) 1485 #if GTK_CHECK_VERSION(4, 10, 0)
1127 } 1490 }
1128 1491
1129 void ui_combobox_destroy(GtkWidget *w, UiListView *v) { 1492 void ui_combobox_destroy(GtkWidget *w, UiListView *v) {
1130 ui_destroy_boundvar(v->obj->ctx, v->var); 1493 ui_destroy_boundvar(v->obj->ctx, v->var);
1131 free(v); 1494 free(v);
1132 }
1133
1134
1135 void ui_listview_activate_event(
1136 GtkTreeView *treeview,
1137 GtkTreePath *path,
1138 GtkTreeViewColumn *column,
1139 UiTreeEventData *event)
1140 {
1141 UiListSelection selection = ui_listview_selection(
1142 gtk_tree_view_get_selection(treeview),
1143 event);
1144
1145 UiEvent e;
1146 e.obj = event->obj;
1147 e.window = event->obj->window;
1148 e.document = event->obj->ctx->document;
1149 e.eventdata = &selection;
1150 e.intval = selection.count > 0 ? selection.rows[0] : -1;
1151 event->activate(&e, event->activatedata);
1152
1153 if(selection.count > 0) {
1154 free(selection.rows);
1155 }
1156 }
1157
1158 void ui_listview_selection_event(
1159 GtkTreeSelection *treeselection,
1160 UiTreeEventData *event)
1161 {
1162 UiListSelection selection = ui_listview_selection(treeselection, event);
1163
1164 UiEvent e;
1165 e.obj = event->obj;
1166 e.window = event->obj->window;
1167 e.document = event->obj->ctx->document;
1168 e.eventdata = &selection;
1169 e.intval = selection.count > 0 ? selection.rows[0] : -1;
1170 event->selection(&e, event->selectiondata);
1171
1172 if(selection.count > 0) {
1173 free(selection.rows);
1174 }
1175 }
1176
1177 UiListSelection ui_listview_selection(
1178 GtkTreeSelection *selection,
1179 UiTreeEventData *event)
1180 {
1181 GList *rows = gtk_tree_selection_get_selected_rows(selection, NULL);
1182
1183 UiListSelection ls;
1184 ls.count = g_list_length(rows);
1185 ls.rows = calloc(ls.count, sizeof(int));
1186 GList *r = rows;
1187 int i = 0;
1188 while(r) {
1189 GtkTreePath *path = r->data;
1190 ls.rows[i] = ui_tree_path_list_index(path);
1191 r = r->next;
1192 i++;
1193 }
1194 return ls;
1195 }
1196
1197 int ui_tree_path_list_index(GtkTreePath *path) {
1198 int depth = gtk_tree_path_get_depth(path);
1199 if(depth == 0) {
1200 fprintf(stderr, "UiError: treeview selection: depth == 0\n");
1201 return -1;
1202 }
1203 int *indices = gtk_tree_path_get_indices(path);
1204 return indices[depth - 1];
1205 }
1206
1207
1208 /* --------------------------- ComboBox --------------------------- */
1209
1210 UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs args) {
1211 UiObject* current = uic_current_obj(obj);
1212
1213 UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1);
1214 model->getvalue = args.getvalue ? args.getvalue : ui_strmodel_getvalue;
1215
1216 UiVar* var = uic_widget_var(obj->ctx, current->ctx, args.list, args.varname, UI_VAR_LIST);
1217
1218 GtkWidget *combobox = ui_create_combobox(obj, model, var, args.onactivate, args.onactivatedata);
1219 ui_set_name_and_style(combobox, args.name, args.style_class);
1220 ui_set_widget_groups(obj->ctx, combobox, args.groups);
1221 UI_APPLY_LAYOUT1(current, args);
1222 current->container->add(current->container, combobox, FALSE);
1223 current->container->current = combobox;
1224 return combobox;
1225 }
1226
1227 GtkWidget* ui_create_combobox(UiObject *obj, UiModel *model, UiVar *var, ui_callback f, void *udata) {
1228 GtkWidget *combobox = gtk_combo_box_new();
1229
1230 UiListView *uicbox = malloc(sizeof(UiListView));
1231 uicbox->obj = obj;
1232 uicbox->widget = combobox;
1233
1234 UiList *list = var ? var->value : NULL;
1235 GtkListStore *listmodel = create_list_store(list, model);
1236
1237 if(listmodel) {
1238 gtk_combo_box_set_model(GTK_COMBO_BOX(combobox), GTK_TREE_MODEL(listmodel));
1239 g_object_unref(listmodel);
1240 }
1241
1242 uicbox->var = var;
1243 uicbox->model = model;
1244
1245 g_signal_connect(
1246 combobox,
1247 "destroy",
1248 G_CALLBACK(ui_combobox_destroy),
1249 uicbox);
1250
1251 // bind var
1252 if(list) {
1253 list->update = ui_combobox_modelupdate;
1254 list->getselection = ui_combobox_getselection;
1255 list->setselection = ui_combobox_setselection;
1256 list->obj = uicbox;
1257 }
1258
1259 GtkCellRenderer *renderer = gtk_cell_renderer_text_new();
1260 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), renderer, TRUE);
1261 gtk_cell_layout_set_attributes(
1262 GTK_CELL_LAYOUT(combobox),
1263 renderer,
1264 "text",
1265 0,
1266 NULL);
1267 gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), 0);
1268
1269 // add callback
1270 if(f) {
1271 UiEventData *event = ui_malloc(obj->ctx, sizeof(UiEventData));
1272 event->obj = obj;
1273 event->userdata = udata;
1274 event->callback = f;
1275 event->value = 0;
1276 event->customdata = NULL;
1277
1278 g_signal_connect(
1279 combobox,
1280 "changed",
1281 G_CALLBACK(ui_combobox_change_event),
1282 event);
1283 }
1284
1285 return combobox;
1286 }
1287
1288 void ui_combobox_change_event(GtkComboBox *widget, UiEventData *e) {
1289 UiEvent event;
1290 event.obj = e->obj;
1291 event.window = event.obj->window;
1292 event.document = event.obj->ctx->document;
1293 event.eventdata = NULL;
1294 event.intval = gtk_combo_box_get_active(widget);
1295 e->callback(&event, e->userdata);
1296 }
1297
1298 void ui_combobox_modelupdate(UiList *list, int i) {
1299 UiListView *view = list->obj;
1300 GtkListStore *store = create_list_store(view->var->value, view->model);
1301 gtk_combo_box_set_model(GTK_COMBO_BOX(view->widget), GTK_TREE_MODEL(store));
1302 g_object_unref(store);
1303 }
1304
1305 UiListSelection ui_combobox_getselection(UiList *list) {
1306 UiListView *combobox = list->obj;
1307 UiListSelection ret;
1308 ret.rows = malloc(sizeof(int*));
1309 ret.count = 1;
1310 ret.rows[0] = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox->widget));
1311 return ret;
1312 }
1313
1314 void ui_combobox_setselection(UiList *list, UiListSelection selection) {
1315 UiListView *combobox = list->obj;
1316 if(selection.count > 0) {
1317 gtk_combo_box_set_active(GTK_COMBO_BOX(combobox->widget), selection.rows[0]);
1318 }
1319 } 1495 }
1320 1496
1321 1497
1322 /* ------------------------------ Source List ------------------------------ */ 1498 /* ------------------------------ Source List ------------------------------ */
1323 1499

mercurial