libegg r845 - in trunk: . libegg/toolpalette



Author: hasselmm
Date: Tue Jan 15 15:37:42 2008
New Revision: 845
URL: http://svn.gnome.org/viewvc/libegg?rev=845&view=rev

Log:
Also demonstrate interactive drag-and-drop.

* libegg/toolpalette/testtoolpalette.c: Replace text-view by primitive
canvas widgets to also demonstrate interactive drag-and-drop.


Modified:
   trunk/ChangeLog
   trunk/libegg/toolpalette/testtoolpalette.c

Modified: trunk/libegg/toolpalette/testtoolpalette.c
==============================================================================
--- trunk/libegg/toolpalette/testtoolpalette.c	(original)
+++ trunk/libegg/toolpalette/testtoolpalette.c	Tue Jan 15 15:37:42 2008
@@ -6,6 +6,267 @@
 #include <glib/gi18n.h>
 #include <string.h>
 
+typedef struct _CanvasItem CanvasItem;
+
+struct _CanvasItem
+{
+  GdkPixbuf *pixbuf;
+  gdouble x, y;
+};
+
+static CanvasItem *drop_item = NULL;
+static GList *canvas_items = NULL;
+
+/********************************/
+/* ====== Canvas drawing ====== */
+/********************************/
+
+static CanvasItem*
+canvas_item_new (GtkWidget     *widget,
+                 GtkToolButton *button,
+                 gdouble        x,
+                 gdouble        y)
+{
+  CanvasItem *item = NULL;
+  const gchar *stock_id;
+  GdkPixbuf *pixbuf;
+
+  stock_id = gtk_tool_button_get_stock_id (button);
+  pixbuf = gtk_widget_render_icon (widget, stock_id, GTK_ICON_SIZE_DIALOG, NULL);
+
+  if (pixbuf)
+    {
+      item = g_slice_new0 (CanvasItem);
+      item->pixbuf = pixbuf;
+      item->x = x;
+      item->y = y;
+    }
+
+  return item;
+}
+
+static void
+canvas_item_free (CanvasItem *item)
+{
+  g_object_unref (item->pixbuf);
+  g_slice_free (CanvasItem, item);
+}
+
+static void
+canvas_item_draw (const CanvasItem *item,
+                  cairo_t          *cr,
+                  gboolean          preview)
+{
+  gdouble cx = gdk_pixbuf_get_width (item->pixbuf);
+  gdouble cy = gdk_pixbuf_get_height (item->pixbuf);
+
+  gdk_cairo_set_source_pixbuf (cr,
+                               item->pixbuf,
+                               item->x - cx * 0.5,
+                               item->y - cy * 0.5);
+
+  if (preview)
+    cairo_paint_with_alpha (cr, 0.6);
+  else
+    cairo_paint (cr);
+}
+
+static gboolean
+canvas_expose_event (GtkWidget      *widget,
+                     GdkEventExpose *event)
+{
+  cairo_t *cr;
+  GList *iter;
+
+  cr = gdk_cairo_create (widget->window);
+  gdk_cairo_region (cr, event->region);
+  cairo_clip (cr);
+
+  cairo_set_source_rgb (cr, 1, 1, 1);
+  cairo_rectangle (cr, 0, 0, widget->allocation.width, widget->allocation.height);
+  cairo_fill (cr);
+
+  for (iter = canvas_items; iter; iter = iter->next)
+    canvas_item_draw (iter->data, cr, FALSE);
+
+  if (drop_item)
+    canvas_item_draw (drop_item, cr, TRUE);
+
+  cairo_destroy (cr);
+
+  return TRUE;
+}
+
+/********************************/
+/* ====== Passive Canvas ====== */
+/********************************/
+
+static void
+passive_canvas_drag_data_received (GtkWidget        *widget,
+                                   GdkDragContext   *context,
+                                   gint              x,
+                                   gint              y,
+                                   GtkSelectionData *selection,
+                                   guint             info G_GNUC_UNUSED,
+                                   guint             time G_GNUC_UNUSED,
+                                   gpointer          data G_GNUC_UNUSED)
+{
+  /* find the tool button, which is the source of this DnD operation */
+
+  GtkWidget *palette = gtk_drag_get_source_widget (context);
+  CanvasItem *canvas_item = NULL;
+  GtkToolItem *tool_item = NULL;
+
+  while (palette && !EGG_IS_TOOL_PALETTE (palette))
+    palette = gtk_widget_get_parent (palette);
+
+  if (palette)
+    tool_item = egg_tool_palette_get_drag_item (EGG_TOOL_PALETTE (palette), selection);
+
+  g_assert (NULL == drop_item);
+
+  /* append a new canvas item when a tool button was found */
+
+  if (GTK_IS_TOOL_ITEM (tool_item))
+    canvas_item = canvas_item_new (widget, GTK_TOOL_BUTTON (tool_item), x, y);
+
+  if (canvas_item)
+    {
+      canvas_items = g_list_append (canvas_items, canvas_item);
+      gtk_widget_queue_draw (widget);
+    }
+}
+
+/************************************/
+/* ====== Interactive Canvas ====== */
+/************************************/
+
+static gboolean
+interactive_canvas_drag_motion (GtkWidget        *widget,
+                                GdkDragContext   *context,
+                                gint              x,
+                                gint              y,
+                                guint             time,
+                                gpointer          data G_GNUC_UNUSED)
+{
+  if (drop_item)
+    {
+      /* already have a drop indicator - just update position */
+
+      drop_item->x = x;
+      drop_item->y = y;
+
+      gtk_widget_queue_draw (widget);
+      gdk_drag_status (context, GDK_ACTION_COPY, time);
+    }
+  else
+    {
+      /* request DnD data for creating a drop indicator */
+
+      GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL);
+
+      if (!target)
+        return FALSE;
+
+      gtk_drag_get_data (widget, context, target, time);
+    }
+
+  return TRUE;
+}
+
+static void
+interactive_canvas_drag_data_received (GtkWidget        *widget,
+                                       GdkDragContext   *context,
+                                       gint              x,
+                                       gint              y,
+                                       GtkSelectionData *selection,
+                                       guint             info G_GNUC_UNUSED,
+                                       guint             time G_GNUC_UNUSED,
+                                       gpointer          data G_GNUC_UNUSED)
+
+{
+  /* find the tool button, which is the source of this DnD operation */
+
+  GtkWidget *palette = gtk_drag_get_source_widget (context);
+  GtkToolItem *tool_item = NULL;
+
+  while (palette && !EGG_IS_TOOL_PALETTE (palette))
+    palette = gtk_widget_get_parent (palette);
+
+  if (palette)
+    tool_item = egg_tool_palette_get_drag_item (EGG_TOOL_PALETTE (palette), selection);
+
+  /* create a drop indicator when a tool button was found */
+
+  g_assert (NULL == drop_item);
+
+  if (GTK_IS_TOOL_ITEM (tool_item))
+    {
+      drop_item = canvas_item_new (widget, GTK_TOOL_BUTTON (tool_item), x, y);
+      gdk_drag_status (context, GDK_ACTION_COPY, time);
+      gtk_widget_queue_draw (widget);
+    }
+}
+
+static gboolean
+interactive_canvas_drag_drop (GtkWidget        *widget,
+                              GdkDragContext   *context G_GNUC_UNUSED,
+                              gint              x,
+                              gint              y,
+                              guint             time,
+                              gpointer          data    G_GNUC_UNUSED)
+{
+  if (drop_item)
+    {
+      /* turn the drop indicator into a real canvas item */
+
+      drop_item->x = x;
+      drop_item->y = y;
+
+      canvas_items = g_list_append (canvas_items, drop_item);
+      drop_item = NULL;
+
+      /* signal the item was accepted and redraw */
+
+      gtk_drag_finish (context, TRUE, FALSE, time);
+      gtk_widget_queue_draw (widget);
+
+      return TRUE;
+    }
+
+  return FALSE;
+}
+
+static gboolean
+interactive_canvas_real_drag_leave (gpointer data)
+{
+  if (drop_item)
+    {
+      GtkWidget *widget = GTK_WIDGET (data);
+
+      canvas_item_free (drop_item);
+      drop_item = NULL;
+
+      gtk_widget_queue_draw (widget);
+    }
+
+  return FALSE;
+}
+
+static void
+interactive_canvas_drag_leave (GtkWidget        *widget,
+                               GdkDragContext   *context G_GNUC_UNUSED,
+                               guint             time    G_GNUC_UNUSED,
+                               gpointer          data    G_GNUC_UNUSED)
+{
+  /* defer cleanup until a potential "drag-drop" signal was received */
+  g_idle_add (interactive_canvas_real_drag_leave, widget);
+}
+
+/*******************************/
+/* ====== Setup Test UI ====== */
+/*******************************/
+
 static void
 not_implemented (GtkAction *action,
                  GtkWindow *parent)
