[gnome-calendar/wip/pandusonu/week-view] week-header: implement drag n' drop



commit 7a21e1e5ac6e8d1092a05a009b69982f869b2446
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Tue Jan 17 11:23:41 2017 -0200

    week-header: implement drag n' drop

 src/views/gcal-week-header.c |  152 ++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 145 insertions(+), 7 deletions(-)
---
diff --git a/src/views/gcal-week-header.c b/src/views/gcal-week-header.c
index 75c6956..32d1655 100644
--- a/src/views/gcal-week-header.c
+++ b/src/views/gcal-week-header.c
@@ -71,6 +71,7 @@ struct _GcalWeekHeader
 
   gint              selection_start;
   gint              selection_end;
+  gint              dnd_cell;
 
   GtkSizeGroup     *sizegroup;
 };
@@ -1179,13 +1180,16 @@ gcal_week_header_draw (GtkWidget      *widget,
 
   cell_width = (alloc.width - start_x) / 7.0;
 
-  /* Start by redrawing the entire background */
-  gtk_render_background (context,
-                         cr,
-                         alloc.x,
-                         alloc.y,
-                         alloc.width,
-                         alloc.height);
+  /* Drag and Drop highlight */
+  if (self->dnd_cell != -1)
+    {
+      gtk_render_background (context,
+                             cr,
+                             start_x + self->dnd_cell * cell_width,
+                             start_y,
+                             cell_width,
+                             alloc.height - start_y + 6);
+    }
 
   /* Draw the selection background */
   if (self->selection_start != -1 && self->selection_end != -1)
@@ -1342,6 +1346,129 @@ gcal_week_header_draw (GtkWidget      *widget,
   return FALSE;
 }
 
+
+static gint
+get_dnd_cell (GtkWidget *widget,
+              gint       x,
+              gint       y)
+{
+  gdouble column_width;
+
+  column_width = gtk_widget_get_allocated_width (widget) / 7.0;
+
+  return x / column_width;
+}
+
+static gboolean
+gcal_week_header_drag_motion (GtkWidget      *widget,
+                              GdkDragContext *context,
+                              gint            x,
+                              gint            y,
+                              guint           time)
+{
+  GcalWeekHeader *self;
+
+  self = GCAL_WEEK_HEADER (widget);
+  self->dnd_cell = get_dnd_cell (widget, x, y);
+
+  /* Setup the drag highlight */
+  if (self->dnd_cell != -1)
+    gtk_drag_highlight (widget);
+  else
+    gtk_drag_unhighlight (widget);
+
+  /*
+   * Sets the status of the drag - if it fails, sets the action to 0 and
+   * aborts the drag with FALSE.
+   */
+  gdk_drag_status (context,
+                   self->dnd_cell == -1 ? 0 : GDK_ACTION_COPY,
+                   time);
+
+  gtk_widget_queue_draw (widget);
+
+  return self->dnd_cell != -1;
+}
+
+static gboolean
+gcal_week_header_drag_drop (GtkWidget      *widget,
+                            GdkDragContext *context,
+                            gint            x,
+                            gint            y,
+                            guint           time)
+{
+  GcalWeekHeader *self;
+  g_autoptr (GDateTime) week_start;
+  g_autoptr (GDateTime) dnd_date;
+  GtkWidget *event_widget;
+  GcalEvent *event;
+  gboolean ltr;
+  gint drop_cell;
+
+  self = GCAL_WEEK_HEADER (widget);
+  ltr = gtk_widget_get_direction (widget) != GTK_TEXT_DIR_RTL;
+  drop_cell = get_dnd_cell (widget, x, y);
+  event_widget = gtk_drag_get_source_widget (context);
+
+  week_start = dnd_date = NULL;
+
+  if (!GCAL_IS_EVENT_WIDGET (event_widget))
+    return FALSE;
+
+  /* RTL languages swap the drop cell column */
+  if (!ltr)
+    {
+      drop_cell = 6 - drop_cell;
+    }
+
+  event = gcal_event_widget_get_event (GCAL_EVENT_WIDGET (event_widget));
+  week_start = get_start_of_week (self->active_date);
+  dnd_date = g_date_time_add_days (week_start, drop_cell);
+
+  /*
+   * Set the event's start and end dates. Since the event may have a
+   * NULL end date, so we have to check it here
+   */
+  gcal_event_set_all_day (event, TRUE);
+  gcal_event_set_date_start (event, dnd_date);
+
+  if (gcal_event_get_date_end (event))
+    {
+      g_autoptr (GDateTime) new_end;
+
+      new_end = g_date_time_add_days (dnd_date, 1);
+
+      gcal_event_set_date_end (event, new_end);
+    }
+
+  /* Commit the changes */
+  gcal_manager_update_event (self->manager, event);
+
+  /* Cancel the DnD */
+  self->dnd_cell = -1;
+  gtk_drag_unhighlight (widget);
+
+  gtk_drag_finish (context, TRUE, FALSE, time);
+
+  gtk_widget_queue_draw (widget);
+
+  return TRUE;
+}
+
+static void
+gcal_week_header_drag_leave (GtkWidget      *widget,
+                             GdkDragContext *context,
+                             guint           time)
+{
+  GcalWeekHeader *self = GCAL_WEEK_HEADER (widget);
+
+  /* Cancel the drag */
+  self->dnd_cell = -1;
+  gtk_drag_unhighlight (widget);
+
+  gtk_widget_queue_draw (widget);
+}
+
 static void
 gcal_week_header_class_init (GcalWeekHeaderClass *kclass)
 {
@@ -1354,6 +1481,9 @@ gcal_week_header_class_init (GcalWeekHeaderClass *kclass)
 
   widget_class->draw = gcal_week_header_draw;
   widget_class->size_allocate = gcal_week_header_size_allocate;
+  widget_class->drag_motion = gcal_week_header_drag_motion;
+  widget_class->drag_leave = gcal_week_header_drag_leave;
+  widget_class->drag_drop = gcal_week_header_drag_drop;
 
   g_object_class_install_property (object_class,
                                    PROP_ACTIVE_DATE,
@@ -1398,8 +1528,16 @@ gcal_week_header_init (GcalWeekHeader *self)
   self->expanded = FALSE;
   self->selection_start = -1;
   self->selection_end = -1;
+  self->dnd_cell = -1;
 
   gtk_widget_init_template (GTK_WIDGET (self));
+
+  /* Setup the week header as a drag n' drop destination */
+  gtk_drag_dest_set (GTK_WIDGET (self),
+                     0,
+                     NULL,
+                     0,
+                     GDK_ACTION_MOVE);
 }
 
 /* Public API */


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