[gnome-builder] grid: stub out API for doing DnD for text/uri-list



commit 1787506d75ea673febc64daba71b57dd61a2f155
Author: Christian Hergert <chergert redhat com>
Date:   Tue Dec 12 19:22:59 2017 -0800

    grid: stub out API for doing DnD for text/uri-list
    
    The goal here is to be able to drop a uri-list on a stack. We
    also want to be able to drag it into new splits and such, but
    that will come in a future patch.

 src/libide/editor/ide-editor-view.c |    2 +
 src/libide/layout/ide-layout-grid.c |  232 +++++++++++++++++++++++++++++++++++
 src/libide/layout/ide-layout-grid.h |    3 +-
 3 files changed, 236 insertions(+), 1 deletions(-)
---
diff --git a/src/libide/editor/ide-editor-view.c b/src/libide/editor/ide-editor-view.c
index 5d4467f..ba28eec 100644
--- a/src/libide/editor/ide-editor-view.c
+++ b/src/libide/editor/ide-editor-view.c
@@ -909,6 +909,8 @@ ide_editor_view_init (IdeEditorView *self)
 
   gtk_widget_init_template (GTK_WIDGET (self));
 
+  gtk_drag_dest_unset (GTK_WIDGET (self->source_view));
+
   ide_layout_view_set_can_split (IDE_LAYOUT_VIEW (self), TRUE);
   ide_layout_view_set_menu_id (IDE_LAYOUT_VIEW (self), "ide-editor-view-document-menu");
 
diff --git a/src/libide/layout/ide-layout-grid.c b/src/libide/layout/ide-layout-grid.c
index 943afec..777276e 100644
--- a/src/libide/layout/ide-layout-grid.c
+++ b/src/libide/layout/ide-layout-grid.c
@@ -18,6 +18,8 @@
 
 #define G_LOG_DOMAIN "ide-layout-grid"
 
+#include <string.h>
+
 #include "ide-object.h"
 
 #include "layout/ide-layout-grid.h"
