429 // to add a context menu |
445 // to add a context menu |
430 current->container->current = view; |
446 current->container->current = view; |
431 |
447 |
432 return scroll_area; |
448 return scroll_area; |
433 } |
449 } |
|
450 |
|
451 #if GTK_MAJOR_VERSION >= 4 |
|
452 |
|
453 static GdkContentProvider *ui_listview_dnd_prepare(GtkDragSource *source, double x, double y, void *data) { |
|
454 //printf("drag prepare\n"); |
|
455 UiListView *listview = data; |
|
456 |
|
457 UiDnD *dnd = ui_create_dnd(); |
|
458 GdkContentProvider *provider = NULL; |
|
459 |
|
460 |
|
461 if(listview->ondragstart) { |
|
462 UiEvent event; |
|
463 event.obj = listview->obj; |
|
464 event.window = event.obj->window; |
|
465 event.document = event.obj->ctx->document; |
|
466 event.eventdata = dnd; |
|
467 event.intval = 0; |
|
468 listview->ondragstart(&event, listview->ondragstartdata); |
|
469 } |
|
470 |
|
471 size_t numproviders = cxListSize(dnd->providers); |
|
472 if(numproviders > 0) { |
|
473 GdkContentProvider **providers = (GdkContentProvider**)cxListAt(dnd->providers, 0); |
|
474 provider = gdk_content_provider_new_union(providers, numproviders); |
|
475 } |
|
476 ui_dnd_free(dnd); |
|
477 |
|
478 return provider; |
|
479 } |
|
480 |
|
481 static void ui_listview_drag_begin(GtkDragSource *self, GdkDrag *drag, gpointer userdata) { |
|
482 //printf("drag begin\n"); |
|
483 } |
|
484 |
|
485 static void ui_listview_drag_end(GtkDragSource *self, GdkDrag *drag, gboolean delete_data, gpointer user_data) { |
|
486 //printf("drag end\n"); |
|
487 UiListView *listview = user_data; |
|
488 if(listview->ondragcomplete) { |
|
489 UiDnD dnd; |
|
490 dnd.target = NULL; |
|
491 dnd.value = NULL; |
|
492 dnd.providers = NULL; |
|
493 dnd.selected_action = gdk_drag_get_selected_action(drag); |
|
494 dnd.delete = delete_data; |
|
495 dnd.accept = FALSE; |
|
496 |
|
497 UiEvent event; |
|
498 event.obj = listview->obj; |
|
499 event.window = event.obj->window; |
|
500 event.document = event.obj->ctx->document; |
|
501 event.eventdata = &dnd; |
|
502 event.intval = 0; |
|
503 listview->ondragcomplete(&event, listview->ondragcompletedata); |
|
504 } |
|
505 } |
|
506 |
|
507 static gboolean ui_listview_drop( |
|
508 GtkDropTarget *target, |
|
509 const GValue* value, |
|
510 gdouble x, |
|
511 gdouble y, |
|
512 gpointer user_data) |
|
513 { |
|
514 UiListView *listview = user_data; |
|
515 UiDnD dnd; |
|
516 dnd.providers = NULL; |
|
517 dnd.target = target; |
|
518 dnd.value = value; |
|
519 dnd.selected_action = 0; |
|
520 dnd.delete = FALSE; |
|
521 dnd.accept = FALSE; |
|
522 |
|
523 if(listview->ondrop) { |
|
524 dnd.accept = TRUE; |
|
525 UiEvent event; |
|
526 event.obj = listview->obj; |
|
527 event.window = event.obj->window; |
|
528 event.document = event.obj->ctx->document; |
|
529 event.eventdata = &dnd; |
|
530 event.intval = 0; |
|
531 listview->ondrop(&event, listview->ondropdata); |
|
532 } |
|
533 |
|
534 return dnd.accept; |
|
535 } |
|
536 |
|
537 void ui_listview_add_dnd(UiListView *listview, UiListArgs *args) { |
|
538 GtkDragSource *dragsource = gtk_drag_source_new(); |
|
539 gtk_widget_add_controller(listview->widget, GTK_EVENT_CONTROLLER(dragsource)); |
|
540 g_signal_connect (dragsource, "prepare", G_CALLBACK (ui_listview_dnd_prepare), listview); |
|
541 g_signal_connect( |
|
542 dragsource, |
|
543 "drag-begin", |
|
544 G_CALLBACK(ui_listview_drag_begin), |
|
545 listview); |
|
546 g_signal_connect( |
|
547 dragsource, |
|
548 "drag-end", |
|
549 G_CALLBACK(ui_listview_drag_end), |
|
550 listview); |
|
551 } |
|
552 |
|
553 void ui_listview_enable_drop(UiListView *listview, UiListArgs *args) { |
|
554 GtkDropTarget *target = gtk_drop_target_new(G_TYPE_INVALID, GDK_ACTION_COPY); |
|
555 gtk_widget_add_controller(listview->widget, GTK_EVENT_CONTROLLER(target)); |
|
556 GType default_types[2] = { GDK_TYPE_FILE_LIST, G_TYPE_STRING }; |
|
557 gtk_drop_target_set_gtypes(target, default_types, 2); |
|
558 g_signal_connect(target, "drop", G_CALLBACK(ui_listview_drop), listview); |
|
559 } |
|
560 |
|
561 #else |
|
562 |
|
563 static GtkTargetEntry targetentries[] = |
|
564 { |
|
565 { "STRING", 0, 0 }, |
|
566 { "text/plain", 0, 1 }, |
|
567 { "text/uri-list", 0, 2 }, |
|
568 }; |
|
569 |
|
570 static void ui_listview_drag_getdata( |
|
571 GtkWidget* self, |
|
572 GdkDragContext* context, |
|
573 GtkSelectionData* data, |
|
574 guint info, |
|
575 guint time, |
|
576 gpointer user_data) |
|
577 { |
|
578 UiListView *listview = user_data; |
|
579 UiDnD dnd; |
|
580 dnd.context = context; |
|
581 dnd.data = data; |
|
582 dnd.selected_action = 0; |
|
583 dnd.delete = FALSE; |
|
584 dnd.accept = FALSE; |
|
585 |
|
586 if(listview->ondragstart) { |
|
587 UiEvent event; |
|
588 event.obj = listview->obj; |
|
589 event.window = event.obj->window; |
|
590 event.document = event.obj->ctx->document; |
|
591 event.eventdata = &dnd; |
|
592 event.intval = 0; |
|
593 listview->ondragstart(&event, listview->ondragstartdata); |
|
594 } |
|
595 } |
|
596 |
|
597 static void ui_listview_drag_end( |
|
598 GtkWidget *widget, |
|
599 GdkDragContext *context, |
|
600 guint time, |
|
601 gpointer user_data) |
|
602 { |
|
603 UiListView *listview = user_data; |
|
604 UiDnD dnd; |
|
605 dnd.context = context; |
|
606 dnd.data = NULL; |
|
607 dnd.selected_action = gdk_drag_context_get_selected_action(context); |
|
608 dnd.delete = dnd.selected_action == UI_DND_ACTION_MOVE ? TRUE : FALSE; |
|
609 dnd.accept = FALSE; |
|
610 if(listview->ondragcomplete) { |
|
611 UiEvent event; |
|
612 event.obj = listview->obj; |
|
613 event.window = event.obj->window; |
|
614 event.document = event.obj->ctx->document; |
|
615 event.eventdata = &dnd; |
|
616 event.intval = 0; |
|
617 listview->ondragcomplete(&event, listview->ondragcompletedata); |
|
618 } |
|
619 } |
|
620 |
|
621 void ui_listview_add_dnd(UiListView *listview, UiListArgs *args) { |
|
622 gtk_tree_view_enable_model_drag_source( |
|
623 GTK_TREE_VIEW(listview->widget), |
|
624 GDK_BUTTON1_MASK, |
|
625 targetentries, |
|
626 2, |
|
627 GDK_ACTION_COPY); |
|
628 |
|
629 g_signal_connect(listview->widget, "drag-data-get", G_CALLBACK(ui_listview_drag_getdata), listview); |
|
630 g_signal_connect(listview->widget, "drag-end", G_CALLBACK(ui_listview_drag_end), listview); |
|
631 } |
|
632 |
|
633 |
|
634 |
|
635 |
|
636 static void ui_listview_drag_data_received( |
|
637 GtkWidget *self, |
|
638 GdkDragContext *context, |
|
639 gint x, |
|
640 gint y, |
|
641 GtkSelectionData *data, |
|
642 guint info, |
|
643 guint time, |
|
644 gpointer user_data) |
|
645 { |
|
646 UiListView *listview = user_data; |
|
647 UiDnD dnd; |
|
648 dnd.context = context; |
|
649 dnd.data = data; |
|
650 dnd.selected_action = 0; |
|
651 dnd.delete = FALSE; |
|
652 dnd.accept = FALSE; |
|
653 |
|
654 if(listview->ondrop) { |
|
655 dnd.accept = TRUE; |
|
656 UiEvent event; |
|
657 event.obj = listview->obj; |
|
658 event.window = event.obj->window; |
|
659 event.document = event.obj->ctx->document; |
|
660 event.eventdata = &dnd; |
|
661 event.intval = 0; |
|
662 listview->ondrop(&event, listview->ondropdata); |
|
663 } |
|
664 } |
|
665 |
|
666 void ui_listview_enable_drop(UiListView *listview, UiListArgs *args) { |
|
667 gtk_tree_view_enable_model_drag_dest( |
|
668 GTK_TREE_VIEW(listview->widget), |
|
669 targetentries, |
|
670 3, |
|
671 GDK_ACTION_COPY); |
|
672 if(listview->ondrop) { |
|
673 g_signal_connect(listview->widget, "drag_data_received", G_CALLBACK(ui_listview_drag_data_received), listview); |
|
674 } |
|
675 } |
|
676 |
|
677 #endif |
434 |
678 |
435 |
679 |
436 GtkWidget* ui_get_tree_widget(UIWIDGET widget) { |
680 GtkWidget* ui_get_tree_widget(UIWIDGET widget) { |
437 return SCROLLEDWINDOW_GET_CHILD(widget); |
681 return SCROLLEDWINDOW_GET_CHILD(widget); |
438 } |
682 } |