chiark / gitweb /
Replace the drag icon with a representation of the dragged row(s), as
authorRichard Kettlewell <rjk@greenend.org.uk>
Mon, 9 Nov 2009 19:59:29 +0000 (19:59 +0000)
committerRichard Kettlewell <rjk@greenend.org.uk>
Mon, 9 Nov 2009 19:59:29 +0000 (19:59 +0000)
is fashionable these days.

disobedience/queue-generic.c

index 92c3851..aea8104 100644 (file)
@@ -423,6 +423,26 @@ void ql_new_queue(struct queuelike *ql,
   --suppress_actions;
 }
 
+/** @brief State for ql_drag_begin() and its callbacks */
+struct ql_drag_begin_state {
+  struct queuelike *ql;
+  int rows;
+  int index;
+  GdkPixmap **pixmaps;
+};
+
+/** @brief Callback to construct a row pixmap */
+static void ql_drag_make_row_pixmaps(GtkTreeModel attribute((unused)) *model,
+                                     GtkTreePath *path,
+                                     GtkTreeIter attribute((unused)) *iter,
+                                     gpointer data) {
+  struct ql_drag_begin_state *qdbs = data;
+
+  qdbs->pixmaps[qdbs->index++]
+    = gtk_tree_view_create_row_drag_icon(GTK_TREE_VIEW(qdbs->ql->view),
+                                         path);
+}
+
 /** @brief Called when a drag operation from this queuelike begins
  * @param w Source widget (the tree view)
  * @param dc Drag context
@@ -431,11 +451,54 @@ void ql_new_queue(struct queuelike *ql,
 static void ql_drag_begin(GtkWidget attribute((unused)) *w,
                           GdkDragContext attribute((unused)) *dc,
                           gpointer user_data) {
-  struct queuelike *const attribute((unused)) ql = user_data;
-
-  fprintf(stderr, "drag-begin\n");
-  // TODO call gtk_drag_source_set_icon() to set a suitably informative
-  // drag icon
+  struct queuelike *const ql = user_data;
+  struct ql_drag_begin_state qdbs[1];
+  GdkPixmap *icon;
+
+  //fprintf(stderr, "drag-begin\n");
+  memset(qdbs, 0, sizeof *qdbs);
+  qdbs->ql = ql;
+  /* Find out how many rows there are */
+  if(!(qdbs->rows = gtk_tree_selection_count_selected_rows(ql->selection)))
+    return;                             /* doesn't make sense */
+  /* Generate a pixmap for each row */
+  qdbs->pixmaps = xcalloc(qdbs->rows, sizeof *qdbs->pixmaps);
+  gtk_tree_selection_selected_foreach(ql->selection,
+                                      ql_drag_make_row_pixmaps,
+                                      qdbs);
+  /* Determine the size of the final icon */
+  int height = 0, width = 0;
+  for(int n = 0; n < qdbs->rows; ++n) {
+    int pxw, pxh;
+    gdk_drawable_get_size(qdbs->pixmaps[n], &pxw, &pxh);
+    if(pxw > width)
+      width = pxw;
+    height += pxh;
+  }
+  if(!width || !height)
+    return;                             /* doesn't make sense */
+  /* Construct the icon */
+  icon = gdk_pixmap_new(qdbs->pixmaps[0], width, height, -1);
+  GdkGC *gc = gdk_gc_new(icon);
+  gdk_gc_set_colormap(gc, gtk_widget_get_colormap(ql->view));
+  int y = 0;
+  for(int n = 0; n < qdbs->rows; ++n) {
+    int pxw, pxh;
+    gdk_drawable_get_size(qdbs->pixmaps[n], &pxw, &pxh);
+    gdk_draw_drawable(icon,
+                      gc,
+                      qdbs->pixmaps[n],
+                      0, 0,             /* source coords */
+                      0, y,             /* dest coords */
+                      pxw, pxh);        /* size */
+    y += pxh;
+  }
+  // TODO scale down a bit, the resulting icons are currently a bit on the
+  // large side.
+  gtk_drag_source_set_icon(ql->view,
+                           gtk_widget_get_colormap(ql->view),
+                           icon,
+                           NULL);
 }
 
 /** @brief Callback to add selected tracks to the selection data