[gimp] Bug 589010 - Don't make Alt-Clicked layers active
- From: Martin Nordholts <martinn src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] Bug 589010 - Don't make Alt-Clicked layers active
- Date: Sun, 27 Jun 2010 19:41:03 +0000 (UTC)
commit 706900c4f6e9d669b7c8be2065decf49a9898620
Author: Martin Nordholts <martinn src gnome org>
Date: Sun Jun 27 21:44:29 2010 +0200
Bug 589010 - Don't make Alt-Clicked layers active
Add a "pre-clicked" signal to GimpCellRendererViewable that can
prevent a selection from happening. Move the Alt-Click code in
GimpLayerTreeView to this signal and if a layer is Alt-Clicked, don't
go ahead and make the layer active. Also add a test for this use case.
app/core/gimpmarshal.list | 1 +
app/tests/test-ui.c | 61 ++++++++++----
app/widgets/gimpcellrendererviewable.c | 53 ++++++++++++
app/widgets/gimpcellrendererviewable.h | 22 +++--
app/widgets/gimpcontainertreeview.c | 13 +++-
app/widgets/gimplayertreeview.c | 138 +++++++++++++++++++-------------
6 files changed, 206 insertions(+), 82 deletions(-)
---
diff --git a/app/core/gimpmarshal.list b/app/core/gimpmarshal.list
index 7f97ddb..104cfa1 100644
--- a/app/core/gimpmarshal.list
+++ b/app/core/gimpmarshal.list
@@ -27,6 +27,7 @@ BOOLEAN: ENUM, INT
BOOLEAN: OBJECT, POINTER
BOOLEAN: OBJECT, POINTER, STRING
BOOLEAN: STRING
+BOOLEAN: STRING, FLAGS
VOID: BOOLEAN
VOID: BOOLEAN, INT, INT, INT, INT
diff --git a/app/tests/test-ui.c b/app/tests/test-ui.c
index 9a4259b..bdd2bc2 100644
--- a/app/tests/test-ui.c
+++ b/app/tests/test-ui.c
@@ -358,7 +358,8 @@ keyboard_zoom_focus (GimpTestFixture *fixture,
* @data:
*
* Makes sure that we can alt-click on a layer to do
- * layer-to-selection.
+ * layer-to-selection. Also makes sure that the layer clicked on is
+ * not set as the active layer.
**/
static void
alt_click_is_layer_to_selection (GimpTestFixture *fixture,
@@ -367,46 +368,74 @@ alt_click_is_layer_to_selection (GimpTestFixture *fixture,
Gimp *gimp = GIMP (data);
GimpImage *image = GIMP_IMAGE (gimp_get_image_iter (gimp)->data);
GimpChannel *selection = gimp_image_get_mask (image);
+ GimpLayer *active_layer;
GtkWidget *dockable;
GtkWidget *gtk_tree_view;
gint assumed_layer_x;
- gint assumed_layer_y;
+ gint assumed_empty_layer_y;
+ gint assumed_background_layer_y;
- /* Hardcode an assumption of where the layer is in the
+ /* Hardcode assumptions of where the layers are in the
* GtkTreeView. Doesn't feel worth adding proper API for this. One
* can just use GIMP_PAUSE and re-measure new coordinates if we
* start to layout layers in the GtkTreeView differently
*/
- assumed_layer_x = 96;
- assumed_layer_y = 42;
+ assumed_layer_x = 96;
+ assumed_empty_layer_y = 16;
+ assumed_background_layer_y = 42;
- /* First make sure there is no selection */
- g_assert (! gimp_channel_bounds (selection,
- NULL, NULL, /*x1, y1*/
- NULL, NULL /*x2, y2*/));
+ /* Store the active layer, it shall not change during the execution
+ * of this test
+ */
+ active_layer = gimp_image_get_active_layer (image);
- /* Now simulate alt-click on a layer after finding the GtkTreeView
- * that shows layers. Note that there is a potential problem with
- * gtk_test_find_widget and GtkNotebook: it will return e.g. a
- * GtkTreeView from another page if that page is "on top" of the
- * reference label.
+ /* Find the layer tree view to click in. Note that there is a
+ * potential problem with gtk_test_find_widget and GtkNotebook: it
+ * will return e.g. a GtkTreeView from another page if that page is
+ * "on top" of the reference label.
*/
dockable = gimp_ui_find_window (gimp_dialog_factory_get_singleton (),
gimp_ui_is_gimp_layer_list);
gtk_tree_view = gtk_test_find_widget (dockable,
"Lock:",
GTK_TYPE_TREE_VIEW);
+
+ /* First make sure there is no selection */
+ g_assert (! gimp_channel_bounds (selection,
+ NULL, NULL, /*x1, y1*/
+ NULL, NULL /*x2, y2*/));
+
+ /* Now simulate alt-click on the background layer */
g_assert (gimp_ui_synthesize_click (gtk_tree_view,
assumed_layer_x,
- assumed_layer_y,
+ assumed_background_layer_y,
1 /*button*/,
GDK_MOD1_MASK));
gimp_test_run_mainloop_until_idle ();
- /* Make sure we got a selection */
+ /* Make sure we got a selection and that the active layer didn't
+ * change
+ */
g_assert (gimp_channel_bounds (selection,
NULL, NULL, /*x1, y1*/
NULL, NULL /*x2, y2*/));
+ g_assert (gimp_image_get_active_layer (image) == active_layer);
+
+ /* Now simulate alt-click on the empty layer */
+ g_assert (gimp_ui_synthesize_click (gtk_tree_view,
+ assumed_layer_x,
+ assumed_empty_layer_y,
+ 1 /*button*/,
+ GDK_MOD1_MASK));
+ gimp_test_run_mainloop_until_idle ();
+
+ /* Make sure that emptied the selection and that the active layer
+ * still didn't change
+ */
+ g_assert (! gimp_channel_bounds (selection,
+ NULL, NULL, /*x1, y1*/
+ NULL, NULL /*x2, y2*/));
+ g_assert (gimp_image_get_active_layer (image) == active_layer);
}
static void
diff --git a/app/widgets/gimpcellrendererviewable.c b/app/widgets/gimpcellrendererviewable.c
index 1f74a62..67e8e24 100644
--- a/app/widgets/gimpcellrendererviewable.c
+++ b/app/widgets/gimpcellrendererviewable.c
@@ -34,6 +34,7 @@
enum
{
+ PRE_CLICKED,
CLICKED,
LAST_SIGNAL
};
@@ -91,6 +92,39 @@ gimp_cell_renderer_viewable_class_init (GimpCellRendererViewableClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkCellRendererClass *cell_class = GTK_CELL_RENDERER_CLASS (klass);
+ /**
+ * GimpCellRendererViewable::pre-clicked:
+ * @cell:
+ * @path:
+ * @state:
+ *
+ * Called early on a viewable cell when it is clicked, typically
+ * before selection code is invoked for example.
+ *
+ * Returns: %TRUE if the signal handled the event and event
+ * propagation should stop, for example preventing a
+ * selection from happening, %FALSE to continue as normal
+ **/
+ viewable_cell_signals[PRE_CLICKED] =
+ g_signal_new ("pre-clicked",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GimpCellRendererViewableClass, pre_clicked),
+ g_signal_accumulator_true_handled, NULL,
+ gimp_marshal_BOOLEAN__STRING_FLAGS,
+ G_TYPE_BOOLEAN, 2,
+ G_TYPE_STRING,
+ GDK_TYPE_MODIFIER_TYPE);
+
+ /**
+ * GimpCellRendererViewable::clicked:
+ * @cell:
+ * @path:
+ * @state:
+ *
+ * Called late on a viewable cell when it is clicked, typically
+ * after selection code has been invoked for example.
+ **/
viewable_cell_signals[CLICKED] =
g_signal_new ("clicked",
G_OBJECT_CLASS_TYPE (object_class),
@@ -315,6 +349,25 @@ gimp_cell_renderer_viewable_new (void)
return g_object_new (GIMP_TYPE_CELL_RENDERER_VIEWABLE, NULL);
}
+gboolean
+gimp_cell_renderer_viewable_pre_clicked (GimpCellRendererViewable *cell,
+ const gchar *path,
+ GdkModifierType state)
+{
+ gboolean handled = FALSE;
+
+ g_return_val_if_fail (GIMP_IS_CELL_RENDERER_VIEWABLE (cell), FALSE);
+ g_return_val_if_fail (path != NULL, FALSE);
+
+ g_signal_emit (cell,
+ viewable_cell_signals[PRE_CLICKED],
+ 0 /*detail*/,
+ path, state,
+ &handled);
+
+ return handled;
+}
+
void
gimp_cell_renderer_viewable_clicked (GimpCellRendererViewable *cell,
const gchar *path,
diff --git a/app/widgets/gimpcellrendererviewable.h b/app/widgets/gimpcellrendererviewable.h
index 0d9b37d..5f43579 100644
--- a/app/widgets/gimpcellrendererviewable.h
+++ b/app/widgets/gimpcellrendererviewable.h
@@ -43,17 +43,23 @@ struct _GimpCellRendererViewableClass
{
GtkCellRendererClass parent_class;
- void (* clicked) (GimpCellRendererViewable *cell,
- const gchar *path,
- GdkModifierType state);
+ gboolean (* pre_clicked) (GimpCellRendererViewable *cell,
+ const gchar *path,
+ GdkModifierType state);
+ void (* clicked) (GimpCellRendererViewable *cell,
+ const gchar *path,
+ GdkModifierType state);
};
-GType gimp_cell_renderer_viewable_get_type (void) G_GNUC_CONST;
-GtkCellRenderer * gimp_cell_renderer_viewable_new (void);
-void gimp_cell_renderer_viewable_clicked (GimpCellRendererViewable *cell,
- const gchar *path,
- GdkModifierType state);
+GType gimp_cell_renderer_viewable_get_type (void) G_GNUC_CONST;
+GtkCellRenderer * gimp_cell_renderer_viewable_new (void);
+gboolean gimp_cell_renderer_viewable_pre_clicked (GimpCellRendererViewable *cell,
+ const gchar *path,
+ GdkModifierType state);
+void gimp_cell_renderer_viewable_clicked (GimpCellRendererViewable *cell,
+ const gchar *path,
+ GdkModifierType state);
#endif /* __GIMP_CELL_RENDERER_VIEWABLE_H__ */
diff --git a/app/widgets/gimpcontainertreeview.c b/app/widgets/gimpcontainertreeview.c
index 30c50b3..1920b11 100644
--- a/app/widgets/gimpcontainertreeview.c
+++ b/app/widgets/gimpcontainertreeview.c
@@ -950,16 +950,25 @@ gimp_container_tree_view_button_press (GtkWidget *widget,
/* don't select item if a toggle was clicked */
if (! toggled_cell)
{
- if (multisel_mode)
+ gchar *path_str = gtk_tree_path_to_string (path);
+
+ handled =
+ gimp_cell_renderer_viewable_pre_clicked (clicked_cell,
+ path_str,
+ bevent->state);
+
+ if (! handled && multisel_mode)
{
/* let parent do the work */
handled = FALSE;
}
- else
+ else if (! handled)
{
handled = gimp_container_view_item_selected (container_view,
renderer->viewable);
}
+
+ g_free (path_str);
}
/* a callback invoked by selecting the item may have
diff --git a/app/widgets/gimplayertreeview.c b/app/widgets/gimplayertreeview.c
index 9591c7b..2e2a26e 100644
--- a/app/widgets/gimplayertreeview.c
+++ b/app/widgets/gimplayertreeview.c
@@ -152,6 +152,10 @@ static void gimp_layer_tree_view_update_borders (GimpLayerTree
GtkTreeIter *iter);
static void gimp_layer_tree_view_mask_callback (GimpLayerMask *mask,
GimpLayerTreeView *view);
+static gboolean gimp_layer_tree_view_layer_pre_clicked (GimpCellRendererViewable *cell,
+ const gchar *path_str,
+ GdkModifierType state,
+ GimpLayerTreeView *layer_view);
static void gimp_layer_tree_view_layer_clicked (GimpCellRendererViewable *cell,
const gchar *path,
GdkModifierType state,
@@ -363,6 +367,9 @@ gimp_layer_tree_view_constructor (GType type,
gimp_container_tree_view_add_renderer_cell (tree_view,
layer_view->priv->mask_cell);
+ g_signal_connect (tree_view->renderer_cell, "pre-clicked",
+ G_CALLBACK (gimp_layer_tree_view_layer_pre_clicked),
+ layer_view);
g_signal_connect (tree_view->renderer_cell, "clicked",
G_CALLBACK (gimp_layer_tree_view_layer_clicked),
layer_view);
@@ -1300,6 +1307,69 @@ gimp_layer_tree_view_mask_callback (GimpLayerMask *mask,
gimp_layer_tree_view_update_borders (layer_view, iter);
}
+static gboolean
+gimp_layer_tree_view_layer_pre_clicked (GimpCellRendererViewable *cell,
+ const gchar *path_str,
+ GdkModifierType state,
+ GimpLayerTreeView *layer_view)
+{
+ GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (layer_view);
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ gboolean handled = FALSE;
+
+ path = gtk_tree_path_new_from_string (path_str);
+
+ if (gtk_tree_model_get_iter (tree_view->model, &iter, path) &&
+ state & GDK_MOD1_MASK)
+ {
+ GimpItemTreeView *item_view = GIMP_ITEM_TREE_VIEW (tree_view);
+ GimpImage *image = gimp_item_tree_view_get_image (item_view);
+ GimpViewRenderer *layer_renderer = NULL;
+ GimpDrawable *layer = NULL;
+ GimpChannelOps op;
+
+ gtk_tree_model_get (tree_view->model, &iter,
+ GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &layer_renderer,
+ -1);
+
+ if (layer_renderer)
+ layer = GIMP_DRAWABLE (layer_renderer->viewable);
+
+ op = GIMP_CHANNEL_OP_REPLACE;
+
+ if ((state & GDK_SHIFT_MASK) && (state & GDK_CONTROL_MASK))
+ {
+ op = GIMP_CHANNEL_OP_INTERSECT;
+ }
+ else if (state & GDK_SHIFT_MASK)
+ {
+ op = GIMP_CHANNEL_OP_ADD;
+ }
+ else if (state & GDK_CONTROL_MASK)
+ {
+ op = GIMP_CHANNEL_OP_SUBTRACT;
+ }
+
+ gimp_channel_select_alpha (gimp_image_get_mask (image),
+ layer,
+ op,
+ FALSE /*feather*/,
+ 0.0, 0.0 /*feather_radius_x,y*/);
+ gimp_image_flush (image);
+
+ if (layer_renderer)
+ g_object_unref (layer_renderer);
+
+ /* Don't select the clicked layer */
+ handled = TRUE;
+ }
+
+ gtk_tree_path_free (path);
+
+ return handled;
+}
+
static void
gimp_layer_tree_view_layer_clicked (GimpCellRendererViewable *cell,
const gchar *path_str,
@@ -1314,69 +1384,25 @@ gimp_layer_tree_view_layer_clicked (GimpCellRendererViewable *cell,
if (gtk_tree_model_get_iter (tree_view->model, &iter, path))
{
- GimpUIManager *ui_manager = GIMP_EDITOR (tree_view)->ui_manager;
- GimpActionGroup *group;
+ GimpUIManager *ui_manager = GIMP_EDITOR (tree_view)->ui_manager;
+ GimpActionGroup *group;
+ GimpViewRenderer *renderer;
group = gimp_ui_manager_get_action_group (ui_manager, "layers");
- if (state & GDK_MOD1_MASK)
- {
- GimpItemTreeView *item_view = GIMP_ITEM_TREE_VIEW (tree_view);
- GimpImage *image = gimp_item_tree_view_get_image (item_view);
- GimpViewRenderer *layer_renderer = NULL;
- GimpDrawable *layer = NULL;
- GimpChannelOps op;
-
- gtk_tree_model_get (tree_view->model, &iter,
- GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &layer_renderer,
- -1);
-
- if (layer_renderer)
- layer = GIMP_DRAWABLE (layer_renderer->viewable);
-
- op = GIMP_CHANNEL_OP_REPLACE;
-
- if ((state & GDK_SHIFT_MASK) && (state & GDK_CONTROL_MASK))
- {
- op = GIMP_CHANNEL_OP_INTERSECT;
- }
- else if (state & GDK_SHIFT_MASK)
- {
- op = GIMP_CHANNEL_OP_ADD;
- }
- else if (state & GDK_CONTROL_MASK)
- {
- op = GIMP_CHANNEL_OP_SUBTRACT;
- }
-
- gimp_channel_select_alpha (gimp_image_get_mask (image),
- layer,
- op,
- FALSE /*feather*/,
- 0.0, 0.0 /*feather_radius_x,y*/);
- gimp_image_flush (image);
+ gtk_tree_model_get (tree_view->model, &iter,
+ layer_view->priv->model_column_mask, &renderer,
+ -1);
- if (layer_renderer)
- g_object_unref (layer_renderer);
- }
- else
+ if (renderer)
{
- GimpViewRenderer *renderer;
-
- gtk_tree_model_get (tree_view->model, &iter,
- layer_view->priv->model_column_mask, &renderer,
- -1);
-
- if (renderer)
- {
- GimpLayerMask *mask = GIMP_LAYER_MASK (renderer->viewable);
+ GimpLayerMask *mask = GIMP_LAYER_MASK (renderer->viewable);
- if (gimp_layer_mask_get_edit (mask))
- gimp_action_group_set_action_active (group,
- "layers-mask-edit", FALSE);
+ if (gimp_layer_mask_get_edit (mask))
+ gimp_action_group_set_action_active (group,
+ "layers-mask-edit", FALSE);
- g_object_unref (renderer);
- }
+ g_object_unref (renderer);
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]