| 78 static UiListView* create_listview(UiObject *obj, UiListArgs *args) { |
78 static UiListView* create_listview(UiObject *obj, UiListArgs *args) { |
| 79 UiListView *tableview = malloc(sizeof(UiListView)); |
79 UiListView *tableview = malloc(sizeof(UiListView)); |
| 80 memset(tableview, 0, sizeof(UiListView)); |
80 memset(tableview, 0, sizeof(UiListView)); |
| 81 tableview->obj = obj; |
81 tableview->obj = obj; |
| 82 tableview->model = args->model; |
82 tableview->model = args->model; |
| |
83 tableview->multiselection = args->multiselection; |
| 83 tableview->onactivate = args->onactivate; |
84 tableview->onactivate = args->onactivate; |
| 84 tableview->onactivatedata = args->onactivatedata; |
85 tableview->onactivatedata = args->onactivatedata; |
| 85 tableview->onselection = args->onselection; |
86 tableview->onselection = args->onselection; |
| 86 tableview->onselectiondata = args->onselectiondata; |
87 tableview->onselectiondata = args->onselectiondata; |
| 87 tableview->ondragstart = args->ondragstart; |
88 tableview->ondragstart = args->ondragstart; |
| 96 tableview->getstyle = args->getstyle; |
97 tableview->getstyle = args->getstyle; |
| 97 tableview->getstyledata = args->getstyledata; |
98 tableview->getstyledata = args->getstyledata; |
| 98 tableview->onsave = args->onsave; |
99 tableview->onsave = args->onsave; |
| 99 tableview->onsavedata = args->onsavedata; |
100 tableview->onsavedata = args->onsavedata; |
| 100 |
101 |
| |
102 #if GTK_CHECK_VERSION(4, 0, 0) |
| |
103 tableview->coldata.listview = tableview; |
| |
104 tableview->coldata.column = 0; |
| |
105 #endif |
| |
106 |
| 101 if(args->getvalue2) { |
107 if(args->getvalue2) { |
| 102 tableview->getvalue = args->getvalue2; |
108 tableview->getvalue = args->getvalue2; |
| 103 tableview->getvaluedata = args->getvalue2data; |
109 tableview->getvaluedata = args->getvalue2data; |
| 104 } else if(args->getvalue) { |
110 } else if(args->getvalue) { |
| 105 tableview->getvalue = getvalue_wrapper; |
111 tableview->getvalue = getvalue_wrapper; |
| 198 } |
204 } |
| 199 |
205 |
| 200 static void column_factory_setup(GtkListItemFactory *factory, GtkListItem *item, gpointer userdata) { |
206 static void column_factory_setup(GtkListItemFactory *factory, GtkListItem *item, gpointer userdata) { |
| 201 UiColData *col = userdata; |
207 UiColData *col = userdata; |
| 202 UiModel *model = col->listview->model; |
208 UiModel *model = col->listview->model; |
| 203 UiModelType type = model->types[col->model_column]; |
209 UiModelType type = model->types[col->column]; |
| 204 if(type == UI_ICON_TEXT || type == UI_ICON_TEXT_FREE) { |
210 if(type == UI_ICON_TEXT || type == UI_ICON_TEXT_FREE) { |
| 205 GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6); |
211 GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 6); |
| 206 GtkWidget *image = gtk_image_new(); |
212 GtkWidget *image = gtk_image_new(); |
| 207 GtkWidget *label = gtk_label_new(NULL); |
213 GtkWidget *label = gtk_label_new(NULL); |
| 208 BOX_ADD(hbox, image); |
214 BOX_ADD(hbox, image); |
| 279 |
285 |
| 280 static void column_factory_bind(GtkListItemFactory *unused, GtkListItem *item, gpointer userdata) { |
286 static void column_factory_bind(GtkListItemFactory *unused, GtkListItem *item, gpointer userdata) { |
| 281 UiColData *col = userdata; |
287 UiColData *col = userdata; |
| 282 UiList *list = col->listview->var ? col->listview->var->value : NULL; |
288 UiList *list = col->listview->var ? col->listview->var->value : NULL; |
| 283 UiListView *listview = col->listview; |
289 UiListView *listview = col->listview; |
| |
290 int datacolumn = listview->columns[col->column]; |
| 284 |
291 |
| 285 ObjWrapper *obj = gtk_list_item_get_item(item); |
292 ObjWrapper *obj = gtk_list_item_get_item(item); |
| 286 UiModel *model = col->listview->model; |
293 UiModel *model = col->listview->model; |
| 287 UiModelType type = model->types[col->model_column]; |
294 UiModelType type = model->types[col->column]; |
| 288 |
295 |
| 289 // cache the GtkListItem |
296 // cache the GtkListItem |
| 290 CxHashKey row_key = cx_hash_key(&obj->i, sizeof(int)); |
297 CxHashKey row_key = cx_hash_key(&obj->i, sizeof(int)); |
| 291 UiRowItems *row = cxMapGet(listview->bound_rows, row_key); |
298 UiRowItems *row = cxMapGet(listview->bound_rows, row_key); |
| 292 if(row) { |
299 if(row) { |
| 293 if(row->items[col->model_column] == NULL) { |
300 if(row->items[col->column] == NULL) { |
| 294 row->bound++; |
301 row->bound++; |
| 295 } |
302 } |
| 296 } else { |
303 } else { |
| 297 row = calloc(1, sizeof(UiRowItems) + listview->numcolumns * sizeof(GtkListItem*)); |
304 row = calloc(1, sizeof(UiRowItems) + listview->numcolumns * sizeof(GtkListItem*)); |
| 298 cxMapPut(listview->bound_rows, row_key, row); |
305 cxMapPut(listview->bound_rows, row_key, row); |
| 299 row->bound = 1; |
306 row->bound = 1; |
| 300 } |
307 } |
| 301 row->items[col->model_column] = item; |
308 row->items[col->column] = item; |
| 302 |
309 |
| 303 UiBool freevalue = FALSE; |
310 UiBool freevalue = FALSE; |
| 304 void *data = listview->getvalue(list, obj->data, obj->i, col->data_column, listview->getvaluedata, &freevalue); |
311 void *data = listview->getvalue(list, obj->data, obj->i, datacolumn, listview->getvaluedata, &freevalue); |
| 305 GtkWidget *child = gtk_list_item_get_child(item); |
312 GtkWidget *child = gtk_list_item_get_child(item); |
| 306 |
313 |
| 307 PangoAttrList *attributes = NULL; |
314 PangoAttrList *attributes = NULL; |
| 308 UiTextStyle style = { 0, 0 }; |
315 UiTextStyle style = { 0, 0 }; |
| 309 if(listview->getstyle) { |
316 if(listview->getstyle) { |
| 317 pango_attr_list_unref(listview->current_row_attributes); |
324 pango_attr_list_unref(listview->current_row_attributes); |
| 318 listview->current_row_attributes = textstyle2pangoattributes(style); |
325 listview->current_row_attributes = textstyle2pangoattributes(style); |
| 319 } |
326 } |
| 320 } |
327 } |
| 321 |
328 |
| 322 int style_col = col->data_column; |
329 int style_col = datacolumn; |
| 323 if(type == UI_ICON_TEXT || type == UI_ICON_TEXT_FREE) { |
330 if(type == UI_ICON_TEXT || type == UI_ICON_TEXT_FREE) { |
| 324 style_col++; // col->data_column is the icon, we need the next col for the label |
331 style_col++; // col->data_column is the icon, we need the next col for the label |
| 325 } |
332 } |
| 326 |
333 |
| 327 // get the column style |
334 // get the column style |
| 361 } |
368 } |
| 362 case UI_ICON_TEXT: { |
369 case UI_ICON_TEXT: { |
| 363 |
370 |
| 364 } |
371 } |
| 365 case UI_ICON_TEXT_FREE: { |
372 case UI_ICON_TEXT_FREE: { |
| 366 void *data2 = listview->getvalue(list, obj->data, obj->i, col->data_column+1, listview->getvaluedata, &freevalue); |
373 void *data2 = listview->getvalue(list, obj->data, obj->i, datacolumn+1, listview->getvaluedata, &freevalue); |
| 367 if(type == UI_ICON_TEXT_FREE) { |
374 if(type == UI_ICON_TEXT_FREE) { |
| 368 freevalue = TRUE; |
375 freevalue = TRUE; |
| 369 } |
376 } |
| 370 GtkWidget *image = g_object_get_data(G_OBJECT(child), "image"); |
377 GtkWidget *image = g_object_get_data(G_OBJECT(child), "image"); |
| 371 GtkWidget *label = g_object_get_data(G_OBJECT(child), "label"); |
378 GtkWidget *label = g_object_get_data(G_OBJECT(child), "label"); |
| 385 case UI_STRING_EDITABLE: { |
392 case UI_STRING_EDITABLE: { |
| 386 UiCellEntry *entry = g_object_get_data(G_OBJECT(child), "ui_entry_data"); |
393 UiCellEntry *entry = g_object_get_data(G_OBJECT(child), "ui_entry_data"); |
| 387 if(entry) { |
394 if(entry) { |
| 388 entry->listview = col->listview; |
395 entry->listview = col->listview; |
| 389 entry->row = obj->i; |
396 entry->row = obj->i; |
| 390 entry->col = col->data_column; |
397 entry->col = datacolumn; |
| 391 entry->previous_value = strdup(data); |
398 entry->previous_value = strdup(data); |
| 392 } |
399 } |
| 393 ENTRY_SET_TEXT(child, data); |
400 ENTRY_SET_TEXT(child, data); |
| 394 break; |
401 break; |
| 395 } |
402 } |
| 403 if(attributes != listview->current_row_attributes) { |
410 if(attributes != listview->current_row_attributes) { |
| 404 pango_attr_list_unref(attributes); |
411 pango_attr_list_unref(attributes); |
| 405 } |
412 } |
| 406 } |
413 } |
| 407 |
414 |
| 408 static void column_factory_unbind(GtkSignalListItemFactory *self, GtkListItem *item, UiColData *col) { |
415 static void column_factory_unbind(GtkSignalListItemFactory *self, GtkListItem *item, UiColData *col) { |
| 409 ObjWrapper *obj = gtk_list_item_get_item(item); |
416 ObjWrapper *obj = gtk_list_item_get_item(item); |
| 410 UiListView *listview = col->listview; |
417 UiListView *listview = col->listview; |
| 411 CxHashKey row_key = cx_hash_key(&obj->i, sizeof(int)); |
418 CxHashKey row_key = cx_hash_key(&obj->i, sizeof(int)); |
| 412 UiRowItems *row = cxMapGet(listview->bound_rows, row_key); |
419 UiRowItems *row = cxMapGet(listview->bound_rows, row_key); |
| 413 if(row) { |
420 if(row) { |
| 414 row->items[col->model_column] = NULL; |
421 row->items[col->column] = NULL; |
| 415 row->bound--; |
422 row->bound--; |
| 416 if(row->bound == 0) { |
423 if(row->bound == 0) { |
| 417 cxMapRemove(listview->bound_rows, row_key); |
424 cxMapRemove(listview->bound_rows, row_key); |
| 418 } |
425 } |
| 419 } // else: should not happen |
426 } // else: should not happen |
| 455 if(!args->getvalue && !args->getvalue2) { |
462 if(!args->getvalue && !args->getvalue2) { |
| 456 listview->getvalue = str_getvalue; |
463 listview->getvalue = str_getvalue; |
| 457 } |
464 } |
| 458 |
465 |
| 459 listview->numcolumns = 1; |
466 listview->numcolumns = 1; |
| 460 listview->columns = malloc(sizeof(UiColData)); |
467 listview->columns = malloc(sizeof(int)); |
| 461 listview->columns->listview = listview; |
468 listview->columns[0] = 0; |
| 462 listview->columns->data_column = 0; |
|
| 463 listview->columns->model_column = 0; |
|
| 464 |
469 |
| 465 listview->bound_rows = cxHashMapCreate(NULL, CX_STORE_POINTERS, 128); |
470 listview->bound_rows = cxHashMapCreate(NULL, CX_STORE_POINTERS, 128); |
| 466 listview->bound_rows->collection.simple_destructor = (cx_destructor_func)free; |
471 listview->bound_rows->collection.simple_destructor = (cx_destructor_func)free; |
| 467 |
472 |
| 468 GtkListItemFactory *factory = gtk_signal_list_item_factory_new(); |
473 GtkListItemFactory *factory = gtk_signal_list_item_factory_new(); |
| 469 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), listview->columns); |
474 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), &listview->coldata); |
| 470 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), listview->columns); |
475 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), &listview->coldata); |
| |
476 g_signal_connect(factory, "unbind", G_CALLBACK(column_factory_unbind), &listview->coldata); |
| 471 |
477 |
| 472 GtkSelectionModel *selection_model = create_selection_model(listview, ls, args->multiselection); |
478 GtkSelectionModel *selection_model = create_selection_model(listview, ls, args->multiselection); |
| 473 GtkWidget *view = gtk_list_view_new(GTK_SELECTION_MODEL(selection_model), factory); |
479 GtkWidget *view = gtk_list_view_new(GTK_SELECTION_MODEL(selection_model), factory); |
| 474 |
480 |
| 475 UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST); |
481 UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->list, args->varname, UI_VAR_LIST); |
| 538 ct->add(ct, scroll_area, &layout); |
544 ct->add(ct, scroll_area, &layout); |
| 539 |
545 |
| 540 return scroll_area; |
546 return scroll_area; |
| 541 } |
547 } |
| 542 |
548 |
| 543 UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs *args) { |
549 UIWIDGET ui_dropdown_create(UiObject *obj, UiListArgs *args) { |
| 544 // to simplify things and share code with ui_tableview_create, we also |
550 // to simplify things and share code with ui_tableview_create, we also |
| 545 // use a UiModel for the listview |
551 // use a UiModel for the listview |
| 546 UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1); |
552 UiModel *model = ui_model(obj->ctx, UI_STRING, "", -1); |
| 547 args->model = model; |
553 args->model = model; |
| 548 |
554 |
| 552 if(!args->getvalue && !args->getvalue2) { |
558 if(!args->getvalue && !args->getvalue2) { |
| 553 listview->getvalue = str_getvalue; |
559 listview->getvalue = str_getvalue; |
| 554 } |
560 } |
| 555 |
561 |
| 556 listview->numcolumns = 1; |
562 listview->numcolumns = 1; |
| 557 listview->columns = malloc(sizeof(UiColData)); |
563 listview->columns = malloc(sizeof(int)); |
| 558 listview->columns->listview = listview; |
564 listview->columns[0] = 0; |
| 559 listview->columns->data_column = 0; |
|
| 560 listview->columns->model_column = 0; |
|
| 561 |
565 |
| 562 listview->bound_rows = cxHashMapCreate(NULL, CX_STORE_POINTERS, 128); |
566 listview->bound_rows = cxHashMapCreate(NULL, CX_STORE_POINTERS, 128); |
| 563 listview->bound_rows->collection.simple_destructor = (cx_destructor_func)free; |
567 listview->bound_rows->collection.simple_destructor = (cx_destructor_func)free; |
| 564 |
568 |
| 565 GtkListItemFactory *factory = gtk_signal_list_item_factory_new(); |
569 GtkListItemFactory *factory = gtk_signal_list_item_factory_new(); |
| 566 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), listview->columns); |
570 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), &listview->coldata); |
| 567 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), listview->columns); |
571 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), &listview->coldata); |
| 568 |
572 |
| 569 GtkWidget *view = gtk_drop_down_new(G_LIST_MODEL(ls), NULL); |
573 GtkWidget *view = gtk_drop_down_new(G_LIST_MODEL(ls), NULL); |
| 570 gtk_drop_down_set_factory(GTK_DROP_DOWN(view), factory); |
574 gtk_drop_down_set_factory(GTK_DROP_DOWN(view), factory); |
| 571 if(args->width > 0) { |
575 if(args->width > 0) { |
| 572 gtk_widget_set_size_request(view, args->width, -1); |
576 gtk_widget_set_size_request(view, args->width, -1); |
| 589 if(var && var->value) { |
593 if(var && var->value) { |
| 590 UiList *list = var->value; |
594 UiList *list = var->value; |
| 591 |
595 |
| 592 list->obj = listview; |
596 list->obj = listview; |
| 593 list->update = ui_listview_update2; |
597 list->update = ui_listview_update2; |
| 594 list->getselection = ui_combobox_getselection; |
598 list->getselection = ui_dropdown_getselection; |
| 595 list->setselection = ui_combobox_setselection; |
599 list->setselection = ui_dropdown_setselection; |
| 596 |
600 |
| 597 ui_update_liststore(ls, list); |
601 ui_update_liststore(ls, list); |
| 598 } else if (args->static_elements && args->static_nelm > 0) { |
602 } else if (args->static_elements && args->static_nelm > 0) { |
| 599 listview_copy_static_elements(listview, args->static_elements, args->static_nelm); |
603 listview_copy_static_elements(listview, args->static_elements, args->static_nelm); |
| 600 listview->getvalue = str_getvalue; // force string values |
604 listview->getvalue = str_getvalue; // force string values |
| 617 void ui_listview_select(UIWIDGET listview, int index) { |
621 void ui_listview_select(UIWIDGET listview, int index) { |
| 618 GtkSelectionModel *model = gtk_list_view_get_model(GTK_LIST_VIEW(listview)); |
622 GtkSelectionModel *model = gtk_list_view_get_model(GTK_LIST_VIEW(listview)); |
| 619 gtk_selection_model_select_item(model, index, TRUE); |
623 gtk_selection_model_select_item(model, index, TRUE); |
| 620 } |
624 } |
| 621 |
625 |
| 622 void ui_combobox_select(UIWIDGET dropdown, int index) { |
626 void ui_dropdown_select(UIWIDGET dropdown, int index) { |
| 623 gtk_drop_down_set_selected(GTK_DROP_DOWN(dropdown), index); |
627 gtk_drop_down_set_selected(GTK_DROP_DOWN(dropdown), index); |
| |
628 } |
| |
629 |
| |
630 static void add_column(UiListView *tableview, int index) { |
| |
631 UiModel *model = tableview->model; |
| |
632 |
| |
633 UiColData *col = malloc(sizeof(UiColData)); |
| |
634 col->listview = tableview; |
| |
635 col->column = index; |
| |
636 |
| |
637 GtkListItemFactory *factory = gtk_signal_list_item_factory_new(); |
| |
638 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), col); |
| |
639 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), col); |
| |
640 g_object_set_data_full(G_OBJECT(factory), "coldata", col, (GDestroyNotify)free); |
| |
641 |
| |
642 GtkColumnViewColumn *column = gtk_column_view_column_new(model->titles[index], factory); |
| |
643 gtk_column_view_column_set_resizable(column, true); |
| |
644 gtk_column_view_insert_column(GTK_COLUMN_VIEW(tableview->widget), index, column); |
| |
645 |
| |
646 int size = model->columnsize[index]; |
| |
647 if(size > 0) { |
| |
648 gtk_column_view_column_set_fixed_width(column, size); |
| |
649 } else if(size < 0) { |
| |
650 gtk_column_view_column_set_expand(column, TRUE); |
| |
651 } |
| 624 } |
652 } |
| 625 |
653 |
| 626 UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) { |
654 UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) { |
| 627 GListStore *ls = g_list_store_new(G_TYPE_OBJECT); |
655 GListStore *ls = g_list_store_new(G_TYPE_OBJECT); |
| 628 //g_list_store_append(ls, v1); |
656 //g_list_store_append(ls, v1); |
| 648 tableview); |
676 tableview); |
| 649 |
677 |
| 650 |
678 |
| 651 // create columns from UiModel |
679 // create columns from UiModel |
| 652 UiModel *model = args->model; |
680 UiModel *model = args->model; |
| 653 int columns = model ? model->columns : 0; |
681 int columns = 0; |
| 654 |
682 if(model) { |
| 655 tableview->columns = calloc(columns, sizeof(UiColData)); |
683 columns = model->columns; |
| |
684 ui_model_add_observer(model, ui_listview_update_model, tableview); |
| |
685 } |
| |
686 |
| |
687 tableview->columns = calloc(columns, sizeof(int)); |
| 656 tableview->numcolumns = columns; |
688 tableview->numcolumns = columns; |
| 657 |
689 |
| 658 tableview->bound_rows = cxHashMapCreate(NULL, CX_STORE_POINTERS, 128); |
690 tableview->bound_rows = cxHashMapCreate(NULL, CX_STORE_POINTERS, 128); |
| 659 tableview->bound_rows->collection.simple_destructor = (cx_destructor_func)free; |
691 tableview->bound_rows->collection.simple_destructor = (cx_destructor_func)free; |
| 660 |
692 |
| 661 int addi = 0; |
693 int addi = 0; |
| 662 for(int i=0;i<columns;i++) { |
694 for(int i=0;i<columns;i++) { |
| 663 tableview->columns[i].listview = tableview; |
695 tableview->columns[i] = i+addi; |
| 664 tableview->columns[i].model_column = i; |
|
| 665 tableview->columns[i].data_column = i+addi; |
|
| 666 |
696 |
| 667 if(model->types[i] == UI_ICON_TEXT || model->types[i] == UI_ICON_TEXT_FREE) { |
697 if(model->types[i] == UI_ICON_TEXT || model->types[i] == UI_ICON_TEXT_FREE) { |
| 668 // icon+text has 2 data columns |
698 // icon+text has 2 data columns |
| 669 addi++; |
699 addi++; |
| 670 } |
700 } |
| 671 |
701 |
| 672 GtkListItemFactory *factory = gtk_signal_list_item_factory_new(); |
702 add_column(tableview, i); |
| 673 UiColData *col = &tableview->columns[i]; |
|
| 674 g_signal_connect(factory, "setup", G_CALLBACK(column_factory_setup), col); |
|
| 675 g_signal_connect(factory, "bind", G_CALLBACK(column_factory_bind), col); |
|
| 676 |
|
| 677 GtkColumnViewColumn *column = gtk_column_view_column_new(model->titles[i], factory); |
|
| 678 gtk_column_view_column_set_resizable(column, true); |
|
| 679 gtk_column_view_append_column(GTK_COLUMN_VIEW(view), column); |
|
| 680 |
|
| 681 int size = model->columnsize[i]; |
|
| 682 if(size > 0) { |
|
| 683 gtk_column_view_column_set_fixed_width(column, size); |
|
| 684 } else if(size < 0) { |
|
| 685 gtk_column_view_column_set_expand(column, TRUE); |
|
| 686 } |
|
| 687 } |
703 } |
| 688 |
704 |
| 689 // bind listview to list |
705 // bind listview to list |
| 690 if(var && var->value) { |
706 if(var && var->value) { |
| 691 UiList *list = var->value; |
707 UiList *list = var->value; |
| 730 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end; |
746 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end; |
| 731 UiLayout layout = UI_ARGS2LAYOUT(args); |
747 UiLayout layout = UI_ARGS2LAYOUT(args); |
| 732 ct->add(ct, scroll_area, &layout); |
748 ct->add(ct, scroll_area, &layout); |
| 733 |
749 |
| 734 return scroll_area; |
750 return scroll_area; |
| |
751 } |
| |
752 |
| |
753 void ui_listview_update_model(UiModel *model, void *userdata, int insert_index, int delete_index) { |
| |
754 UiListView *listview = userdata; |
| |
755 if(insert_index >= listview->numcolumns) { |
| |
756 listview->numcolumns = insert_index+1; |
| |
757 listview->columns = realloc(listview->columns, listview->numcolumns * sizeof(UiColData)); |
| |
758 } |
| |
759 |
| |
760 gtk_column_view_set_model(GTK_COLUMN_VIEW(listview->widget), NULL); |
| |
761 cxMapClear(listview->bound_rows); |
| |
762 |
| |
763 if(insert_index) { |
| |
764 int prev = 0; |
| |
765 if(insert_index > 0) { |
| |
766 prev = listview->columns[insert_index-1]; |
| |
767 } |
| |
768 listview->columns[insert_index] = prev+1; |
| |
769 add_column(listview, insert_index); |
| |
770 |
| |
771 if(insert_index+1 < listview->numcolumns) { |
| |
772 // the data index of trailing columns must be adjusted |
| |
773 UiModelType type = model->types[insert_index]; |
| |
774 int add = 1; |
| |
775 if(type == UI_ICON_TEXT || type == UI_ICON_TEXT_FREE) { |
| |
776 add++; |
| |
777 } |
| |
778 for(int i=insert_index+1;i<listview->numcolumns;i++) { |
| |
779 listview->columns[i] += add; |
| |
780 } |
| |
781 } |
| |
782 } // TODO: delete_index |
| |
783 |
| |
784 GListStore *ls = g_list_store_new(G_TYPE_OBJECT); |
| |
785 GtkSelectionModel *selection_model = create_selection_model(listview, ls, listview->multiselection); |
| |
786 gtk_column_view_set_model(GTK_COLUMN_VIEW(listview->widget), selection_model); |
| |
787 listview->selectionmodel = selection_model; |
| |
788 listview->liststore = ls; |
| |
789 |
| |
790 if(listview->var) { |
| |
791 UiList *list = listview->var->value; |
| |
792 ui_list_update(list); |
| |
793 } |
| 735 } |
794 } |
| 736 |
795 |
| 737 static UiListSelection selectionmodel_get_selection(GtkSelectionModel *model) { |
796 static UiListSelection selectionmodel_get_selection(GtkSelectionModel *model) { |
| 738 UiListSelection sel = { 0, NULL }; |
797 UiListSelection sel = { 0, NULL }; |
| 739 GtkBitset *bitset = gtk_selection_model_get_selection(model); |
798 GtkBitset *bitset = gtk_selection_model_get_selection(model); |
| 858 } |
917 } |
| 859 } |
918 } |
| 860 |
919 |
| 861 void ui_listview_update2(UiList *list, int i) { |
920 void ui_listview_update2(UiList *list, int i) { |
| 862 UiListView *view = list->obj; |
921 UiListView *view = list->obj; |
| |
922 view->current_row = -1; |
| 863 if(i < 0) { |
923 if(i < 0) { |
| |
924 cxMapClear(view->bound_rows); |
| 864 ui_update_liststore(view->liststore, list); |
925 ui_update_liststore(view->liststore, list); |
| 865 } else { |
926 } else { |
| 866 void *value = list->get(list, i); |
927 void *value = list->get(list, i); |
| 867 if(value) { |
928 if(value) { |
| 868 ObjWrapper *obj = g_list_model_get_item(G_LIST_MODEL(view->liststore), i); |
929 ObjWrapper *obj = g_list_model_get_item(G_LIST_MODEL(view->liststore), i); |
| 871 } |
932 } |
| 872 |
933 |
| 873 CxHashKey row_key = cx_hash_key(&i, sizeof(int)); |
934 CxHashKey row_key = cx_hash_key(&i, sizeof(int)); |
| 874 UiRowItems *row = cxMapGet(view->bound_rows, row_key); |
935 UiRowItems *row = cxMapGet(view->bound_rows, row_key); |
| 875 if(row) { |
936 if(row) { |
| |
937 UiColData coldata; |
| |
938 coldata.listview = view; |
| 876 for(int c=0;c<view->numcolumns;c++) { |
939 for(int c=0;c<view->numcolumns;c++) { |
| 877 if(row->items[c] != NULL) { |
940 if(row->items[c] != NULL) { |
| 878 column_factory_bind(NULL, row->items[c], &view->columns[c]); |
941 coldata.column = c; |
| |
942 column_factory_bind(NULL, row->items[c], &coldata); |
| 879 } |
943 } |
| 880 } |
944 } |
| 881 } |
945 } |
| 882 } |
946 } |
| 883 } |
947 } |
| 913 } |
977 } |
| 914 } |
978 } |
| 915 ui_setop_enable(FALSE); |
979 ui_setop_enable(FALSE); |
| 916 } |
980 } |
| 917 |
981 |
| 918 UiListSelection ui_combobox_getselection(UiList *list) { |
982 UiListSelection ui_dropdown_getselection(UiList *list) { |
| 919 UiListView *view = list->obj; |
983 UiListView *view = list->obj; |
| 920 guint selection = gtk_drop_down_get_selected(GTK_DROP_DOWN(view->widget)); |
984 guint selection = gtk_drop_down_get_selected(GTK_DROP_DOWN(view->widget)); |
| 921 UiListSelection sel = { 0, NULL }; |
985 UiListSelection sel = { 0, NULL }; |
| 922 if(selection != GTK_INVALID_LIST_POSITION) { |
986 if(selection != GTK_INVALID_LIST_POSITION) { |
| 923 sel.count = 1; |
987 sel.count = 1; |
| 925 sel.rows[0] = (int)selection; |
989 sel.rows[0] = (int)selection; |
| 926 } |
990 } |
| 927 return sel; |
991 return sel; |
| 928 } |
992 } |
| 929 |
993 |
| 930 void ui_combobox_setselection(UiList *list, UiListSelection selection) { |
994 void ui_dropdown_setselection(UiList *list, UiListSelection selection) { |
| 931 ui_setop_enable(TRUE); |
995 ui_setop_enable(TRUE); |
| 932 UiListView *view = list->obj; |
996 UiListView *view = list->obj; |
| 933 if(selection.count > 0) { |
997 if(selection.count > 0) { |
| 934 gtk_drop_down_set_selected(GTK_DROP_DOWN(view->widget), selection.rows[0]); |
998 gtk_drop_down_set_selected(GTK_DROP_DOWN(view->widget), selection.rows[0]); |
| 935 } else { |
999 } else { |
| 1154 |
1218 |
| 1155 UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args) { |
1219 UIWIDGET ui_listview_create(UiObject *obj, UiListArgs *args) { |
| 1156 // create treeview |
1220 // create treeview |
| 1157 GtkWidget *view = gtk_tree_view_new(); |
1221 GtkWidget *view = gtk_tree_view_new(); |
| 1158 ui_set_name_and_style(view, args->name, args->style_class); |
1222 ui_set_name_and_style(view, args->name, args->style_class); |
| 1159 ui_set_widget_groups(obj->ctx, view, args->groups); |
1223 ui_set_widget_states(obj->ctx, view, args->states); |
| 1160 GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); |
1224 GtkCellRenderer *renderer = gtk_cell_renderer_text_new(); |
| 1161 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(NULL, renderer, "text", 0, NULL); |
1225 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(NULL, renderer, "text", 0, NULL); |
| 1162 gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); |
1226 gtk_tree_view_append_column(GTK_TREE_VIEW(view), column); |
| 1163 |
1227 |
| 1164 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); |
1228 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), FALSE); |
| 1270 GtkTreePath *path = gtk_tree_path_new_from_indicesv(&index, 1); |
1334 GtkTreePath *path = gtk_tree_path_new_from_indicesv(&index, 1); |
| 1271 gtk_tree_selection_select_path(sel, path); |
1335 gtk_tree_selection_select_path(sel, path); |
| 1272 //g_object_unref(path); |
1336 //g_object_unref(path); |
| 1273 } |
1337 } |
| 1274 |
1338 |
| 1275 void ui_combobox_select(UIWIDGET dropdown, int index) { |
1339 void ui_dropdown_select(UIWIDGET dropdown, int index) { |
| 1276 gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown), index); |
1340 gtk_combo_box_set_active(GTK_COMBO_BOX(dropdown), index); |
| 1277 } |
1341 } |
| 1278 |
1342 |
| 1279 UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) { |
1343 UIWIDGET ui_table_create(UiObject *obj, UiListArgs *args) { |
| 1280 // create treeview |
1344 // create treeview |
| 1512 ui_setop_enable(FALSE); |
1576 ui_setop_enable(FALSE); |
| 1513 } |
1577 } |
| 1514 |
1578 |
| 1515 |
1579 |
| 1516 |
1580 |
| 1517 /* --------------------------- ComboBox --------------------------- */ |
1581 /* --------------------------- Dropdown --------------------------- */ |
| 1518 |
1582 |
| 1519 UIWIDGET ui_combobox_create(UiObject *obj, UiListArgs *args) { |
1583 UIWIDGET ui_dropdown_create(UiObject *obj, UiListArgs *args) { |
| 1520 GtkWidget *combobox = gtk_combo_box_new(); |
1584 GtkWidget *combobox = gtk_combo_box_new(); |
| 1521 if(args->width > 0) { |
1585 if(args->width > 0) { |
| 1522 gtk_widget_set_size_request(combobox, args->width, -1); |
1586 gtk_widget_set_size_request(combobox, args->width, -1); |
| 1523 } |
1587 } |
| 1524 |
1588 |
| 1525 ui_set_name_and_style(combobox, args->name, args->style_class); |
1589 ui_set_name_and_style(combobox, args->name, args->style_class); |
| 1526 ui_set_widget_groups(obj->ctx, combobox, args->groups); |
1590 ui_set_widget_states(obj->ctx, combobox, args->states); |
| 1527 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end; |
1591 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end; |
| 1528 UiLayout layout = UI_ARGS2LAYOUT(args); |
1592 UiLayout layout = UI_ARGS2LAYOUT(args); |
| 1529 ct->add(ct, combobox, &layout); |
1593 ct->add(ct, combobox, &layout); |
| 1530 |
1594 |
| 1531 UiListView *listview = create_listview(obj, args); |
1595 UiListView *listview = create_listview(obj, args); |
| 1542 UiList *list = var ? var->value : NULL; |
1606 UiList *list = var ? var->value : NULL; |
| 1543 GtkListStore *listmodel = create_list_store(listview, list); |
1607 GtkListStore *listmodel = create_list_store(listview, list); |
| 1544 if(var) { |
1608 if(var) { |
| 1545 listview->var = var; |
1609 listview->var = var; |
| 1546 list->update = ui_combobox_modelupdate; |
1610 list->update = ui_combobox_modelupdate; |
| 1547 list->getselection = ui_combobox_getselection; |
1611 list->getselection = ui_dropdown_getselection; |
| 1548 list->setselection = ui_combobox_setselection; |
1612 list->setselection = ui_dropdown_setselection; |
| 1549 list->obj = listview; |
1613 list->obj = listview; |
| 1550 list->update(list, -1); |
1614 list->update(list, -1); |
| 1551 } else if(args->static_nelm > 0) { |
1615 } else if(args->static_nelm > 0) { |
| 1552 listview_copy_static_elements(listview, args->static_elements, args->static_nelm); |
1616 listview_copy_static_elements(listview, args->static_elements, args->static_nelm); |
| 1553 for(int i=0;i<args->static_nelm;i++) { |
1617 for(int i=0;i<args->static_nelm;i++) { |
| 1620 GtkListStore *store = create_list_store(view, list); |
1684 GtkListStore *store = create_list_store(view, list); |
| 1621 gtk_combo_box_set_model(GTK_COMBO_BOX(view->widget), GTK_TREE_MODEL(store)); |
1685 gtk_combo_box_set_model(GTK_COMBO_BOX(view->widget), GTK_TREE_MODEL(store)); |
| 1622 g_object_unref(store); |
1686 g_object_unref(store); |
| 1623 } |
1687 } |
| 1624 |
1688 |
| 1625 UiListSelection ui_combobox_getselection(UiList *list) { |
1689 UiListSelection ui_dropdown_getselection(UiList *list) { |
| 1626 UiListView *combobox = list->obj; |
1690 UiListView *combobox = list->obj; |
| 1627 UiListSelection ret; |
1691 UiListSelection ret; |
| 1628 ret.rows = malloc(sizeof(int*)); |
1692 ret.rows = malloc(sizeof(int*)); |
| 1629 ret.count = 1; |
1693 ret.count = 1; |
| 1630 ret.rows[0] = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox->widget)); |
1694 ret.rows[0] = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox->widget)); |
| 1631 return ret; |
1695 return ret; |
| 1632 } |
1696 } |
| 1633 |
1697 |
| 1634 void ui_combobox_setselection(UiList *list, UiListSelection selection) { |
1698 void ui_dropdown_setselection(UiList *list, UiListSelection selection) { |
| 1635 ui_setop_enable(TRUE); |
1699 ui_setop_enable(TRUE); |
| 1636 UiListView *combobox = list->obj; |
1700 UiListView *combobox = list->obj; |
| 1637 if(selection.count > 0) { |
1701 if(selection.count > 0) { |
| 1638 gtk_combo_box_set_active(GTK_COMBO_BOX(combobox->widget), selection.rows[0]); |
1702 gtk_combo_box_set_active(GTK_COMBO_BOX(combobox->widget), selection.rows[0]); |
| 1639 } |
1703 } |
| 2043 void ui_listview_destroy(GtkWidget *w, UiListView *v) { |
2107 void ui_listview_destroy(GtkWidget *w, UiListView *v) { |
| 2044 //gtk_tree_view_set_model(GTK_TREE_VIEW(w), NULL); |
2108 //gtk_tree_view_set_model(GTK_TREE_VIEW(w), NULL); |
| 2045 if(v->var) { |
2109 if(v->var) { |
| 2046 ui_destroy_boundvar(v->obj->ctx, v->var); |
2110 ui_destroy_boundvar(v->obj->ctx, v->var); |
| 2047 } |
2111 } |
| |
2112 if(v->model) { |
| |
2113 ui_model_remove_observer(v->model, v); |
| |
2114 ui_model_unref(v->model); |
| |
2115 } |
| 2048 if(v->elements) { |
2116 if(v->elements) { |
| 2049 for(int i=0;i<v->nelm;i++) { |
2117 for(int i=0;i<v->nelm;i++) { |
| 2050 free(v->elements[i]); |
2118 free(v->elements[i]); |
| 2051 } |
2119 } |
| 2052 free(v->elements); |
2120 free(v->elements); |
| 2158 UiListBoxSubList *sublist_ptr = cxListAt(uilistbox->sublists, cxListSize(sublists)-1); |
2226 UiListBoxSubList *sublist_ptr = cxListAt(uilistbox->sublists, cxListSize(sublists)-1); |
| 2159 if(uisublist.var && uisublist.var->value) { |
2227 if(uisublist.var && uisublist.var->value) { |
| 2160 UiList *list = uisublist.var->value; |
2228 UiList *list = uisublist.var->value; |
| 2161 list->obj = sublist_ptr; |
2229 list->obj = sublist_ptr; |
| 2162 list->update = ui_listbox_list_update; |
2230 list->update = ui_listbox_list_update; |
| |
2231 list->getselection = ui_listbox_list_getselection; |
| |
2232 list->setselection = ui_listbox_list_setselection; |
| 2163 } |
2233 } |
| 2164 } |
2234 } |
| 2165 |
2235 |
| 2166 UIEXPORT UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs *args) { |
2236 UIEXPORT UIWIDGET ui_sourcelist_create(UiObject *obj, UiSourceListArgs *args) { |
| 2167 #ifdef UI_GTK3 |
2237 #ifdef UI_GTK3 |
| 2179 gtk_list_box_set_header_func(GTK_LIST_BOX(listbox), listbox_create_header, NULL, NULL); |
2249 gtk_list_box_set_header_func(GTK_LIST_BOX(listbox), listbox_create_header, NULL, NULL); |
| 2180 GtkWidget *scroll_area = SCROLLEDWINDOW_NEW(); |
2250 GtkWidget *scroll_area = SCROLLEDWINDOW_NEW(); |
| 2181 SCROLLEDWINDOW_SET_CHILD(scroll_area, listbox); |
2251 SCROLLEDWINDOW_SET_CHILD(scroll_area, listbox); |
| 2182 |
2252 |
| 2183 ui_set_name_and_style(listbox, args->name, args->style_class); |
2253 ui_set_name_and_style(listbox, args->name, args->style_class); |
| 2184 ui_set_widget_groups(obj->ctx, listbox, args->groups); |
2254 ui_set_widget_states(obj->ctx, listbox, args->states); |
| 2185 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end; |
2255 UiContainerPrivate *ct = (UiContainerPrivate*)obj->container_end; |
| 2186 UiLayout layout = UI_ARGS2LAYOUT(args); |
2256 UiLayout layout = UI_ARGS2LAYOUT(args); |
| 2187 ct->add(ct, scroll_area, &layout); |
2257 ct->add(ct, scroll_area, &layout); |
| 2188 |
2258 |
| 2189 UiListBox *uilistbox = malloc(sizeof(UiListBox)); |
2259 UiListBox *uilistbox = malloc(sizeof(UiListBox)); |
| 2221 UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->dynamic_sublist, args->varname, UI_VAR_LIST); |
2291 UiVar* var = uic_widget_var(obj->ctx, obj->ctx, args->dynamic_sublist, args->varname, UI_VAR_LIST); |
| 2222 if(var) { |
2292 if(var) { |
| 2223 UiList *list = var->value; |
2293 UiList *list = var->value; |
| 2224 list->obj = uilistbox; |
2294 list->obj = uilistbox; |
| 2225 list->update = ui_listbox_dynamic_update; |
2295 list->update = ui_listbox_dynamic_update; |
| |
2296 list->getselection = ui_listbox_dynamic_getselection; |
| |
2297 list->setselection = ui_listbox_dynamic_setselection; |
| 2226 |
2298 |
| 2227 ui_listbox_dynamic_update(list, -1); |
2299 ui_listbox_dynamic_update(list, -1); |
| 2228 } |
2300 } |
| 2229 } |
2301 } |
| 2230 |
2302 |
| 2290 add_sublist(uilistbox, new_sublists, sublist); |
2362 add_sublist(uilistbox, new_sublists, sublist); |
| 2291 sublist = list->next(list); |
2363 sublist = list->next(list); |
| 2292 } |
2364 } |
| 2293 |
2365 |
| 2294 ui_listbox_update(uilistbox, 0, cxListSize(uilistbox->sublists)); |
2366 ui_listbox_update(uilistbox, 0, cxListSize(uilistbox->sublists)); |
| |
2367 } |
| |
2368 |
| |
2369 void ui_listbox_dynamic_setselection(UiList *list, UiListSelection sel) { |
| |
2370 UiListBox *uilistbox = list->obj; |
| |
2371 gtk_list_box_unselect_all(uilistbox->listbox); |
| |
2372 if(sel.count > 0) { |
| |
2373 int index = sel.rows[0]; |
| |
2374 if(index >= 0) { |
| |
2375 GtkListBoxRow *row = gtk_list_box_get_row_at_index(uilistbox->listbox, index); |
| |
2376 if(row) { |
| |
2377 gtk_list_box_select_row(uilistbox->listbox, row); |
| |
2378 } |
| |
2379 } |
| |
2380 } |
| |
2381 } |
| |
2382 |
| |
2383 UiListSelection ui_listbox_dynamic_getselection(UiList *list) { |
| |
2384 UiListSelection sel = { 0, NULL }; |
| |
2385 UiListBox *uilistbox = list->obj; |
| |
2386 GtkListBoxRow *row = gtk_list_box_get_selected_row(uilistbox->listbox); |
| |
2387 if(row) { |
| |
2388 sel.count = 1; |
| |
2389 sel.rows = malloc(sizeof(int)); |
| |
2390 sel.rows[0] = gtk_list_box_row_get_index(row); |
| |
2391 } |
| |
2392 return sel; |
| 2295 } |
2393 } |
| 2296 |
2394 |
| 2297 void ui_listbox_update(UiListBox *listbox, int from, int to) { |
2395 void ui_listbox_update(UiListBox *listbox, int from, int to) { |
| 2298 CxIterator i = cxListIterator(listbox->sublists); |
2396 CxIterator i = cxListIterator(listbox->sublists); |
| 2299 size_t pos = 0; |
2397 size_t pos = 0; |
| 2657 } |
2755 } |
| 2658 |
2756 |
| 2659 ui_sourcelist_update_finished(); |
2757 ui_sourcelist_update_finished(); |
| 2660 } |
2758 } |
| 2661 |
2759 |
| |
2760 void ui_listbox_list_setselection(UiList *list, UiListSelection sel) { |
| |
2761 UiListBoxSubList *sublist = list->obj; |
| |
2762 UiListBox *uilistbox = sublist->listbox; |
| |
2763 gtk_list_box_unselect_all(uilistbox->listbox); |
| |
2764 if(sel.count > 0) { |
| |
2765 int index = sel.rows[0]; |
| |
2766 if(index >= 0 && index < sublist->numitems) { |
| |
2767 int global_index = sublist->startpos + index; |
| |
2768 GtkListBoxRow *row = gtk_list_box_get_row_at_index(uilistbox->listbox, global_index); |
| |
2769 if(row) { |
| |
2770 gtk_list_box_select_row(uilistbox->listbox, row); |
| |
2771 } |
| |
2772 } |
| |
2773 } |
| |
2774 } |
| |
2775 |
| |
2776 UiListSelection ui_listbox_list_getselection(UiList *list) { |
| |
2777 UiListSelection sel = { 0, NULL }; |
| |
2778 UiListBoxSubList *sublist = list->obj; |
| |
2779 UiListBox *uilistbox = sublist->listbox; |
| |
2780 GtkListBoxRow *row = gtk_list_box_get_selected_row(uilistbox->listbox); |
| |
2781 if(row) { |
| |
2782 int index = gtk_list_box_row_get_index(row); |
| |
2783 size_t startpos = sublist->startpos; |
| |
2784 if(index >= startpos && index < startpos+sublist->numitems) { |
| |
2785 sel.count = 1; |
| |
2786 sel.rows = malloc(sizeof(int)); |
| |
2787 sel.rows[0] = index - startpos; |
| |
2788 } |
| |
2789 } |
| |
2790 return sel; |
| |
2791 } |
| |
2792 |
| 2662 void ui_listbox_row_activate(GtkListBox *self, GtkListBoxRow *row, gpointer user_data) { |
2793 void ui_listbox_row_activate(GtkListBox *self, GtkListBoxRow *row, gpointer user_data) { |
| 2663 UiEventDataExt *data = g_object_get_data(G_OBJECT(row), "ui-listbox-row-eventdata"); |
2794 UiEventDataExt *data = g_object_get_data(G_OBJECT(row), "ui-listbox-row-eventdata"); |
| 2664 if(!data) { |
2795 if(!data) { |
| 2665 return; |
2796 return; |
| 2666 } |
2797 } |