@@ -53,6 +55,13 @@ typedef struct
   GArray         *stack_info;
 
   /*
+   * This owned reference is our box highlight theatric that we
+   * animate while doing a DnD drop interaction.
+   */
+  DzlBoxTheatric *drag_theatric;
+  DzlAnimation   *drag_anim;
+
+  /*
    * This unowned reference is simply used to compare to a new focus
    * view to see if we have changed our current view. It is not to
    * be used directly, only for pointer comparison.
@@ -62,6 +71,16 @@ typedef struct
 
 typedef struct
 {
+  IdeLayoutGridColumn *column;
+  IdeLayoutStack      *stack;
+  GdkRectangle         area;
+  gint                 drop;
+  gint                 x;
+  gint                 y;
+} DropLocate;
+
+typedef struct
+{
   IdeLayoutStack *stack;
   guint           len;
 } StackInfo;
@@ -76,9 +95,18 @@ enum {
 
 enum {
   CREATE_STACK,
+  CREATE_VIEW,
   N_SIGNALS
 };
 
+enum {
+  DROP_ONTO,
+  DROP_ABOVE,
+  DROP_BELOW,
+  DROP_LEFT_OF,
+  DROP_RIGHT_OF,
+};
+
 static void list_model_iface_init (GListModelInterface *iface);
 
 G_DEFINE_TYPE_WITH_CODE (IdeLayoutGrid, ide_layout_grid, DZL_TYPE_MULTI_PANED,
@@ -332,6 +360,198 @@ ide_layout_grid_remove (GtkContainer *container,
     g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CURRENT_COLUMN]);
 }
 
+static inline gboolean
+rect_contains_point (cairo_rectangle_int_t *rect,
+                     gint                   x,
+                     gint                   y)
+{
+  return x >= rect->x &&
+         y >= rect->y &&
+         x <= (rect->x + rect->width) &&
+         y <= (rect->y + rect->height);
+}
+
+static gboolean
+ide_layout_grid_get_drop_area (IdeLayoutGrid        *self,
+                               gint                  x,
+                               gint                  y,
+                               GdkRectangle         *out_area,
+                               IdeLayoutGridColumn **out_column,
+                               IdeLayoutStack      **out_stack,
+                               gint                 *out_drop)
+{
+  GtkAllocation alloc;
+  GtkWidget *column;
+  GtkWidget *stack = NULL;
+
+  g_assert (IDE_IS_LAYOUT_GRID (self));
+  g_assert (out_area != NULL);
+  g_assert (out_column != NULL);
+  g_assert (out_stack != NULL);
+  g_assert (out_drop != NULL);
+
+  gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
+
+  column = dzl_multi_paned_get_at_point (DZL_MULTI_PANED (self), x + alloc.x, 0);
+  if (column != NULL)
+    stack = dzl_multi_paned_get_at_point (DZL_MULTI_PANED (column), 0, y + alloc.y);
+
+  if (column != NULL && stack != NULL)
+    {
+      GtkAllocation stack_alloc;
+
+      gtk_widget_get_allocation (stack, &stack_alloc);
+
+      gtk_widget_translate_coordinates (stack,
+                                        GTK_WIDGET (self),
+                                        0, 0,
+                                        &stack_alloc.x, &stack_alloc.y);
+
+      *out_area = stack_alloc;
+      *out_column = IDE_LAYOUT_GRID_COLUMN (column);
+      *out_stack = IDE_LAYOUT_STACK (stack);
+      *out_drop = DROP_ONTO;
+
+      gtk_widget_translate_coordinates (GTK_WIDGET (self), stack, x, y, &x, &y);
+
+      if (FALSE) {}
+      else if (x < (stack_alloc.width / 4))
+        {
+          out_area->y = 0;
+          out_area->height = alloc.height;
+          out_area->width = stack_alloc.width / 4;
+          *out_drop = DROP_LEFT_OF;
+        }
+      else if (x > (stack_alloc.width / 4 * 3))
+        {
+          out_area->y = 0;
+          out_area->height = alloc.height;
+          out_area->x = dzl_cairo_rectangle_x2 (&stack_alloc) - (stack_alloc.width / 4);
+          out_area->width = stack_alloc.width / 4;
+          *out_drop = DROP_RIGHT_OF;
+        }
+      else if (y < (stack_alloc.height / 4))
+        {
+          out_area->height = stack_alloc.height / 4;
+          *out_drop = DROP_ABOVE;
+        }
+      else if (y > (stack_alloc.height / 4 * 3))
+        {
+          out_area->y = dzl_cairo_rectangle_y2 (&stack_alloc) - (stack_alloc.height / 4);
+          out_area->height = stack_alloc.height / 4;
+          *out_drop = DROP_BELOW;
+        }
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static gboolean
+ide_layout_grid_drag_motion (GtkWidget      *widget,
+                             GdkDragContext *context,
+                             gint            x,
+                             gint            y,
+                             guint           time_)
+{
+  IdeLayoutGrid *self = (IdeLayoutGrid *)widget;
+  IdeLayoutGridPrivate *priv = ide_layout_grid_get_instance_private (self);
+  IdeLayoutGridColumn *column = NULL;
+  IdeLayoutStack *stack = NULL;
+  DzlAnimation *drag_anim;
+  GdkRectangle area = { 0 };
+  GtkAllocation alloc;
+  gint drop = DROP_ONTO;
+
+  g_assert (IDE_IS_LAYOUT_GRID (self));
+  g_assert (GDK_IS_DRAG_CONTEXT (context));
+
+  if (priv->drag_anim != NULL)
+    {
+      dzl_animation_stop (priv->drag_anim);
+      dzl_clear_weak_pointer (&priv->drag_anim);
+    }
+
+  gtk_widget_get_allocation (GTK_WIDGET (self), &alloc);
+
+  if (!ide_layout_grid_get_drop_area (self, x, y, &area, &column, &stack, &drop))
+    return GDK_EVENT_PROPAGATE;
+
+  if (priv->drag_theatric == NULL)
+    {
+      priv->drag_theatric = g_object_new (DZL_TYPE_BOX_THEATRIC,
+                                          "x", area.x,
+                                          "y", area.y,
+                                          "width", area.width,
+                                          "height", area.height,
+                                          "alpha", 0.3,
+                                          "background", "#729fcf",
+                                          "target", self,
+                                          NULL);
+      return GDK_EVENT_STOP;
+    }
+
+  drag_anim = dzl_object_animate (priv->drag_theatric,
+                                  DZL_ANIMATION_EASE_OUT_CUBIC,
+                                  100,
+                                  gtk_widget_get_frame_clock (GTK_WIDGET (self)),
+                                  "x", area.x,
+                                  "width", area.width,
+                                  "y", area.y,
+                                  "height", area.height,
+                                  NULL);
+  dzl_set_weak_pointer (&priv->drag_anim, drag_anim);
+
+  gtk_widget_queue_draw (GTK_WIDGET (self));
+
+  return GDK_EVENT_STOP;
+}
+
+static void
+ide_layout_grid_drag_leave (GtkWidget      *widget,
+                            GdkDragContext *context,
+                            guint           time_)
+{
+  IdeLayoutGrid *self = (IdeLayoutGrid *)widget;
+  IdeLayoutGridPrivate *priv = ide_layout_grid_get_instance_private (self);
+
+  g_assert (IDE_IS_LAYOUT_GRID (self));
+  g_assert (GDK_IS_DRAG_CONTEXT (context));
+
+  if (priv->drag_anim != NULL)
+    {
+      dzl_animation_stop (priv->drag_anim);
+      dzl_clear_weak_pointer (&priv->drag_anim);
+    }
+
+  g_clear_object (&priv->drag_theatric);
+  gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+static gboolean
+ide_layout_grid_drag_failed (GtkWidget      *widget,
+                             GdkDragContext *context,
+                             GtkDragResult   result)
+{
+  IdeLayoutGrid *self = (IdeLayoutGrid *)widget;
+  IdeLayoutGridPrivate *priv = ide_layout_grid_get_instance_private (self);
+
+  g_assert (IDE_IS_LAYOUT_GRID (self));
+  g_assert (GDK_IS_DRAG_CONTEXT (context));
+
+  if (priv->drag_anim != NULL)
+    {
+      dzl_animation_stop (priv->drag_anim);
+      dzl_clear_weak_pointer (&priv->drag_anim);
+    }
+
+  g_clear_object (&priv->drag_theatric);
+  gtk_widget_queue_draw (GTK_WIDGET (self));
+
+  return GDK_EVENT_PROPAGATE;
+}
+
 static void
 ide_layout_grid_grab_focus (GtkWidget *widget)
 {
@@ -418,6 +638,9 @@ ide_layout_grid_class_init (IdeLayoutGridClass *klass)
   object_class->get_property = ide_layout_grid_get_property;
   object_class->set_property = ide_layout_grid_set_property;
 
+  widget_class->drag_motion = ide_layout_grid_drag_motion;
+  widget_class->drag_leave = ide_layout_grid_drag_leave;
+  widget_class->drag_failed = ide_layout_grid_drag_failed;
   widget_class->grab_focus = ide_layout_grid_grab_focus;
   widget_class->hierarchy_changed = ide_layout_grid_hierarchy_changed;
 
@@ -472,6 +695,15 @@ static void
 ide_layout_grid_init (IdeLayoutGrid *self)
 {
   IdeLayoutGridPrivate *priv = ide_layout_grid_get_instance_private (self);
+  static const GtkTargetEntry target_entries[] = {
+    { "text/uri-list", 0, 0 },
+  };
+
+  gtk_drag_dest_set (GTK_WIDGET (self),
+                     GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
+                     target_entries,
+                     G_N_ELEMENTS (target_entries),
+                     GDK_ACTION_COPY);
 
   priv->stack_info = g_array_new (FALSE, FALSE, sizeof (StackInfo));
 
diff --git a/src/libide/layout/ide-layout-grid.h b/src/libide/layout/ide-layout-grid.h
index 1ca4b71..e44ccbd 100644
--- a/src/libide/layout/ide-layout-grid.h
+++ b/src/libide/layout/ide-layout-grid.h
@@ -37,9 +37,10 @@ struct _IdeLayoutGridClass
   DzlMultiPanedClass parent_class;
 
   IdeLayoutStack *(*create_stack) (IdeLayoutGrid *self);
+  IdeLayoutView  *(*create_view)  (IdeLayoutGrid *self,
+                                   const gchar   *uri);
 
   /*< private >*/
-  gpointer _reserved1;
   gpointer _reserved2;
   gpointer _reserved3;
   gpointer _reserved4;


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