[gtk/wip/otte/dnd: 5/9] dragicon: Add gtk_drag_icon_create_widget_for_value()



commit 7a6546f476bc124922cdb6c6b8b57baa2edbf26f
Author: Benjamin Otte <otte redhat com>
Date:   Mon Mar 2 03:11:14 2020 +0100

    dragicon: Add gtk_drag_icon_create_widget_for_value()
    
    ... and use it to set a drag icon.

 docs/reference/gtk/gtk4-sections.txt |  3 ++
 gtk/gtkdragicon.c                    | 64 ++++++++++++++++++++++++++++++++++++
 gtk/gtkdragicon.h                    |  2 ++
 gtk/gtkdragsource.c                  | 64 ++++++++++++++++++++++++++----------
 4 files changed, 116 insertions(+), 17 deletions(-)
---
diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt
index 419b28193c..689ac2b024 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -6885,6 +6885,9 @@ gtk_drag_icon_set_child
 gtk_drag_icon_get_child
 gtk_drag_icon_set_from_paintable
 
+<SUBSECTION>
+gtk_drag_icon_create_widget_for_value
+
 <SUBSECTION Standard>
 GTK_TYPE_DRAG_ICON
 GTK_DRAG_ICON
diff --git a/gtk/gtkdragicon.c b/gtk/gtkdragicon.c
index 4e1afa522a..a01e088946 100644
--- a/gtk/gtkdragicon.c
+++ b/gtk/gtkdragicon.c
@@ -29,6 +29,11 @@
 #include "gtkpicture.h"
 #include "gtkcssnumbervalueprivate.h"
 
+/* for the drag icons */
+#include "gtkcolorswatchprivate.h"
+#include "gtklabel.h"
+#include "gtktextutil.h"
+
 
 /**
  * SECTION:gtkdragicon
@@ -497,3 +502,62 @@ gtk_drag_icon_get_child (GtkDragIcon *self)
   return self->child;
 }
 
+/**
+ * gtk_drag_icon_create_widget_for_value:
+ * @value: a #GValue
+ *
+ * Creates a widget that can be used as a drag icon for the given
+ * @value.
+ *
+ * If GTK does not know how to create a widget for a given value,
+ * it will return %NULL.
+ *
+ * This method is used to set the default drag icon on drag'n'drop
+ * operations started by #GtkDragSource, so you don't need to set
+ * a drag icon using this function there.
+ *
+ * Returns: (nullable) (transfer full): A new #GtkWidget
+ *     for displaying @value as a drag icon.
+ **/
+GtkWidget *
+gtk_drag_icon_create_widget_for_value (const GValue *value)
+{
+  g_return_val_if_fail (G_IS_VALUE (value), NULL);
+
+  if (G_VALUE_HOLDS (value, G_TYPE_STRING))
+    {
+      return gtk_label_new (g_value_get_string (value));
+    }
+  else if (G_VALUE_HOLDS (value, GDK_TYPE_RGBA))
+    {
+      GtkWidget *swatch;
+
+      swatch = gtk_color_swatch_new ();
+      gtk_color_swatch_set_rgba (GTK_COLOR_SWATCH (swatch), g_value_get_boxed (value));
+
+      return swatch;
+    }
+  else if (G_VALUE_HOLDS (value, GTK_TYPE_TEXT_BUFFER))
+    {
+      GtkTextBuffer *buffer = g_value_get_object (value);
+      GtkTextIter start, end;
+      GdkPaintable *paintable;
+      GtkWidget *picture;
+
+      if (buffer == NULL || !gtk_text_buffer_get_selection_bounds (buffer, &start, &end))
+        return NULL;
+
+      picture = gtk_picture_new ();
+      paintable = gtk_text_util_create_rich_drag_icon (picture, buffer, &start, &end);
+      gtk_picture_set_paintable (GTK_PICTURE (picture), paintable);
+      gtk_picture_set_can_shrink (GTK_PICTURE (picture), FALSE);
+      g_object_unref (paintable);
+
+      return picture;
+    }
+  else
+    {
+      return NULL;
+    }
+}
+
diff --git a/gtk/gtkdragicon.h b/gtk/gtkdragicon.h
index b8c70d6f86..3be995773a 100644
--- a/gtk/gtkdragicon.h
+++ b/gtk/gtkdragicon.h
@@ -52,6 +52,8 @@ void            gtk_drag_icon_set_from_paintable (GdkDrag      *drag,
                                                   int           hot_x,
                                                   int           hot_y);
 
