[gimp] app: Add support for multiple items selection
- From: Aurimas Juška <aurisj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: Add support for multiple items selection
- Date: Sun, 7 Mar 2010 17:02:00 +0000 (UTC)
commit ebe9e51b62a61d903d2ecc908c469d45b7fd3e83
Author: Aurimas Juška <aurimas juska gmail com>
Date: Sun Mar 7 18:54:20 2010 +0200
app: Add support for multiple items selection
Implemented infrastructure for multiple selection support.
GimpContainerTreeView actually provides such functionality.
All other GimpContainerViews should work as before.
app/actions/actions.c | 16 ++++
app/actions/actions.h | 1 +
app/actions/brushes-actions.c | 5 ++
app/actions/gradients-actions.c | 5 ++
app/actions/palettes-actions.c | 5 ++
app/actions/patterns-actions.c | 5 ++
app/widgets/gimpcontainertreeview.c | 136 ++++++++++++++++++++++++++++-------
app/widgets/gimpcontainerview.c | 76 +++++++++++++++++++
app/widgets/gimpcontainerview.h | 9 ++-
9 files changed, 229 insertions(+), 29 deletions(-)
---
diff --git a/app/actions/actions.c b/app/actions/actions.c
index 3e39eef..0040bcf 100644
--- a/app/actions/actions.c
+++ b/app/actions/actions.c
@@ -431,6 +431,22 @@ action_data_get_widget (gpointer data)
return dialogs_get_toolbox ();
}
+gint
+action_data_sel_count (gpointer data)
+{
+ if (GIMP_IS_CONTAINER_EDITOR (data))
+ {
+ GimpContainerEditor *editor;
+
+ editor = GIMP_CONTAINER_EDITOR (data);
+ return gimp_container_view_get_selected (editor->view, NULL);
+ }
+ else
+ {
+ return 0;
+ }
+}
+
gdouble
action_select_value (GimpActionSelectType select_type,
gdouble value,
diff --git a/app/actions/actions.h b/app/actions/actions.h
index 6db2db3..8a9c354 100644
--- a/app/actions/actions.h
+++ b/app/actions/actions.h
@@ -31,6 +31,7 @@ GimpImage * action_data_get_image (gpointer data);
GimpDisplay * action_data_get_display (gpointer data);
GimpDisplayShell * action_data_get_shell (gpointer data);
GtkWidget * action_data_get_widget (gpointer data);
+gint action_data_sel_count (gpointer data);
gdouble action_select_value (GimpActionSelectType select_type,
gdouble value,
diff --git a/app/actions/brushes-actions.c b/app/actions/brushes-actions.c
index d5b9c39..97d4d43 100644
--- a/app/actions/brushes-actions.c
+++ b/app/actions/brushes-actions.c
@@ -115,6 +115,11 @@ brushes_actions_update (GimpActionGroup *group,
{
brush = gimp_context_get_brush (context);
+ if (action_data_sel_count (user_data) > 1)
+ {
+ brush = NULL;
+ }
+
if (brush)
{
data = GIMP_DATA (brush);
diff --git a/app/actions/gradients-actions.c b/app/actions/gradients-actions.c
index a990190..98833bb 100644
--- a/app/actions/gradients-actions.c
+++ b/app/actions/gradients-actions.c
@@ -116,6 +116,11 @@ gradients_actions_update (GimpActionGroup *group,
{
gradient = gimp_context_get_gradient (context);
+ if (action_data_sel_count (user_data) > 1)
+ {
+ gradient = NULL;
+ }
+
if (gradient)
{
data = GIMP_DATA (gradient);
diff --git a/app/actions/palettes-actions.c b/app/actions/palettes-actions.c
index 4a46acb..3f6eb21 100644
--- a/app/actions/palettes-actions.c
+++ b/app/actions/palettes-actions.c
@@ -122,6 +122,11 @@ palettes_actions_update (GimpActionGroup *group,
{
palette = gimp_context_get_palette (context);
+ if (action_data_sel_count (user_data) > 1)
+ {
+ palette = NULL;
+ }
+
if (palette)
{
data = GIMP_DATA (palette);
diff --git a/app/actions/patterns-actions.c b/app/actions/patterns-actions.c
index 87ed336..3f16ac6 100644
--- a/app/actions/patterns-actions.c
+++ b/app/actions/patterns-actions.c
@@ -115,6 +115,11 @@ patterns_actions_update (GimpActionGroup *group,
{
pattern = gimp_context_get_pattern (context);
+ if (action_data_sel_count (user_data) > 1)
+ {
+ pattern = NULL;
+ }
+
if (pattern)
{
data = GIMP_DATA (pattern);
diff --git a/app/widgets/gimpcontainertreeview.c b/app/widgets/gimpcontainertreeview.c
index 8ee76ac..6e56b51 100644
--- a/app/widgets/gimpcontainertreeview.c
+++ b/app/widgets/gimpcontainertreeview.c
@@ -99,6 +99,11 @@ static GimpViewable *gimp_container_tree_view_drag_viewable (GtkWidget
static GdkPixbuf *gimp_container_tree_view_drag_pixbuf (GtkWidget *widget,
gpointer data);
+static gboolean gimp_container_tree_view_get_selected_single (GimpContainerTreeView *tree_view,
+ GtkTreeIter *iter);
+static gint gimp_container_tree_view_get_selected (GimpContainerView *view,
+ GList **items);
+
G_DEFINE_TYPE_WITH_CODE (GimpContainerTreeView, gimp_container_tree_view,
GIMP_TYPE_CONTAINER_BOX,
@@ -147,6 +152,7 @@ gimp_container_tree_view_view_iface_init (GimpContainerViewInterface *iface)
iface->select_item = gimp_container_tree_view_select_item;
iface->clear_items = gimp_container_tree_view_clear_items;
iface->set_view_size = gimp_container_tree_view_set_view_size;
+ iface->get_selected = gimp_container_tree_view_get_selected;
iface->insert_data_free = (GDestroyNotify) gtk_tree_iter_free;
}
@@ -249,6 +255,9 @@ gimp_container_tree_view_constructor (GType type,
tree_view->priv->selection = gtk_tree_view_get_selection (tree_view->view);
+ gtk_tree_selection_set_mode (tree_view->priv->selection,
+ GTK_SELECTION_MULTIPLE);
+
g_signal_connect (tree_view->priv->selection, "changed",
G_CALLBACK (gimp_container_tree_view_selection_changed),
tree_view);
@@ -334,8 +343,7 @@ gimp_container_tree_view_menu_position (GtkMenu *menu,
*y += allocation.y;
}
- if (gtk_tree_selection_get_selected (tree_view->priv->selection, NULL,
- &selected_iter))
+ if (gimp_container_tree_view_get_selected_single (tree_view, &selected_iter))
{
GtkTreePath *path;
GdkRectangle cell_rect;
@@ -680,8 +688,8 @@ gimp_container_tree_view_reorder_item (GimpContainerView *view,
else
container = gimp_container_view_get_container (view);
- selected = gtk_tree_selection_get_selected (tree_view->priv->selection,
- NULL, &selected_iter);
+ selected = gimp_container_tree_view_get_selected_single (tree_view,
+ &selected_iter);
if (selected)
{
@@ -780,11 +788,11 @@ gimp_container_tree_view_select_item (GimpContainerView *view,
gpointer insert_data)
{
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
- GtkTreeIter *iter = (GtkTreeIter *) insert_data;
- if (iter)
+ if (viewable && insert_data)
{
GtkTreePath *path;
+ GtkTreeIter *iter = (GtkTreeIter *) insert_data;
path = gtk_tree_model_get_path (tree_view->model, iter);
@@ -803,8 +811,10 @@ gimp_container_tree_view_select_item (GimpContainerView *view,
gtk_tree_path_free (path);
}
- else
+ else if (insert_data == NULL)
{
+ /* viewable == NULL && insert_data != NULL means multiple selection.
+ * viewable == NULL && insert_data == NULL means no selection. */
gtk_tree_selection_unselect_all (tree_view->priv->selection);
}
@@ -922,7 +932,7 @@ gimp_container_tree_view_name_canceled (GtkCellRendererText *cell,
{
GtkTreeIter iter;
- if (gtk_tree_selection_get_selected (tree_view->priv->selection, NULL, &iter))
+ if (gimp_container_tree_view_get_selected_single (tree_view, &iter))
{
GimpViewRenderer *renderer;
gchar *name;
@@ -946,20 +956,12 @@ static void
gimp_container_tree_view_selection_changed (GtkTreeSelection *selection,
GimpContainerTreeView *tree_view)
{
- GtkTreeIter iter;
+ GimpContainerView *view = GIMP_CONTAINER_VIEW (tree_view);
+ GList *items;
- if (gtk_tree_selection_get_selected (selection, NULL, &iter))
- {
- GimpViewRenderer *renderer;
-
- gtk_tree_model_get (tree_view->model, &iter,
- GIMP_CONTAINER_TREE_VIEW_COLUMN_RENDERER, &renderer,
- -1);
-
- gimp_container_view_item_selected (GIMP_CONTAINER_VIEW (tree_view),
- renderer->viewable);
- g_object_unref (renderer);
- }
+ gimp_container_tree_view_get_selected (view, &items);
+ gimp_container_view_multi_selected (view, items);
+ g_list_free (items);
}
static GtkCellRenderer *
@@ -1028,6 +1030,7 @@ gimp_container_tree_view_button_press (GtkWidget *widget,
GtkCellRenderer *edit_cell = NULL;
GdkRectangle column_area;
GtkTreeIter iter;
+ gboolean handled = TRUE;
gtk_tree_model_get_iter (tree_view->model, &iter, path);
@@ -1100,12 +1103,9 @@ gimp_container_tree_view_button_press (GtkWidget *widget,
case 1:
if (bevent->type == GDK_BUTTON_PRESS)
{
- gboolean success = TRUE;
-
/* don't select item if a toggle was clicked */
if (! toggled_cell)
- success = gimp_container_view_item_selected (container_view,
- renderer->viewable);
+ handled = FALSE;
/* a callback invoked by selecting the item may have
* destroyed us, so check if the container is still there
@@ -1217,6 +1217,8 @@ gimp_container_tree_view_button_press (GtkWidget *widget,
gtk_tree_path_free (path);
g_object_unref (renderer);
+
+ return handled;
}
else
{
@@ -1229,9 +1231,9 @@ gimp_container_tree_view_button_press (GtkWidget *widget,
default:
break;
}
- }
- return TRUE;
+ return TRUE;
+ }
}
static gboolean
@@ -1333,3 +1335,83 @@ gimp_container_tree_view_drag_pixbuf (GtkWidget *widget,
return NULL;
}
+
+static gboolean
+gimp_container_tree_view_get_selected_single (GimpContainerTreeView *tree_view,
+ GtkTreeIter *iter)
+{
+ GtkTreeSelection *selection;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view->view));
+
+ if (gtk_tree_selection_count_selected_rows (selection) == 1)
+ {
+ GList *selected_rows;
+
+ selected_rows = gtk_tree_selection_get_selected_rows (selection, NULL);
+
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_view->model), iter,
+ (GtkTreePath *) selected_rows->data);
+
+ g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
+ g_list_free (selected_rows);
+
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+static gint
+gimp_container_tree_view_get_selected (GimpContainerView *view,
+ GList **items)
+{
+ GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
+ GtkTreeSelection *selection;
+ gint selected_count;
+ GList *selected_rows;
+ GList *current_row;
+ GtkTreeIter iter;
+ GimpViewRenderer *renderer;
+
+ selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view->view));
+ selected_count = gtk_tree_selection_count_selected_rows (selection);
+
+ if (items == NULL)
+ {
+ /* just provide selected count */
+ return selected_count;
+ }
+
+ selected_rows = gtk_tree_selection_get_selected_rows (selection, NULL);
+
+ *items = NULL;
+ for (current_row = g_list_first (selected_rows);
+ current_row;
+ current_row = g_list_next (current_row))
+ {
+ gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_view->model), &iter,
+ (GtkTreePath *) current_row->data);
+
+ gtk_tree_model_get (tree_view->model, &iter,
+ GIMP_CONTAINER_TREE_VIEW_COLUMN_RENDERER, &renderer,
+ -1);
+
+ if (renderer->viewable)
+ {
+ *items = g_list_prepend (*items, renderer->viewable);
+ }
+
+ g_object_unref (renderer);
+ }
+
+ g_list_foreach (selected_rows, (GFunc) gtk_tree_path_free, NULL);
+ g_list_free (selected_rows);
+
+ *items = g_list_reverse (*items);
+
+ return selected_count;
+}
+
diff --git a/app/widgets/gimpcontainerview.c b/app/widgets/gimpcontainerview.c
index 41a24e6..0de7ccf 100644
--- a/app/widgets/gimpcontainerview.c
+++ b/app/widgets/gimpcontainerview.c
@@ -37,6 +37,8 @@
#include "gimpcontainerview.h"
#include "gimpdnd.h"
#include "gimpviewrenderer.h"
+#include "gimpuimanager.h"
+#include "gimpcontainertreeview.h"
enum
@@ -128,6 +130,8 @@ static void gimp_container_view_button_viewable_dropped (GtkWidget *widget,
gint y,
GimpViewable *viewable,
gpointer data);
+static gint gimp_container_view_real_get_selected (GimpContainerView *view,
+ GList **list);
static guint view_signals[LAST_SIGNAL] = { 0 };
@@ -210,6 +214,7 @@ gimp_container_view_iface_base_init (GimpContainerViewInterface *view_iface)
view_iface->rename_item = NULL;
view_iface->clear_items = gimp_container_view_real_clear_items;
view_iface->set_view_size = NULL;
+ view_iface->get_selected = gimp_container_view_real_get_selected;
view_iface->insert_data_free = NULL;
view_iface->model_is_tree = FALSE;
@@ -728,6 +733,76 @@ gimp_container_view_item_selected (GimpContainerView *view,
return success;
}
+gboolean
+gimp_container_view_multi_selected (GimpContainerView *view,
+ GList *items)
+{
+ guint selected_count;
+ gboolean success = FALSE;
+
+ g_return_val_if_fail (GIMP_IS_CONTAINER_VIEW (view), FALSE);
+
+ selected_count = g_list_length (items);
+
+ if (selected_count == 0)
+ {
+ /* do nothing */
+ }
+ else if (selected_count == 1)
+ {
+ success = gimp_container_view_item_selected (view, items->data);
+ }
+ else
+ {
+ success = FALSE;
+ g_signal_emit (view, view_signals[SELECT_ITEM], 0,
+ NULL, items, &success);
+ }
+
+ return success;
+}
+
+gint
+gimp_container_view_get_selected (GimpContainerView *view,
+ GList **list)
+{
+ g_return_val_if_fail (GIMP_IS_CONTAINER_VIEW (view), 0);
+
+ return GIMP_CONTAINER_VIEW_GET_INTERFACE (view)->get_selected (view, list);
+}
+
+static gint
+gimp_container_view_real_get_selected (GimpContainerView *view,
+ GList **list)
+{
+ GimpContainerViewPrivate *private = GIMP_CONTAINER_VIEW_GET_PRIVATE (view);
+ GType children_type;
+ GimpObject *object;
+
+ if (list)
+ {
+ *list = NULL;
+ }
+
+ if (!private->container
+ || !private->context)
+ {
+ return 0;
+ }
+
+ children_type = gimp_container_get_children_type (private->container);
+ object = gimp_context_get_by_type (private->context,
+ children_type);
+
+ if (list
+ && object)
+ {
+ *list = g_list_append (*list, object);
+ }
+
+ return object != NULL;
+}
+
void
gimp_container_view_item_activated (GimpContainerView *view,
GimpViewable *viewable)
@@ -1194,3 +1269,4 @@ gimp_container_view_button_viewable_dropped (GtkWidget *widget,
gtk_button_clicked (GTK_BUTTON (widget));
}
}
+
diff --git a/app/widgets/gimpcontainerview.h b/app/widgets/gimpcontainerview.h
index 1157f09..41b63a8 100644
--- a/app/widgets/gimpcontainerview.h
+++ b/app/widgets/gimpcontainerview.h
@@ -81,6 +81,9 @@ struct _GimpContainerViewInterface
gpointer insert_data);
void (* clear_items) (GimpContainerView *view);
void (* set_view_size) (GimpContainerView *view);
+ gint (* get_selected) (GimpContainerView *view,
+ GList **items);
+
/* the destroy notifier for private->hash_table's values */
GDestroyNotify insert_data_free;
@@ -122,7 +125,8 @@ void gimp_container_view_activate_item (GimpContainerView *view,
GimpViewable *viewable);
void gimp_container_view_context_item (GimpContainerView *view,
GimpViewable *viewable);
-
+gint gimp_container_view_get_selected (GimpContainerView *view,
+ GList **list);
/* protected */
@@ -131,6 +135,8 @@ gpointer gimp_container_view_lookup (GimpContainerView *view,
gboolean gimp_container_view_item_selected (GimpContainerView *view,
GimpViewable *item);
+gboolean gimp_container_view_multi_selected (GimpContainerView *view,
+ GList *items);
void gimp_container_view_item_activated (GimpContainerView *view,
GimpViewable *item);
void gimp_container_view_item_context (GimpContainerView *view,
@@ -148,5 +154,4 @@ void gimp_container_view_get_property (GObject *object,
GValue *value,
GParamSpec *pspec);
-
#endif /* __GIMP_CONTAINER_VIEW_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]