Author: benny
Date: 2006-08-09 15:03:06 +0000 (Wed, 09 Aug 2006)
New Revision: 22695
Modified:
libexo/trunk/ChangeLog
libexo/trunk/exo/exo-tree-view.c
Log:
2006-08-09 Benedikt Meurer <[EMAIL PROTECTED]>
* exo/exo-tree-view.c: Add support for rubberband selection in the
ExoTreeView class. Bug #1996.
Modified: libexo/trunk/ChangeLog
===================================================================
--- libexo/trunk/ChangeLog 2006-08-09 12:01:02 UTC (rev 22694)
+++ libexo/trunk/ChangeLog 2006-08-09 15:03:06 UTC (rev 22695)
@@ -1,3 +1,8 @@
+2006-08-09 Benedikt Meurer <[EMAIL PROTECTED]>
+
+ * exo/exo-tree-view.c: Add support for rubberband selection in the
+ ExoTreeView class. Bug #1996.
+
2006-08-07 Benedikt Meurer <[EMAIL PROTECTED]>
* exo-desktop-item-edit/exo-die-desktop-model.c
Modified: libexo/trunk/exo/exo-tree-view.c
===================================================================
--- libexo/trunk/exo/exo-tree-view.c 2006-08-09 12:01:02 UTC (rev 22694)
+++ libexo/trunk/exo/exo-tree-view.c 2006-08-09 15:03:06 UTC (rev 22695)
@@ -79,6 +79,12 @@
/* whether the next button-release-event should emit "row-activate" */
guint button_release_activates : 1;
+ /* whether drag and drop must be re-enabled on button-release-event
(rubberbanding active) */
+ guint button_release_unblocks_dnd : 1;
+
+ /* whether rubberbanding must be re-enabled on button-release-event (drag
and drop active) */
+ guint button_release_enables_rubber_banding : 1;
+
/* single click mode */
guint single_click : 1;
guint single_click_timeout;
@@ -327,6 +333,43 @@
selected_paths = gtk_tree_selection_get_selected_rows (selection,
NULL);
}
+#if GTK_CHECK_VERSION(2,9,0)
+ /* Rubberbanding in GtkTreeView 2.9.0 and above is rather buggy,
unfortunately, and
+ * doesn't interact properly with GTKs own DnD mechanism. So we need to
block all
+ * dragging here when pressing the mouse button on a not yet selected row if
+ * rubberbanding is active, or disable rubberbanding when starting a drag.
+ */
+ if (gtk_tree_selection_get_mode (selection) == GTK_SELECTION_MULTIPLE
+ && gtk_tree_view_get_rubber_banding (GTK_TREE_VIEW (tree_view))
+ && event->button == 1 && event->type == GDK_BUTTON_PRESS)
+ {
+ /* check if clicked on empty area or on a not yet selected row */
+ if (G_LIKELY (path == NULL || !gtk_tree_selection_path_is_selected
(selection, path)))
+ {
+ /* need to disable drag and drop because we're rubberbanding now */
+ gpointer drag_data = g_object_get_data (G_OBJECT (tree_view),
I_("gtk-site-data"));
+ if (G_LIKELY (drag_data != NULL))
+ {
+ g_signal_handlers_block_matched (G_OBJECT (tree_view),
+ G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL,
+ drag_data);
+ }
+
+ /* remember to re-enable drag and drop later */
+ tree_view->priv->button_release_unblocks_dnd = TRUE;
+ }
+ else
+ {
+ /* need to disable rubberbanding because we're dragging now */
+ gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (tree_view), FALSE);
+
+ /* remember to re-enable rubberbanding later */
+ tree_view->priv->button_release_enables_rubber_banding = TRUE;
+ }
+ }
+#endif
+
/* call the parent's button press handler */
result = (*GTK_WIDGET_CLASS
(exo_tree_view_parent_class)->button_press_event) (widget, event);
@@ -391,7 +434,7 @@
gtk_tree_path_free (path);
}
}
- else if ((event->state & gtk_accelerator_get_default_mod_mask ()) == 0)
+ else if ((event->state & gtk_accelerator_get_default_mod_mask ()) == 0
&& !tree_view->priv->button_release_unblocks_dnd)
{
/* determine the path on which the button was released and select
only this row, this way
* the user is still able to alter the selection easily if all rows
are selected.
@@ -415,6 +458,29 @@
}
}
+#if GTK_CHECK_VERSION(2,9,0)
+ /* check if we need to re-enable drag and drop */
+ if (G_LIKELY (tree_view->priv->button_release_unblocks_dnd))
+ {
+ gpointer drag_data = g_object_get_data (G_OBJECT (tree_view),
I_("gtk-site-data"));
+ if (G_LIKELY (drag_data != NULL))
+ {
+ g_signal_handlers_unblock_matched (G_OBJECT (tree_view),
+ G_SIGNAL_MATCH_DATA,
+ 0, 0, NULL, NULL,
+ drag_data);
+ }
+ tree_view->priv->button_release_unblocks_dnd = FALSE;
+ }
+
+ /* check if we need to re-enable rubberbanding */
+ if (G_UNLIKELY (tree_view->priv->button_release_enables_rubber_banding))
+ {
+ gtk_tree_view_set_rubber_banding (GTK_TREE_VIEW (tree_view), TRUE);
+ tree_view->priv->button_release_enables_rubber_banding = FALSE;
+ }
+#endif
+
/* call the parent's button release handler */
return (*GTK_WIDGET_CLASS
(exo_tree_view_parent_class)->button_release_event) (widget, event);
}
@@ -432,57 +498,71 @@
/* check if the event occurred on the tree view internal window and we are
in single-click mode */
if (event->window == gtk_tree_view_get_bin_window (GTK_TREE_VIEW
(tree_view)) && tree_view->priv->single_click)
{
- /* determine the path at the event coordinates */
- if (!gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (tree_view), event->x,
event->y, &path, NULL, NULL, NULL))
- path = NULL;
+#if GTK_CHECK_VERSION(2,9,0)
+ /* check if we're doing a rubberband selection right now (which means
DnD is blocked) */
+ if (G_UNLIKELY (tree_view->priv->button_release_unblocks_dnd))
+ {
+ /* we're doing a rubberband selection, so don't activate anything */
+ tree_view->priv->button_release_activates = FALSE;
- /* check if we have a new path */
- if ((path == NULL && tree_view->priv->hover_path != NULL) || (path !=
NULL && tree_view->priv->hover_path == NULL)
- || (path != NULL && tree_view->priv->hover_path != NULL &&
gtk_tree_path_compare (path, tree_view->priv->hover_path) != 0))
+ /* also be sure to reset the cursor */
+ gdk_window_set_cursor (event->window, NULL);
+ }
+ else
+#endif
{
- /* release the previous hover path */
- if (tree_view->priv->hover_path != NULL)
- gtk_tree_path_free (tree_view->priv->hover_path);
+ /* determine the path at the event coordinates */
+ if (!gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (tree_view),
event->x, event->y, &path, NULL, NULL, NULL))
+ path = NULL;
- /* setup the new path */
- tree_view->priv->hover_path = path;
+ /* check if we have a new path */
+ if ((path == NULL && tree_view->priv->hover_path != NULL) || (path
!= NULL && tree_view->priv->hover_path == NULL)
+ || (path != NULL && tree_view->priv->hover_path != NULL &&
gtk_tree_path_compare (path, tree_view->priv->hover_path) != 0))
+ {
+ /* release the previous hover path */
+ if (tree_view->priv->hover_path != NULL)
+ gtk_tree_path_free (tree_view->priv->hover_path);
- /* check if we're over a row right now */
- if (G_LIKELY (path != NULL))
- {
- /* setup the hand cursor to indicate that the row at the pointer
can be activated with a single click */
- cursor = gdk_cursor_new (GDK_HAND2);
- gdk_window_set_cursor (event->window, cursor);
- gdk_cursor_unref (cursor);
+ /* setup the new path */
+ tree_view->priv->hover_path = path;
+
+ /* check if we're over a row right now */
+ if (G_LIKELY (path != NULL))
+ {
+ /* setup the hand cursor to indicate that the row at the
pointer can be activated with a single click */
+ cursor = gdk_cursor_new (GDK_HAND2);
+ gdk_window_set_cursor (event->window, cursor);
+ gdk_cursor_unref (cursor);
+ }
+ else
+ {
+ /* reset the cursor to its default */
+ gdk_window_set_cursor (event->window, NULL);
+ }
+
+ /* check if autoselection is enabled and the pointer is over a
row */
+ if (G_LIKELY (tree_view->priv->single_click_timeout > 0 &&
tree_view->priv->hover_path != NULL))
+ {
+ /* cancel any previous single-click timeout */
+ if (G_LIKELY (tree_view->priv->single_click_timeout_id >= 0))
+ g_source_remove (tree_view->priv->single_click_timeout_id);
+
+ /* remember the current event state */
+ tree_view->priv->single_click_timeout_state = event->state;
+
+ /* schedule a new single-click timeout */
+ tree_view->priv->single_click_timeout_id =
g_timeout_add_full (G_PRIORITY_LOW, tree_view->priv->single_click_timeout,
+
exo_tree_view_single_click_timeout, tree_view,
+
exo_tree_view_single_click_timeout_destroy);
+ }
}
else
{
- /* reset the cursor to its default */
- gdk_window_set_cursor (event->window, NULL);
+ /* release the path resources */
+ if (path != NULL)
+ gtk_tree_path_free (path);
}
-
- /* check if autoselection is enabled and the pointer is over a row */
- if (G_LIKELY (tree_view->priv->single_click_timeout > 0 &&
tree_view->priv->hover_path != NULL))
- {
- /* cancel any previous single-click timeout */
- if (G_LIKELY (tree_view->priv->single_click_timeout_id >= 0))
- g_source_remove (tree_view->priv->single_click_timeout_id);
-
- /* remember the current event state */
- tree_view->priv->single_click_timeout_state = event->state;
-
- /* schedule a new single-click timeout */
- tree_view->priv->single_click_timeout_id = g_timeout_add_full
(G_PRIORITY_LOW, tree_view->priv->single_click_timeout,
-
exo_tree_view_single_click_timeout, tree_view,
-
exo_tree_view_single_click_timeout_destroy);
- }
}
- else
- {
- /* release the path resources */
- if (path != NULL)
- gtk_tree_path_free (path);
- }
}
/* call the parent's motion notify handler */
_______________________________________________
Xfce4-commits mailing list
[email protected]
http://foo-projects.org/mailman/listinfo/xfce4-commits