chiark / gitweb /
Multiple-track drag+drop queue rearrangement.
[disorder] / disobedience / multidrag.c
CommitLineData
6a7eb118
RK
1/*
2 * This file is part of DisOrder
3 * Copyright (C) 2009 Richard Kettlewell
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18/** @file disobedience/multidrag.c
19 * @brief Drag multiple rows of a GtkTreeView
20 */
21#include "disobedience.h"
22
23static gboolean multidrag_selection_block(GtkTreeSelection attribute((unused)) *selection,
24 GtkTreeModel attribute((unused)) *model,
25 GtkTreePath attribute((unused)) *path,
26 gboolean attribute((unused)) path_currently_selected,
27 gpointer data) {
28 return *(gboolean *)data;
29}
30
31static void block_selection(GtkWidget *w, gboolean block,
32 int x, int y) {
33 static gboolean which[] = { FALSE, TRUE };
34 GtkTreeSelection *s = gtk_tree_view_get_selection(GTK_TREE_VIEW(w));
35 gtk_tree_selection_set_select_function(s,
36 multidrag_selection_block,
37 &which[!!block],
38 NULL);
39 // Remember the pointer location
40 int *where = g_object_get_data(G_OBJECT(w), "multidrag-where");
41 if(!where) {
42 where = g_malloc(2 * sizeof (int));
43 g_object_set_data(G_OBJECT(w), "multidrag-where", where);
44 }
45 where[0] = x;
46 where[1] = y;
47}
48
49static gboolean multidrag_button_press_event(GtkWidget *w,
50 GdkEventButton *event,
51 gpointer attribute((unused)) user_data) {
52 /* By default we assume that anything this button press does should
53 * act as normal */
54 block_selection(w, TRUE, -1, -1);
55 /* We are only interested in left-button behavior */
56 if(event->button != 1)
57 return FALSE;
58 /* We are only interested in unmodified clicks (not SHIFT etc) */
59 if(event->state & GDK_MODIFIER_MASK)
60 return FALSE;
61 /* We are only interested if a well-defined path is clicked */
62 GtkTreePath *path;
63 if(!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(w),
64 event->x, event->y,
65 &path,
66 NULL,
67 NULL, NULL))
68 return FALSE;
69 //gtk_widget_grab_focus(w); // TODO why??
70 /* We are only interested if a selected row is clicked */
71 GtkTreeSelection *s = gtk_tree_view_get_selection(GTK_TREE_VIEW(w));
72 if(!gtk_tree_selection_path_is_selected(s, path))
73 return FALSE;
74 /* We block subsequent selection changes and remember where the
75 * click was */
76 block_selection(w, FALSE, event->x, event->y);
77 return FALSE; /* propagate */
78}
79
80static gboolean multidrag_button_release_event(GtkWidget *w,
81 GdkEventButton *event,
82 gpointer attribute((unused)) user_data) {
83 int *where = g_object_get_data(G_OBJECT(w), "multidrag-where");
84
85 if(where && where[0] != -1) {
86 // Remember where the down-click was
87 const int x = where[0], y = where[1];
88 // Re-allow selections
89 block_selection(w, TRUE, -1, -1);
90 if(x == event->x && y == event->y) {
91 // If the up-click is at the same location as the down-click,
92 // it's not a drag.
93 GtkTreePath *path;
94 GtkTreeViewColumn *col;
95 if(gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(w),
96 event->x, event->y,
97 &path,
98 &col,
99 NULL, NULL)) {
100 gtk_tree_view_set_cursor(GTK_TREE_VIEW(w), path, col, FALSE);
101 }
102 }
103 }
104 return FALSE; /* propagate */
105}
106
107void make_treeview_multidrag(GtkWidget *w) {
108 g_signal_connect(w, "button-press-event",
109 G_CALLBACK(multidrag_button_press_event), NULL);
110 g_signal_connect(w, "button-release-event",
111 G_CALLBACK(multidrag_button_release_event), NULL);
112}
113
114/*
115Local Variables:
116c-basic-offset:2
117comment-column:40
118fill-column:79
119indent-tabs-mode:nil
120End:
121*/