@@ -78,38 +339,6 @@
   g_slist_free (stock_ids);
 }
 
-static void
-contents_drag_data_received (GtkWidget        *widget,
-                             GdkDragContext   *context,
-                             gint              x         G_GNUC_UNUSED,
-                             gint              y         G_GNUC_UNUSED,
-                             GtkSelectionData *selection,
-                             guint             info      G_GNUC_UNUSED,
-                             guint             time      G_GNUC_UNUSED,
-                             gpointer          data      G_GNUC_UNUSED)
-
-{
-  GtkWidget *palette = NULL;
-  GtkToolItem *item = NULL;
-  GtkTextBuffer *buffer;
-  const gchar *stock_id;
-
-  palette = gtk_drag_get_source_widget (context);
-
-  while (palette && !EGG_IS_TOOL_PALETTE (palette))
-    palette = gtk_widget_get_parent (palette);
-
-  if (palette)
-    item = egg_tool_palette_get_drag_item (EGG_TOOL_PALETTE (palette), selection);
-
-  if (GTK_IS_TOOL_ITEM (item))
-    {
-      buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (widget));
-      stock_id = gtk_tool_button_get_stock_id (GTK_TOOL_BUTTON (item));
-      gtk_text_buffer_set_text (buffer, stock_id, -1);
-    }
-}
-
 static gboolean
 drop_invalid_icon_size (GEnumValue *enum_value,
                         gpointer    user_data G_GNUC_UNUSED)