+GtkWidget *     gtk_drag_icon_create_widget_for_value           (const GValue           *value);
+
 G_END_DECLS
 
 
diff --git a/gtk/gtkdragsource.c b/gtk/gtkdragsource.c
index 6b6c4d38de..017bee493c 100644
--- a/gtk/gtkdragsource.c
+++ b/gtk/gtkdragsource.c
@@ -439,6 +439,52 @@ gtk_drag_source_cancel_cb (GdkDrag             *drag,
   drag_end (source, FALSE);
 }
 
+static void
+gtk_drag_source_ensure_icon (GtkDragSource *self,
+                             GdkDrag       *drag)
+{
+  GdkContentProvider *provider;
+  GtkWidget *icon, *child;
+  GdkContentFormats *formats;
+  const GType *types;
+  gsize i, n_types;
+
+  icon = gtk_drag_icon_get_for_drag (drag);
+  /* If an icon has been set already, we don't need to set one. */
+  if (gtk_drag_icon_get_child (GTK_DRAG_ICON (icon)))
+    return;
+
+  gdk_drag_set_hotspot (drag, -2, -2);
+
+  provider = gdk_drag_get_content (drag);
+  formats = gdk_content_provider_ref_formats (provider);
+  types = gdk_content_formats_get_gtypes (formats, &n_types);
+  for (i = 0; i < n_types; i++)
+    {
+      GValue value = G_VALUE_INIT;
+
+      g_value_init (&value, types[i]);
+      if (gdk_content_provider_get_value (provider, &value, NULL))
+        {
+          child = gtk_drag_icon_create_widget_for_value (&value);
+
+          if (child)
+            {
+              gtk_drag_icon_set_child (GTK_DRAG_ICON (icon), child);
+              g_value_unset (&value);
+              gdk_content_formats_unref (formats);
+              return;
+            }
+        }
+      g_value_unset (&value);
+    }
+
+  gdk_content_formats_unref (formats);
+  child = gtk_image_new_from_icon_name ("text-x-generic");
+  gtk_image_set_icon_size (GTK_IMAGE (child), GTK_ICON_SIZE_LARGE);
+  gtk_drag_icon_set_child (GTK_DRAG_ICON (icon), child);
+}
+
 static void
 gtk_drag_source_drag_begin (GtkDragSource *source)
 {
@@ -481,23 +527,7 @@ gtk_drag_source_drag_begin (GtkDragSource *source)
 
   g_signal_emit (source, signals[DRAG_BEGIN], 0, source->drag);
 
-  if (!source->paintable)
-    {
-      GtkIconTheme *theme;
-
-      theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (widget));
-      source->paintable = GDK_PAINTABLE(gtk_icon_theme_lookup_icon (theme,
-                                                                    "text-x-generic",
-                                                                    NULL,
-                                                                    32,
-                                                                    1,
-                                                                    gtk_widget_get_direction (widget),
-                                                                    0));
-      source->hot_x = 0;
-      source->hot_y = 0;
-    }
-
-  gtk_drag_icon_set_from_paintable (source->drag, source->paintable, source->hot_x, source->hot_y);
+  gtk_drag_source_ensure_icon (source, source->drag);
 
   g_signal_connect (source->drag, "dnd-finished",
                     G_CALLBACK (gtk_drag_source_dnd_finished_cb), source);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]