chiark / gitweb /
Comments, esp. for multidrag
authorRichard Kettlewell <rjk@greenend.org.uk>
Fri, 13 Nov 2009 21:00:31 +0000 (21:00 +0000)
committerRichard Kettlewell <rjk@greenend.org.uk>
Fri, 13 Nov 2009 21:00:31 +0000 (21:00 +0000)
disobedience/multidrag.c
disobedience/queue-generic.c

index 95a133a5cc427ec682cfafe19de827adeb0e533c..650d1c4c73a96f7124686bdd6093d4537b8b02c8 100644 (file)
  */
 /** @file disobedience/multidrag.c
  * @brief Drag multiple rows of a GtkTreeView
+ *
+ * Normally when you start a drag, GtkTreeView sets the selection to just row
+ * you dragged from (because it can't cope with dragging more than one row at a
+ * time).
+ *
+ * Disobedience needs more.  To implement this it intercepts button-press-event
+ * and button-release event and for clicks that might be the start of drags,
+ * suppresses changes to the selection.  A consequence of this is that it needs
+ * to intercept button-release-event too, to restore the effect of the click,
+ * if it turns out not to be drag after all.
+ *
+ * The location of the initial click is stored in object data called @c
+ * multidrag-where.
+ *
+ * Inspired by similar code in <a
+ * href="http://code.google.com/p/quodlibet/">Quodlibet</a> (another software
+ * jukebox, albeit as far as I can see a single-user one).
  */
 #include "disobedience.h"
 
@@ -25,16 +42,16 @@ static gboolean multidrag_selection_block(GtkTreeSelection attribute((unused)) *
                                          GtkTreePath attribute((unused)) *path,
                                          gboolean attribute((unused)) path_currently_selected,
                                          gpointer data) {
-  return *(gboolean *)data;
+  return *(const gboolean *)data;
 }
 
 static void block_selection(GtkWidget *w, gboolean block,
                            int x, int y) {
-  static gboolean which[] = { FALSE, TRUE };
+  static const gboolean which[] = { FALSE, TRUE };
   GtkTreeSelection *s = gtk_tree_view_get_selection(GTK_TREE_VIEW(w));
   gtk_tree_selection_set_select_function(s,
                                         multidrag_selection_block,
-                                        &which[!!block],
+                                        (gboolean *)&which[!!block],
                                         NULL);
   // Remember the pointer location
   int *where = g_object_get_data(G_OBJECT(w), "multidrag-where");
@@ -44,6 +61,7 @@ static void block_selection(GtkWidget *w, gboolean block,
   }
   where[0] = x;
   where[1] = y;
+  // TODO release 'where' when object is destroyed
 }
 
 static gboolean multidrag_button_press_event(GtkWidget *w,
@@ -82,6 +100,8 @@ static gboolean multidrag_button_release_event(GtkWidget *w,
                                               gpointer attribute((unused)) user_data) {
   int *where = g_object_get_data(G_OBJECT(w), "multidrag-where");
 
+  /* Did button-press-event do anything?  We just check the outcome rather than
+   * going through all the conditions it tests. */
   if(where && where[0] != -1) {
     // Remember where the down-click was
     const int x = where[0], y = where[1];
@@ -104,6 +124,11 @@ static gboolean multidrag_button_release_event(GtkWidget *w,
   return FALSE;                        /* propagate */
 }
 
+/** @brief Allow multi-row drag for @p w
+ * @param w A GtkTreeView widget
+ *
+ * Suppresses the restriction of selections when a drag is started.
+ */
 void make_treeview_multidrag(GtkWidget *w) {
   g_signal_connect(w, "button-press-event",
                   G_CALLBACK(multidrag_button_press_event), NULL);
index 2db2e1dad40e5190a27df0896d859dbfc0d882c9..045b38ab104171fb7f4c02cabce9d4aa34991f04 100644 (file)
@@ -501,6 +501,15 @@ static void ql_drag_begin(GtkWidget attribute((unused)) *w,
                            NULL);
 }
 
+/** @brief Called when a drag moves within a candidate destination
+ * @param w Destination widget
+ * @param dc Drag context
+ * @param x Current pointer location
+ * @param y Current pointer location
+ * @param time_ Current time
+ * @param user_data Pointer to queuelike
+ * @return TRUE in a dropzone, otherwise FALSE
+ */
 static gboolean ql_drag_motion(GtkWidget *w,
                                GdkDragContext *dc,
                                gint x,
@@ -563,6 +572,12 @@ static gboolean ql_drag_motion(GtkWidget *w,
   return TRUE;
 }
 
+/** @brief Called when a drag moves leaves a candidate destination
+ * @param w Destination widget
+ * @param dc Drag context
+ * @param time_ Current time
+ * @param user_data Pointer to queuelike
+ */
 static void ql_drag_leave(GtkWidget *w,
                           GdkDragContext attribute((unused)) *dc,
                           guint attribute((unused)) time_,