@@ -176,7 +405,7 @@
   GError *error = NULL;
   GtkUIManager *ui;
 
-  GtkWidget *window, *vbox;
+  GtkWidget *window, *vbox, *notebook;
   GtkWidget *menubar, *toolbar, *hpaned;
   GtkWidget *palette, *palette_scroller;
   GtkWidget *contents, *contents_scroller;
@@ -225,29 +454,63 @@
   gtk_container_set_border_width (GTK_CONTAINER (palette_scroller), 6);
   gtk_container_add (GTK_CONTAINER (palette_scroller), palette);
 
-  /* ===== contents ===== */
+  /* ===== notebook ===== */
+
+  notebook = gtk_notebook_new ();
+  gtk_container_set_border_width (GTK_CONTAINER (notebook), 6);
+
+  /* ===== passive DnD dest ===== */
+
+  contents = gtk_drawing_area_new ();
+  gtk_widget_set_app_paintable (contents, TRUE);
+
+  g_object_connect (contents,
+                    "signal::expose-event",       canvas_expose_event, NULL,
+                    "signal::drag-data-received", passive_canvas_drag_data_received, NULL,
+                    NULL);
+
+  egg_tool_palette_add_drag_dest (EGG_TOOL_PALETTE (palette),
+                                  contents, GTK_DEST_DEFAULT_ALL);
 
-  contents = gtk_text_view_new ();
-  gtk_widget_set_size_request (contents, 100, 400);
-  egg_tool_palette_add_drag_dest (EGG_TOOL_PALETTE (palette), contents, GTK_DEST_DEFAULT_ALL);
+  contents_scroller = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (contents_scroller),
+                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (contents_scroller), contents);
+  gtk_container_set_border_width (GTK_CONTAINER (contents_scroller), 6);
+
+  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), contents_scroller,
+                            gtk_label_new ("Passive DnD Mode"));
 
-  g_signal_connect (contents, "drag-data-received",
-                    G_CALLBACK (contents_drag_data_received),
+  /* ===== interactive DnD dest ===== */
+
+  contents = gtk_drawing_area_new ();
+  gtk_widget_set_app_paintable (contents, TRUE);
+
+  g_object_connect (contents,
+                    "signal::expose-event",       canvas_expose_event, NULL,
+                    "signal::drag-motion",        interactive_canvas_drag_motion, NULL,
+                    "signal::drag-data-received", interactive_canvas_drag_data_received, NULL,
+                    "signal::drag-leave",         interactive_canvas_drag_leave, NULL,
+                    "signal::drag-drop",          interactive_canvas_drag_drop, NULL,
                     NULL);
 
+  egg_tool_palette_add_drag_dest (EGG_TOOL_PALETTE (palette),
+                                  contents, GTK_DEST_DEFAULT_HIGHLIGHT);
+
   contents_scroller = gtk_scrolled_window_new (NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (contents_scroller),
-                                  GTK_POLICY_ALWAYS, GTK_POLICY_ALWAYS);
-  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (contents_scroller),
-                                       GTK_SHADOW_IN);
-  gtk_container_add (GTK_CONTAINER (contents_scroller), contents);
+                                  GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+  gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (contents_scroller), contents);
   gtk_container_set_border_width (GTK_CONTAINER (contents_scroller), 6);
 
+  gtk_notebook_append_page (GTK_NOTEBOOK (notebook), contents_scroller,
+                            gtk_label_new ("Interactive DnD Mode"));
+
   /* ===== hpaned ===== */
 
   hpaned = gtk_hpaned_new ();
   gtk_paned_pack1 (GTK_PANED (hpaned), palette_scroller, FALSE, FALSE);
-  gtk_paned_pack2 (GTK_PANED (hpaned), contents_scroller, TRUE, FALSE);
+  gtk_paned_pack2 (GTK_PANED (hpaned), notebook, TRUE, FALSE);
 
   /* ===== vbox ===== */
 



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