]> Pileus Git - ~andy/gtk/blob - gtk/gtktreednd.c
New static function to set the background of all windows.
[~andy/gtk] / gtk / gtktreednd.c
1 /* gtktreednd.c
2  * Copyright (C) 2001  Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include <string.h>
21 #include "gtktreednd.h"
22
23 GType
24 gtk_tree_drag_source_get_type (void)
25 {
26   static GType our_type = 0;
27
28   if (!our_type)
29     {
30       static const GTypeInfo our_info =
31       {
32         sizeof (GtkTreeDragSourceIface), /* class_size */
33         NULL,           /* base_init */
34         NULL,           /* base_finalize */
35         NULL,
36         NULL,           /* class_finalize */
37         NULL,           /* class_data */
38         0,
39         0,              /* n_preallocs */
40         NULL
41       };
42
43       our_type = g_type_register_static (G_TYPE_INTERFACE, "GtkTreeDragSource",
44                                          &our_info, 0);
45     }
46   
47   return our_type;
48 }
49
50
51 GType
52 gtk_tree_drag_dest_get_type (void)
53 {
54   static GType our_type = 0;
55
56   if (!our_type)
57     {
58       static const GTypeInfo our_info =
59       {
60         sizeof (GtkTreeDragDestIface), /* class_size */
61         NULL,           /* base_init */
62         NULL,           /* base_finalize */
63         NULL,
64         NULL,           /* class_finalize */
65         NULL,           /* class_data */
66         0,
67         0,              /* n_preallocs */
68         NULL
69       };
70
71       our_type = g_type_register_static (G_TYPE_INTERFACE, "GtkTreeDragDest", &our_info, 0);
72     }
73   
74   return our_type;
75 }
76
77 /**
78  * gtk_tree_drag_source_row_draggable:
79  * @drag_source: a #GtkTreeDragSource
80  * @path: row on which user is initiating a drag
81  * 
82  * Asks the #GtkTreeDragSource whether a particular row can be used as
83  * the source of a DND operation. If the source doesn't implement
84  * this interface, the row is assumed draggable.
85  *
86  * Return value: %TRUE if the row can be dragged
87  **/
88 gboolean
89 gtk_tree_drag_source_row_draggable (GtkTreeDragSource *drag_source,
90                                     GtkTreePath       *path)
91 {
92   GtkTreeDragSourceIface *iface = GTK_TREE_DRAG_SOURCE_GET_IFACE (drag_source);
93
94   g_return_val_if_fail (path != NULL, FALSE);
95
96   if (iface->row_draggable)
97     return (* iface->row_draggable) (drag_source, path);
98   else
99     return TRUE;
100 }
101
102
103 /**
104  * gtk_tree_drag_source_drag_data_delete:
105  * @drag_source: a #GtkTreeDragSource
106  * @path: row that was being dragged
107  * 
108  * Asks the #GtkTreeDragSource to delete the row at @path, because
109  * it was moved somewhere else via drag-and-drop. Returns %FALSE
110  * if the deletion fails because @path no longer exists, or for
111  * some model-specific reason. Should robustly handle a @path no
112  * longer found in the model!
113  * 
114  * Return value: %TRUE if the row was successfully deleted
115  **/
116 gboolean
117 gtk_tree_drag_source_drag_data_delete (GtkTreeDragSource *drag_source,
118                                        GtkTreePath       *path)
119 {
120   GtkTreeDragSourceIface *iface = GTK_TREE_DRAG_SOURCE_GET_IFACE (drag_source);
121
122   g_return_val_if_fail (iface->drag_data_delete != NULL, FALSE);
123   g_return_val_if_fail (path != NULL, FALSE);
124
125   return (* iface->drag_data_delete) (drag_source, path);
126 }
127
128 /**
129  * gtk_tree_drag_source_drag_data_get:
130  * @drag_source: a #GtkTreeDragSource
131  * @path: row that was dragged
132  * @selection_data: a #GtkSelectionData to fill with data from the dragged row
133  * 
134  * Asks the #GtkTreeDragSource to fill in @selection_data with a
135  * representation of the row at @path. @selection_data->target gives
136  * the required type of the data.  Should robustly handle a @path no
137  * longer found in the model!
138  * 
139  * Return value: %TRUE if data of the required type was provided 
140  **/
141 gboolean
142 gtk_tree_drag_source_drag_data_get    (GtkTreeDragSource *drag_source,
143                                        GtkTreePath       *path,
144                                        GtkSelectionData  *selection_data)
145 {
146   GtkTreeDragSourceIface *iface = GTK_TREE_DRAG_SOURCE_GET_IFACE (drag_source);
147
148   g_return_val_if_fail (iface->drag_data_get != NULL, FALSE);
149   g_return_val_if_fail (path != NULL, FALSE);
150   g_return_val_if_fail (selection_data != NULL, FALSE);
151
152   return (* iface->drag_data_get) (drag_source, path, selection_data);
153 }
154
155 /**
156  * gtk_tree_drag_dest_drag_data_received:
157  * @drag_dest: a #GtkTreeDragDest
158  * @dest: row to drop in front of
159  * @selection_data: data to drop
160  * 
161  * Asks the #GtkTreeDragDest to insert a row before the path @dest,
162  * deriving the contents of the row from @selection_data. If @dest is
163  * outside the tree so that inserting before it is impossible, %FALSE
164  * will be returned. Also, %FALSE may be returned if the new row is
165  * not created for some model-specific reason.  Should robustly handle
166  * a @dest no longer found in the model!
167  * 
168  * Return value: whether a new row was created before position @dest
169  **/
170 gboolean
171 gtk_tree_drag_dest_drag_data_received (GtkTreeDragDest  *drag_dest,
172                                        GtkTreePath      *dest,
173                                        GtkSelectionData *selection_data)
174 {
175   GtkTreeDragDestIface *iface = GTK_TREE_DRAG_DEST_GET_IFACE (drag_dest);
176
177   g_return_val_if_fail (iface->drag_data_received != NULL, FALSE);
178   g_return_val_if_fail (dest != NULL, FALSE);
179   g_return_val_if_fail (selection_data != NULL, FALSE);
180
181   return (* iface->drag_data_received) (drag_dest, dest, selection_data);
182 }
183
184
185 /**
186  * gtk_tree_drag_dest_drop_possible:
187  * @drag_dest: a #GtkTreeDragDest
188  * @dest_path: destination row
189  * @selection_data: the data being dragged
190  * 
191  * Determines whether a drop is possible before the given @dest_path,
192  * at the same depth as @dest_path. i.e., can we drop the data in
193  * @selection_data at that location. @dest_path does not have to
194  * exist; the return value will almost certainly be %FALSE if the
195  * parent of @dest_path doesn't exist, though.
196  * 
197  * Return value: %TRUE if a drop is possible before @dest_path
198  **/
199 gboolean
200 gtk_tree_drag_dest_row_drop_possible (GtkTreeDragDest   *drag_dest,
201                                       GtkTreePath       *dest_path,
202                                       GtkSelectionData  *selection_data)
203 {
204   GtkTreeDragDestIface *iface = GTK_TREE_DRAG_DEST_GET_IFACE (drag_dest);
205
206   g_return_val_if_fail (iface->row_drop_possible != NULL, FALSE);
207   g_return_val_if_fail (selection_data != NULL, FALSE);
208   g_return_val_if_fail (dest_path != NULL, FALSE);
209
210   return (* iface->row_drop_possible) (drag_dest, dest_path, selection_data);
211 }
212
213 typedef struct _TreeRowData TreeRowData;
214
215 struct _TreeRowData
216 {
217   GtkTreeModel *model;
218   gchar path[4];
219 };
220
221 /**
222  * gtk_tree_set_row_drag_data:
223  * @selection_data: some #GtkSelectionData
224  * @tree_model: a #GtkTreeModel
225  * @path: a row in @tree_model
226  * 
227  * Sets selection data of target type %GTK_TREE_MODEL_ROW. Normally used
228  * in a drag_data_get handler.
229  * 
230  * Return value: %TRUE if the #GtkSelectionData had the proper target type to allow us to set a tree row
231  **/
232 gboolean
233 gtk_tree_set_row_drag_data (GtkSelectionData *selection_data,
234                             GtkTreeModel     *tree_model,
235                             GtkTreePath      *path)
236 {
237   TreeRowData *trd;
238   gchar *path_str;
239   gint len;
240   gint struct_size;
241   
242   g_return_val_if_fail (selection_data != NULL, FALSE);
243   g_return_val_if_fail (GTK_IS_TREE_MODEL (tree_model), FALSE);
244   g_return_val_if_fail (path != NULL, FALSE);
245
246   if (selection_data->target != gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
247     return FALSE;
248   
249   path_str = gtk_tree_path_to_string (path);
250
251   len = strlen (path_str);
252
253   /* the old allocate-end-of-struct-to-hold-string trick */
254   struct_size = sizeof (TreeRowData) + len + 1 -
255     (sizeof (TreeRowData) - G_STRUCT_OFFSET (TreeRowData, path));
256
257   trd = g_malloc (struct_size); 
258
259   strcpy (trd->path, path_str);
260
261   g_free (path_str);
262   
263   trd->model = tree_model;
264   
265   gtk_selection_data_set (selection_data,
266                           gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE),
267                           8, /* bytes */
268                           (void*)trd,
269                           struct_size);
270
271   g_free (trd);
272   
273   return TRUE;
274 }
275
276 /**
277  * gtk_tree_get_row_drag_data:
278  * @selection_data: a #GtkSelectionData
279  * @tree_model: a #GtkTreeModel
280  * @path: row in @tree_model
281  * 
282  * Obtains a @tree_model and @path from selection data of target type
283  * %GTK_TREE_MODEL_ROW. Normally called from a drag_data_received handler.
284  * This function can only be used if @selection_data originates from the same
285  * process that's calling this function, because a pointer to the tree model
286  * is being passed around. If you aren't in the same process, then you'll
287  * get memory corruption. In the #GtkTreeDragDest drag_data_received handler,
288  * you can assume that selection data of type %GTK_TREE_MODEL_ROW is
289  * in from the current process. The returned path must be freed with
290  * gtk_tree_path_free().
291  * 
292  * Return value: %TRUE if @selection_data had target type %GTK_TREE_MODEL_ROW and
293  *  is otherwise valid
294  **/
295 gboolean
296 gtk_tree_get_row_drag_data (GtkSelectionData  *selection_data,
297                             GtkTreeModel     **tree_model,
298                             GtkTreePath      **path)
299 {
300   TreeRowData *trd;
301   
302   g_return_val_if_fail (selection_data != NULL, FALSE);  
303
304   if (tree_model)
305     *tree_model = NULL;
306
307   if (path)
308     *path = NULL;
309   
310   if (selection_data->target != gdk_atom_intern ("GTK_TREE_MODEL_ROW", FALSE))
311     return FALSE;
312
313   trd = (void*) selection_data->data;
314
315   if (tree_model)
316     *tree_model = trd->model;
317
318   if (path)
319     *path = gtk_tree_path_new_from_string (trd->path);
320   
321   return TRUE;
322 }