app: make GimpContainerView behave like a normal widget

The old API to select stuff and its signals was doing unexpected
stuff and was very confusing. Change things to be "normal":

The selection API is now set_selected() and get_selected(), with no
internal data exposed, and set_selected() emitting the expected
signal.

The signals are now "selection-changed" and "item-activated".
"selection-changed" is always emitted in response to changing the
selection, be it via the API, or by changes in the model (the internal
callbacks in from e.g. GimpContext or GimpImage simply call set_selected()
and don't do any unxpected magic).
This commit is contained in:
Michael Natterer 2025-07-30 16:38:24 +02:00
parent a7be8ec6cd
commit b416994ed0
29 changed files with 1446 additions and 1815 deletions

View file

@ -490,10 +490,9 @@ action_data_sel_count (gpointer data)
{
if (GIMP_IS_CONTAINER_EDITOR (data))
{
GimpContainerEditor *editor;
GimpContainerEditor *editor = GIMP_CONTAINER_EDITOR (data);
editor = GIMP_CONTAINER_EDITOR (data);
return gimp_container_view_get_selected (editor->view, NULL, NULL);
return gimp_container_view_get_selected (editor->view, NULL);
}
else
{

View file

@ -117,9 +117,7 @@ palettes_merge_callback (GtkWidget *widget,
context = gimp_container_view_get_context (editor->view);
factory = gimp_data_factory_view_get_data_factory (view);
gimp_container_view_get_selected (editor->view, &selected, NULL);
if (g_list_length (selected) < 2)
if (gimp_container_view_get_selected (editor->view, &selected) < 2)
{
gimp_message_literal (context->gimp,
G_OBJECT (editor), GIMP_MESSAGE_WARNING,

View file

@ -57,14 +57,12 @@ struct _LayerAddMaskDialog
/* local function prototypes */
static void layer_add_mask_dialog_free (LayerAddMaskDialog *private);
static void layer_add_mask_dialog_response (GtkWidget *dialog,
gint response_id,
LayerAddMaskDialog *private);
static gboolean layer_add_mask_dialog_channel_selected (GimpContainerView *view,
GList *viewables,
GList *paths,
LayerAddMaskDialog *private);
static void layer_add_mask_dialog_free (LayerAddMaskDialog *private);
static void layer_add_mask_dialog_response (GtkWidget *dialog,
gint response_id,
LayerAddMaskDialog *private);
static void layer_add_mask_dialog_channel_selected (GimpContainerView *view,
LayerAddMaskDialog *private);
/* public functions */
@ -166,7 +164,7 @@ layer_add_mask_dialog_new (GList *layers,
GIMP_ADD_MASK_CHANNEL, TRUE);
gtk_widget_show (combo);
g_signal_connect (combo, "select-items",
g_signal_connect (combo, "selection-changed",
G_CALLBACK (layer_add_mask_dialog_channel_selected),
private);
@ -179,8 +177,8 @@ layer_add_mask_dialog_new (GList *layers,
else
channel = GIMP_CHANNEL (gimp_container_get_first_child (gimp_image_get_channels (image)));
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (combo),
GIMP_VIEWABLE (channel));
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (combo),
GIMP_VIEWABLE (channel));
button = gtk_check_button_new_with_mnemonic (_("In_vert mask"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), private->invert);
@ -234,15 +232,9 @@ layer_add_mask_dialog_response (GtkWidget *dialog,
}
}
static gboolean
static void
layer_add_mask_dialog_channel_selected (GimpContainerView *view,
GList *viewables,
GList *paths,
LayerAddMaskDialog *private)
{
g_return_val_if_fail (g_list_length (viewables) < 2, FALSE);
private->channel = viewables? GIMP_CHANNEL (viewables->data) : NULL;
return TRUE;
private->channel = GIMP_CHANNEL (gimp_container_view_get_1_selected (view));
}

View file

@ -464,24 +464,20 @@ prefs_path_reset (GtkWidget *widget,
gimp_config_reset_property (config, writable_property);
}
static gboolean
static void
prefs_template_select_callback (GimpContainerView *view,
GList *templates,
GList *paths,
GimpTemplate *edit_template)
{
g_return_val_if_fail (g_list_length (templates) < 2, FALSE);
GimpViewable *item = gimp_container_view_get_1_selected (view);
if (templates)
if (item)
{
/* make sure the resolution values are copied first (see bug #546924) */
gimp_config_sync (G_OBJECT (templates->data), G_OBJECT (edit_template),
gimp_config_sync (G_OBJECT (item), G_OBJECT (edit_template),
GIMP_TEMPLATE_PARAM_COPY_FIRST);
gimp_config_sync (G_OBJECT (templates->data), G_OBJECT (edit_template),
gimp_config_sync (G_OBJECT (item), G_OBJECT (edit_template),
0);
}
return TRUE;
}
static void
@ -1813,9 +1809,9 @@ prefs_dialog_new (Gimp *gimp,
_("_Template:"), 0.0, 0.5,
combo, 1);
gimp_container_view_select_items (GIMP_CONTAINER_VIEW (combo), NULL);
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (combo), NULL);
g_signal_connect (combo, "select-items",
g_signal_connect (combo, "selection-changed",
G_CALLBACK (prefs_template_select_callback),
core_config->default_image);
}

View file

@ -94,9 +94,7 @@ static void quit_close_all_dialog_accel_marshal (GClosure *c
static void quit_close_all_dialog_container_changed (GimpContainer *images,
GimpObject *image,
QuitDialog *private);
static gboolean quit_close_all_dialog_images_selected (GimpContainerView *view,
GList *images,
GList *paths,
static void quit_close_all_dialog_images_selected (GimpContainerView *view,
QuitDialog *private);
static void quit_close_all_dialog_name_cell_func (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
@ -266,7 +264,7 @@ quit_close_all_dialog_new (Gimp *gimp,
gtk_box_pack_start (GTK_BOX (private->box), view, TRUE, TRUE, 0);
gtk_widget_show (view);
g_signal_connect (view, "select-items",
g_signal_connect (view, "selection-changed",
G_CALLBACK (quit_close_all_dialog_images_selected),
private);
@ -443,21 +441,15 @@ quit_close_all_dialog_container_changed (GimpContainer *images,
g_free (accel_string);
}
static gboolean
static void
quit_close_all_dialog_images_selected (GimpContainerView *view,
GList *images,
GList *paths,
QuitDialog *private)
{
/* The signal allows for multiple selection cases, but this specific
* dialog only allows one image selected at a time.
*/
g_return_val_if_fail (g_list_length (images) <= 1, FALSE);
GimpViewable *image = gimp_container_view_get_1_selected (view);
if (images)
if (image)
{
GimpImage *image = images->data;
GList *list;
GList *list;
for (list = gimp_get_display_iter (private->gimp);
list;
@ -465,7 +457,7 @@ quit_close_all_dialog_images_selected (GimpContainerView *view,
{
GimpDisplay *display = list->data;
if (gimp_display_get_image (display) == image)
if (gimp_display_get_image (display) == GIMP_IMAGE (image))
{
gimp_display_shell_present (gimp_display_get_shell (display));
@ -476,8 +468,6 @@ quit_close_all_dialog_images_selected (GimpContainerView *view,
}
}
}
return TRUE;
}
static void

View file

@ -276,8 +276,8 @@ stroke_dialog_response (GtkWidget *dialog,
gimp_config_reset (GIMP_CONFIG (private->options));
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (private->tool_combo),
GIMP_VIEWABLE (tool_info->paint_info));
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (private->tool_combo),
GIMP_VIEWABLE (tool_info->paint_info));
}
break;

View file

@ -103,10 +103,7 @@ static void gimp_bucket_fill_options_get_property (GObject
guint property_id,
GValue *value,
GParamSpec *pspec);
static gboolean
gimp_bucket_fill_options_select_stroke_tool (GimpContainerView *view,
GList *items,
GList *paths,
static void gimp_bucket_fill_options_select_stroke_tool (GimpContainerView *view,
GimpBucketFillOptions *options);
static void gimp_bucket_fill_options_tool_cell_renderer (GtkCellLayout *layout,
GtkCellRenderer *cell,
@ -481,24 +478,15 @@ gimp_bucket_fill_options_get_property (GObject *object,
}
}
static gboolean
static void
gimp_bucket_fill_options_select_stroke_tool (GimpContainerView *view,
GList *items,
GList *paths,
GimpBucketFillOptions *options)
{
GList *iter;
GimpViewable *item = gimp_container_view_get_1_selected (view);
for (iter = items; iter; iter = iter->next)
{
g_object_set (options,
"line-art-stroke-tool",
iter->data ? gimp_object_get_name (iter->data) : NULL,
NULL);
break;
}
return TRUE;
g_object_set (options,
"line-art-stroke-tool", item,
NULL);
}
static void
@ -851,7 +839,7 @@ gimp_bucket_fill_options_gui (GimpToolOptions *tool_options)
GIMP_CONTAINER_COMBO_BOX (widget)->viewable_renderer,
gimp_bucket_fill_options_tool_cell_renderer,
options, NULL);
g_signal_connect (widget, "select-items",
g_signal_connect (widget, "selection-changed",
G_CALLBACK (gimp_bucket_fill_options_select_stroke_tool),
options);

View file

@ -69,10 +69,10 @@ gimp_container_box_class_init (GimpContainerBoxClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = gimp_container_box_constructed;
object_class->set_property = gimp_container_view_set_property;
object_class->get_property = gimp_container_view_get_property;
object_class->set_property = _gimp_container_view_set_property;
object_class->get_property = _gimp_container_view_get_property;
gimp_container_view_install_properties (object_class);
_gimp_container_view_install_properties (object_class);
}
static void

View file

@ -60,6 +60,13 @@ static void gimp_container_combo_box_get_property (GObject *o
static void gimp_container_combo_box_set_context (GimpContainerView *view,
GimpContext *context);
static void gimp_container_combo_box_set_view_size (GimpContainerView *view);
static gboolean
gimp_container_combo_box_set_selected (GimpContainerView *view,
GList *items);
static gint gimp_container_combo_box_get_selected (GimpContainerView *view,
GList **items);
static gpointer gimp_container_combo_box_insert_item (GimpContainerView *view,
GimpViewable *viewable,
gpointer parent_insert_data,
@ -74,14 +81,7 @@ static void gimp_container_combo_box_reorder_item (GimpContainerView *v
static void gimp_container_combo_box_rename_item (GimpContainerView *view,
GimpViewable *viewable,
gpointer insert_data);
static gboolean gimp_container_combo_box_select_items(GimpContainerView *view,
GList *viewables,
GList *paths);
static void gimp_container_combo_box_clear_items (GimpContainerView *view);
static void gimp_container_combo_box_set_view_size (GimpContainerView *view);
static gint gimp_container_combo_box_get_selected (GimpContainerView *view,
GList **items,
GList **items_data);
static void gimp_container_combo_box_changed (GtkComboBox *combo_box,
GimpContainerView *view);
@ -105,7 +105,7 @@ gimp_container_combo_box_class_init (GimpContainerComboBoxClass *klass)
object_class->set_property = gimp_container_combo_box_set_property;
object_class->get_property = gimp_container_combo_box_get_property;
gimp_container_view_install_properties (object_class);
_gimp_container_view_install_properties (object_class);
g_object_class_install_property (object_class,
PROP_ELLIPSIZE,
@ -125,14 +125,15 @@ gimp_container_combo_box_view_iface_init (GimpContainerViewInterface *iface)
parent_view_iface = g_type_default_interface_peek (GIMP_TYPE_CONTAINER_VIEW);
iface->set_context = gimp_container_combo_box_set_context;
iface->set_view_size = gimp_container_combo_box_set_view_size;
iface->set_selected = gimp_container_combo_box_set_selected;
iface->get_selected = gimp_container_combo_box_get_selected;
iface->insert_item = gimp_container_combo_box_insert_item;
iface->remove_item = gimp_container_combo_box_remove_item;
iface->reorder_item = gimp_container_combo_box_reorder_item;
iface->rename_item = gimp_container_combo_box_rename_item;
iface->select_items = gimp_container_combo_box_select_items;
iface->clear_items = gimp_container_combo_box_clear_items;
iface->set_view_size = gimp_container_combo_box_set_view_size;
iface->get_selected = gimp_container_combo_box_get_selected;
iface->insert_data_free = (GDestroyNotify) gtk_tree_iter_free;
}
@ -205,7 +206,7 @@ gimp_container_combo_box_set_property (GObject *object,
break;
default:
gimp_container_view_set_property (object, property_id, value, pspec);
_gimp_container_view_set_property (object, property_id, value, pspec);
break;
}
}
@ -226,7 +227,7 @@ gimp_container_combo_box_get_property (GObject *object,
break;
default:
gimp_container_view_get_property (object, property_id, value, pspec);
_gimp_container_view_get_property (object, property_id, value, pspec);
break;
}
}
@ -275,6 +276,92 @@ gimp_container_combo_box_set_context (GimpContainerView *view,
context);
}
static void
gimp_container_combo_box_set_view_size (GimpContainerView *view)
{
GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (view));
if (model)
gimp_container_tree_store_set_view_size (GIMP_CONTAINER_TREE_STORE (model));
}
static gboolean
gimp_container_combo_box_set_selected (GimpContainerView *view,
GList *viewables)
{
GtkComboBox *combo_box = GTK_COMBO_BOX (view);
/* Only zero or one items may selected in a GimpContainerComboBox. */
g_return_val_if_fail (g_list_length (viewables) < 2, FALSE);
if (gtk_combo_box_get_model (GTK_COMBO_BOX (view)))
{
if (viewables)
{
GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (view));
GtkTreeIter iter;
gboolean iter_valid;
for (iter_valid = gtk_tree_model_get_iter_first (model, &iter);
iter_valid;
iter_valid = gtk_tree_model_iter_next (model, &iter))
{
GimpViewRenderer *renderer;
gtk_tree_model_get (model, &iter,
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
-1);
if (renderer->viewable == viewables->data)
{
gtk_combo_box_set_active_iter (combo_box, &iter);
g_object_unref (renderer);
break;
}
g_object_unref (renderer);
}
}
else
{
gtk_combo_box_set_active (combo_box, -1);
}
}
return TRUE;
}
static gint
gimp_container_combo_box_get_selected (GimpContainerView *view,
GList **items)
{
GtkComboBox *combo_box = GTK_COMBO_BOX (view);
GtkTreeIter iter;
gint selected = 0;
if (gtk_combo_box_get_active_iter (combo_box, &iter))
{
GimpViewRenderer *renderer;
gtk_tree_model_get (gtk_combo_box_get_model (combo_box), &iter,
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
-1);
if (renderer && renderer->viewable)
{
selected = 1;
if (items)
*items = g_list_prepend (NULL, renderer->viewable);
}
g_clear_object (&renderer);
}
return selected;
}
static gpointer
gimp_container_combo_box_insert_item (GimpContainerView *view,
GimpViewable *viewable,
@ -356,62 +443,6 @@ gimp_container_combo_box_rename_item (GimpContainerView *view,
insert_data);
}
static gboolean
gimp_container_combo_box_select_items (GimpContainerView *view,
GList *viewables,
GList *paths)
{
GtkComboBox *combo_box = GTK_COMBO_BOX (view);
g_return_val_if_fail (GIMP_IS_CONTAINER_VIEW (view), FALSE);
/* Only zero or one items may selected in a GimpContainerComboBox. */
g_return_val_if_fail (g_list_length (viewables) < 2, FALSE);
if (gtk_combo_box_get_model (GTK_COMBO_BOX (view)))
{
g_signal_handlers_block_by_func (combo_box,
gimp_container_combo_box_changed,
view);
if (viewables)
{
GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (view));
GtkTreeIter iter;
gboolean iter_valid;
for (iter_valid = gtk_tree_model_get_iter_first (model, &iter);
iter_valid;
iter_valid = gtk_tree_model_iter_next (model, &iter))
{
GimpViewRenderer *renderer;
gtk_tree_model_get (model, &iter,
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
-1);
if (renderer->viewable == viewables->data)
{
gtk_combo_box_set_active_iter (combo_box, &iter);
g_object_unref (renderer);
break;
}
g_object_unref (renderer);
}
}
else
{
gtk_combo_box_set_active (combo_box, -1);
}
g_signal_handlers_unblock_by_func (combo_box,
gimp_container_combo_box_changed,
view);
}
return TRUE;
}
static void
gimp_container_combo_box_clear_items (GimpContainerView *view)
{
@ -425,62 +456,9 @@ gimp_container_combo_box_clear_items (GimpContainerView *view)
parent_view_iface->clear_items (view);
}
static void
gimp_container_combo_box_set_view_size (GimpContainerView *view)
{
GtkTreeModel *model = gtk_combo_box_get_model (GTK_COMBO_BOX (view));
if (model)
gimp_container_tree_store_set_view_size (GIMP_CONTAINER_TREE_STORE (model));
}
static gint
gimp_container_combo_box_get_selected (GimpContainerView *view,
GList **items,
GList **items_data)
{
GtkComboBox *combo_box = GTK_COMBO_BOX (view);
GimpViewRenderer *renderer = NULL;
GtkTreeIter iter;
gint selected = 0;
if (gtk_combo_box_get_active_iter (combo_box, &iter))
gtk_tree_model_get (gtk_combo_box_get_model (combo_box), &iter,
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
-1);
if (items)
{
if (renderer != NULL && renderer->viewable != NULL)
{
*items = g_list_prepend (NULL, renderer->viewable);
selected = 1;
}
else
{
*items = NULL;
}
}
g_clear_object (&renderer);
return selected;
}
static void
gimp_container_combo_box_changed (GtkComboBox *combo,
GimpContainerView *view)
{
GtkTreeIter iter;
if (gtk_combo_box_get_active_iter (combo, &iter))
{
GimpViewRenderer *renderer;
gtk_tree_model_get (gtk_combo_box_get_model (combo), &iter,
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
-1);
gimp_container_view_item_selected (view, renderer->viewable);
g_object_unref (renderer);
}
_gimp_container_view_selection_changed (view);
}

View file

@ -85,13 +85,10 @@ static void gimp_container_editor_get_property (GObject *objec
GValue *value,
GParamSpec *pspec);
static gboolean gimp_container_editor_select_items (GimpContainerView *view,
GList *items,
GList *paths,
static void gimp_container_editor_selection_changed(GimpContainerView *view,
GimpContainerEditor *editor);
static void gimp_container_editor_activate_item (GtkWidget *widget,
static void gimp_container_editor_item_activated (GtkWidget *widget,
GimpViewable *viewable,
gpointer insert_data,
GimpContainerEditor *editor);
static GtkWidget * gimp_container_editor_get_preview (GimpDocked *docked,
@ -273,33 +270,13 @@ gimp_container_editor_constructed (GObject *object)
editor->view, "visible",
G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN);
/* Connect "select-items" with G_CONNECT_AFTER because it's a
* RUN_LAST signal and the default handler selecting the row must
* run before signal connections. See bug #784176.
*/
g_signal_connect_object (editor->view, "select-items",
G_CALLBACK (gimp_container_editor_select_items),
editor, G_CONNECT_AFTER);
g_signal_connect_object (editor->view, "activate-item",
G_CALLBACK (gimp_container_editor_activate_item),
g_signal_connect_object (editor->view, "selection-changed",
G_CALLBACK (gimp_container_editor_selection_changed),
editor, 0);
/* g_signal_connect_object (editor->view, "context-item", XXX maybe listen to popup-menu? */
/* G_CALLBACK (gimp_container_editor_context_item), */
/* editor, 0); */
{
GList *objects = NULL;
GimpObject *object = gimp_context_get_by_type (editor->priv->context,
gimp_container_get_child_type (editor->priv->container));
if (object)
objects = g_list_prepend (objects, object);
gimp_container_editor_select_items (editor->view, objects, NULL, editor);
g_list_free (objects);
}
g_signal_connect_object (editor->view, "item-activated",
G_CALLBACK (gimp_container_editor_item_activated),
editor, 0);
}
static void
@ -429,22 +406,25 @@ gimp_container_editor_set_selection_mode (GimpContainerEditor *editor,
mode);
}
/* private functions */
static gboolean
gimp_container_editor_select_items (GimpContainerView *view,
GList *items,
GList *paths,
GimpContainerEditor *editor)
static void
gimp_container_editor_selection_changed (GimpContainerView *view,
GimpContainerEditor *editor)
{
GimpContainerEditorClass *klass = GIMP_CONTAINER_EDITOR_GET_CLASS (editor);
GimpViewable *viewable = NULL;
GimpEditor *editor_view = NULL;
GList *items;
gimp_container_view_get_selected (view, &items);
/* XXX Right now a GimpContainerEditor only supports 1 item selected
* at once. Let's see later if we want to allow more.
*
* g_warn_if_fail (n_items < 2);
*/
/*g_return_val_if_fail (g_list_length (items) < 2, FALSE);*/
/* The editor view may get destroyed through a chain of signals when
* changing the context viewables with gimp_context_set_by_type().
@ -459,19 +439,6 @@ gimp_container_editor_select_items (GimpContainerView *view,
if (klass->select_item)
klass->select_item (editor, viewable);
if (editor->priv->container)
{
const gchar *signal_name;
GType child_type;
child_type = gimp_container_get_child_type (editor->priv->container);
signal_name = gimp_context_type_to_signal_name (child_type);
if (signal_name)
gimp_context_set_by_type (editor->priv->context, child_type,
GIMP_OBJECT (viewable));
}
if (viewable && editor_view)
{
gchar *desc = gimp_viewable_get_description (viewable, NULL);
@ -486,14 +453,13 @@ gimp_container_editor_select_items (GimpContainerView *view,
g_clear_weak_pointer (&editor_view);
return TRUE;
g_list_free (items);
}
static void
gimp_container_editor_activate_item (GtkWidget *widget,
GimpViewable *viewable,
gpointer insert_data,
GimpContainerEditor *editor)
gimp_container_editor_item_activated (GtkWidget *widget,
GimpViewable *viewable,
GimpContainerEditor *editor)
{
GimpContainerEditorClass *klass = GIMP_CONTAINER_EDITOR_GET_CLASS (editor);

View file

@ -46,6 +46,12 @@ static void gimp_container_entry_finalize (GObject *objec
static void gimp_container_entry_set_context (GimpContainerView *view,
GimpContext *context);
static void gimp_container_entry_set_view_size(GimpContainerView *view);
static gboolean gimp_container_entry_set_selected (GimpContainerView *view,
GList *items);
static gint gimp_container_entry_get_selected (GimpContainerView *view,
GList **items);
static gpointer gimp_container_entry_insert_item (GimpContainerView *view,
GimpViewable *viewable,
gpointer parent_insert_data,
@ -60,14 +66,7 @@ static void gimp_container_entry_reorder_item (GimpContainerView *view,
static void gimp_container_entry_rename_item (GimpContainerView *view,
GimpViewable *viewable,
gpointer insert_data);
static gboolean gimp_container_entry_select_items(GimpContainerView *view,
GList *items,
GList *paths);
static void gimp_container_entry_clear_items (GimpContainerView *view);
static void gimp_container_entry_set_view_size (GimpContainerView *view);
static gint gimp_container_entry_get_selected (GimpContainerView *view,
GList **items,
GList **items_data);
static void gimp_container_entry_changed (GtkEntry *entry,
GimpContainerView *view);
@ -92,11 +91,11 @@ gimp_container_entry_class_init (GimpContainerEntryClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->set_property = gimp_container_view_set_property;
object_class->get_property = gimp_container_view_get_property;
object_class->set_property = _gimp_container_view_set_property;
object_class->get_property = _gimp_container_view_get_property;
object_class->finalize = gimp_container_entry_finalize;
gimp_container_view_install_properties (object_class);
_gimp_container_view_install_properties (object_class);
}
static void
@ -108,14 +107,15 @@ gimp_container_entry_view_iface_init (GimpContainerViewInterface *iface)
parent_view_iface = g_type_default_interface_peek (GIMP_TYPE_CONTAINER_VIEW);
iface->set_context = gimp_container_entry_set_context;
iface->set_view_size = gimp_container_entry_set_view_size;
iface->set_selected = gimp_container_entry_set_selected;
iface->get_selected = gimp_container_entry_get_selected;
iface->insert_item = gimp_container_entry_insert_item;
iface->remove_item = gimp_container_entry_remove_item;
iface->reorder_item = gimp_container_entry_reorder_item;
iface->rename_item = gimp_container_entry_rename_item;
iface->select_items = gimp_container_entry_select_items;
iface->clear_items = gimp_container_entry_clear_items;
iface->set_view_size = gimp_container_entry_set_view_size;
iface->get_selected = gimp_container_entry_get_selected;
iface->insert_data_free = (GDestroyNotify) gtk_tree_iter_free;
}
@ -242,6 +242,64 @@ gimp_container_entry_set_context (GimpContainerView *view,
context);
}
static void
gimp_container_entry_set_view_size (GimpContainerView *view)
{
GtkTreeModel *model = gimp_container_entry_get_model (view);
gimp_container_tree_store_set_view_size (GIMP_CONTAINER_TREE_STORE (model));
}
static gboolean
gimp_container_entry_set_selected (GimpContainerView *view,
GList *viewables)
{
GimpContainerEntry *container_entry = GIMP_CONTAINER_ENTRY (view);
GtkEntry *entry = GTK_ENTRY (view);
GimpViewable *viewable = NULL;
/* XXX Only support 1 selected viewable for now. */
if (viewables)
viewable = viewables->data;
g_set_weak_pointer (&container_entry->viewable, viewable);
if (viewable)
{
gtk_entry_set_icon_from_icon_name (entry,
GTK_ENTRY_ICON_SECONDARY,
NULL);
}
else
{
/* The selected item does not exist. */
gtk_entry_set_icon_from_icon_name (entry,
GTK_ENTRY_ICON_SECONDARY,
GIMP_ICON_WILBER_EEK);
}
gtk_entry_set_text (entry, viewable ? gimp_object_get_name (viewable) : "");
return TRUE;
}
static gint
gimp_container_entry_get_selected (GimpContainerView *view,
GList **items)
{
GimpContainerEntry *container_entry = GIMP_CONTAINER_ENTRY (view);
if (items)
{
if (container_entry->viewable)
*items = g_list_prepend (NULL, container_entry->viewable);
else
*items = NULL;
}
return container_entry->viewable ? 1 : 0;
}
static gpointer
gimp_container_entry_insert_item (GimpContainerView *view,
GimpViewable *viewable,
@ -309,48 +367,6 @@ gimp_container_entry_rename_item (GimpContainerView *view,
insert_data);
}
static gboolean
gimp_container_entry_select_items (GimpContainerView *view,
GList *viewables,
GList *paths)
{
GimpContainerEntry *container_entry = GIMP_CONTAINER_ENTRY (view);
GtkEntry *entry = GTK_ENTRY (view);
GimpViewable *viewable = NULL;
/* XXX Only support 1 selected viewable for now. */
if (viewables)
viewable = viewables->data;
g_signal_handlers_block_by_func (entry,
gimp_container_entry_changed,
view);
g_set_weak_pointer (&container_entry->viewable, viewable);
if (viewable)
{
gtk_entry_set_icon_from_icon_name (entry,
GTK_ENTRY_ICON_SECONDARY,
NULL);
}
else
{
/* The selected item does not exist. */
gtk_entry_set_icon_from_icon_name (entry,
GTK_ENTRY_ICON_SECONDARY,
GIMP_ICON_WILBER_EEK);
}
gtk_entry_set_text (entry, viewable? gimp_object_get_name (viewable) : "");
g_signal_handlers_unblock_by_func (entry,
gimp_container_entry_changed,
view);
return TRUE;
}
static void
gimp_container_entry_clear_items (GimpContainerView *view)
{
@ -363,32 +379,6 @@ gimp_container_entry_clear_items (GimpContainerView *view)
parent_view_iface->clear_items (view);
}
static void
gimp_container_entry_set_view_size (GimpContainerView *view)
{
GtkTreeModel *model = gimp_container_entry_get_model (view);
gimp_container_tree_store_set_view_size (GIMP_CONTAINER_TREE_STORE (model));
}
static gint
gimp_container_entry_get_selected (GimpContainerView *view,
GList **items,
GList **items_data)
{
GimpContainerEntry *container_entry = GIMP_CONTAINER_ENTRY (view);
if (items)
{
if (container_entry->viewable != NULL)
*items = g_list_prepend (NULL, container_entry->viewable);
else
*items = NULL;
}
return container_entry->viewable == NULL ? 0 : 1;
}
static void
gimp_container_entry_changed (GtkEntry *entry,
GimpContainerView *view)
@ -406,10 +396,10 @@ gimp_container_entry_changed (GtkEntry *entry,
g_set_weak_pointer (&container_entry->viewable, GIMP_VIEWABLE (object));
_gimp_container_view_selection_changed (view);
if (container_entry->viewable)
{
gimp_container_view_item_selected (view, container_entry->viewable);
gtk_entry_set_icon_from_icon_name (entry,
GTK_ENTRY_ICON_SECONDARY,
NULL);
@ -429,12 +419,5 @@ gimp_container_entry_match_selected (GtkEntryCompletion *widget,
GtkTreeIter *iter,
GimpContainerView *view)
{
GimpViewRenderer *renderer;
gtk_tree_model_get (model, iter,
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
-1);
gimp_container_view_item_selected (view, renderer->viewable);
g_object_unref (renderer);
_gimp_container_view_selection_changed (view);
}

View file

@ -65,6 +65,11 @@ static void gimp_container_icon_view_set_context (GimpContainerVi
GimpContext *context);
static void gimp_container_icon_view_set_selection_mode(GimpContainerView *view,
GtkSelectionMode mode);
static void gimp_container_icon_view_set_view_size (GimpContainerView *view);
static gboolean gimp_container_icon_view_set_selected (GimpContainerView *view,
GList *items);
static gint gimp_container_icon_view_get_selected (GimpContainerView *view,
GList **items);
static gpointer gimp_container_icon_view_insert_item (GimpContainerView *view,
GimpViewable *viewable,
@ -80,11 +85,8 @@ static void gimp_container_icon_view_reorder_item (GimpContainerVi
static void gimp_container_icon_view_rename_item (GimpContainerView *view,
GimpViewable *viewable,
gpointer insert_data);
static gboolean gimp_container_icon_view_select_items (GimpContainerView *view,
GList *items,
GList *paths);
static void gimp_container_icon_view_clear_items (GimpContainerView *view);
static void gimp_container_icon_view_set_view_size (GimpContainerView *view);
static void gimp_container_icon_view_invalidate (GimpContainerIconView *view);
static void gimp_container_icon_view_selection_changed (GtkIconView *view,
@ -105,15 +107,12 @@ static gboolean gimp_container_icon_view_tooltip (GtkWidget
static GimpViewable * gimp_container_icon_view_drag_viewable (GtkWidget *widget,
GimpContext **context,
gpointer data);
static GdkPixbuf * gimp_container_icon_view_drag_pixbuf (GtkWidget *widget,
gpointer data);
static gboolean gimp_container_icon_view_get_selected_single (GimpContainerIconView *icon_view,
GtkTreeIter *iter);
static gint gimp_container_icon_view_get_selected (GimpContainerView *view,
GList **items,
GList **paths);
static GdkPixbuf * gimp_container_icon_view_drag_pixbuf (GtkWidget *widget,
gpointer data);
static gboolean gimp_container_icon_view_get_1_selected (GimpContainerIconView *icon_view,
GtkTreeIter *iter);
static void gimp_container_icon_view_trigger_redraw (GimpContainerIconView *view);
static void gimp_container_icon_view_trigger_redraw (GimpContainerIconView *view);
G_DEFINE_TYPE_WITH_CODE (GimpContainerIconView, gimp_container_icon_view,
@ -153,14 +152,15 @@ gimp_container_icon_view_view_iface_init (GimpContainerViewInterface *iface)
iface->set_container = gimp_container_icon_view_set_container;
iface->set_context = gimp_container_icon_view_set_context;
iface->set_selection_mode = gimp_container_icon_view_set_selection_mode;
iface->set_view_size = gimp_container_icon_view_set_view_size;
iface->set_selected = gimp_container_icon_view_set_selected;
iface->get_selected = gimp_container_icon_view_get_selected;
iface->insert_item = gimp_container_icon_view_insert_item;
iface->remove_item = gimp_container_icon_view_remove_item;
iface->reorder_item = gimp_container_icon_view_reorder_item;
iface->rename_item = gimp_container_icon_view_rename_item;
iface->select_items = gimp_container_icon_view_select_items;
iface->clear_items = gimp_container_icon_view_clear_items;
iface->set_view_size = gimp_container_icon_view_set_view_size;
iface->get_selected = gimp_container_icon_view_get_selected;
iface->insert_data_free = (GDestroyNotify) gtk_tree_iter_free;
}
@ -259,7 +259,7 @@ gimp_container_icon_view_popup_menu (GtkWidget *widget)
GtkTreePath *path;
GdkRectangle rect;
if (!gimp_container_icon_view_get_selected_single (icon_view, &iter))
if (! gimp_container_icon_view_get_1_selected (icon_view, &iter))
return FALSE;
path = gtk_tree_model_get_path (icon_view->model, &iter);
@ -377,10 +377,11 @@ gimp_container_icon_view_set_context (GimpContainerView *view,
if (context != NULL)
{
if (icon_view->priv->color_scheme_handler_id == 0)
icon_view->priv->color_scheme_handler_id = g_signal_connect_object (context->gimp->config,
"notify::theme-color-scheme",
G_CALLBACK (gimp_container_icon_view_trigger_redraw),
icon_view, G_CONNECT_SWAPPED);
icon_view->priv->color_scheme_handler_id =
g_signal_connect_object (context->gimp->config,
"notify::theme-color-scheme",
G_CALLBACK (gimp_container_icon_view_trigger_redraw),
icon_view, G_CONNECT_SWAPPED);
}
}
@ -395,6 +396,136 @@ gimp_container_icon_view_set_selection_mode (GimpContainerView *view,
parent_view_iface->set_selection_mode (view, mode);
}
static void
gimp_container_icon_view_set_view_size (GimpContainerView *view)
{
GimpContainerIconView *icon_view = GIMP_CONTAINER_ICON_VIEW (view);
if (icon_view->model)
gimp_container_tree_store_set_view_size (GIMP_CONTAINER_TREE_STORE (icon_view->model));
if (icon_view->view)
{
gtk_icon_view_set_columns (icon_view->view, -1);
gtk_icon_view_set_item_width (icon_view->view, -1);
/* ugly workaround to force the icon view to invalidate all its
* cached icon sizes
*/
gtk_icon_view_set_item_orientation (icon_view->view,
GTK_ORIENTATION_VERTICAL);
gtk_icon_view_set_item_orientation (icon_view->view,
GTK_ORIENTATION_HORIZONTAL);
}
}
static gboolean
gimp_container_icon_view_set_selected (GimpContainerView *view,
GList *items)
{
GimpContainerIconView *icon_view = GIMP_CONTAINER_ICON_VIEW (view);
GList *list;
if (items)
{
GList *paths = NULL;
for (list = items; list; list = g_list_next (list))
{
GtkTreeIter *iter;
GtkTreePath *path;
iter = _gimp_container_view_lookup (GIMP_CONTAINER_VIEW (view),
list->data);
if (! iter)
/* This may happen when the GimpContainerIconView only
* shows a subpart of the whole icons. We don't select
* what is not shown.
*/
continue;
path = gtk_tree_model_get_path (icon_view->model, iter);
paths = g_list_prepend (paths, path);
}
paths = g_list_reverse (paths);
g_signal_handlers_block_by_func (icon_view->view,
gimp_container_icon_view_selection_changed,
icon_view);
gtk_icon_view_unselect_all (icon_view->view);
for (list = paths; list; list = g_list_next (list))
{
gtk_icon_view_select_path (icon_view->view, list->data);
}
if (paths)
{
gtk_icon_view_set_cursor (icon_view->view, paths->data, NULL, FALSE);
gtk_icon_view_scroll_to_path (icon_view->view, paths->data,
FALSE, 0.0, 0.0);
}
g_signal_handlers_unblock_by_func (icon_view->view,
gimp_container_icon_view_selection_changed,
icon_view);
g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
_gimp_container_view_selection_changed (GIMP_CONTAINER_VIEW (icon_view));
}
else
{
gtk_icon_view_unselect_all (icon_view->view);
}
return TRUE;
}
static gint
gimp_container_icon_view_get_selected (GimpContainerView *view,
GList **items)
{
GimpContainerIconView *icon_view = GIMP_CONTAINER_ICON_VIEW (view);
GList *paths;
gint n_selected;
paths = gtk_icon_view_get_selected_items (icon_view->view);
n_selected = g_list_length (paths);
if (items)
{
GList *list;
for (list = paths; list; list = g_list_next (list))
{
GtkTreeIter iter;
GimpViewRenderer *renderer;
gtk_tree_model_get_iter (GTK_TREE_MODEL (icon_view->model), &iter,
(GtkTreePath *) list->data);
gtk_tree_model_get (icon_view->model, &iter,
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
-1);
if (renderer->viewable)
*items = g_list_prepend (*items, renderer->viewable);
g_object_unref (renderer);
}
*items = g_list_reverse (*items);
}
g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
return n_selected;
}
static gpointer
gimp_container_icon_view_insert_item (GimpContainerView *view,
GimpViewable *viewable,
@ -449,8 +580,8 @@ gimp_container_icon_view_reorder_item (GimpContainerView *view,
{
GtkTreeIter selected_iter;
selected = gimp_container_icon_view_get_selected_single (icon_view,
&selected_iter);
selected = gimp_container_icon_view_get_1_selected (icon_view,
&selected_iter);
if (selected)
{
@ -473,7 +604,7 @@ gimp_container_icon_view_reorder_item (GimpContainerView *view,
iter);
if (selected)
gimp_container_view_select_item (view, viewable);
gimp_container_view_set_1_selected (view, viewable);
}
static void
@ -489,75 +620,6 @@ gimp_container_icon_view_rename_item (GimpContainerView *view,
iter);
}
static gboolean
gimp_container_icon_view_select_items (GimpContainerView *view,
GList *viewables,
GList *paths)
{
GimpContainerIconView *icon_view = GIMP_CONTAINER_ICON_VIEW (view);
GList *list;
if (viewables)
{
gboolean free_paths = FALSE;
if (g_list_length (paths) != g_list_length (viewables))
{
free_paths = TRUE;
paths = NULL;
for (list = viewables; list; list = list->next)
{
GtkTreeIter *iter;
GtkTreePath *path;
iter = gimp_container_view_lookup (GIMP_CONTAINER_VIEW (view),
list->data);
if (! iter)
/* This may happen when the GimpContainerIconView only
* shows a subpart of the whole icons. We don't select
* what is not shown.
*/
continue;
path = gtk_tree_model_get_path (icon_view->model, iter);
paths = g_list_prepend (paths, path);
}
paths = g_list_reverse (paths);
}
g_signal_handlers_block_by_func (icon_view->view,
gimp_container_icon_view_selection_changed,
icon_view);
gtk_icon_view_unselect_all (icon_view->view);
for (list = paths; list; list = list->next)
{
gtk_icon_view_select_path (icon_view->view, list->data);
}
if (list)
{
gtk_icon_view_set_cursor (icon_view->view, list->data, NULL, FALSE);
gtk_icon_view_scroll_to_path (icon_view->view, list->data, FALSE, 0.0, 0.0);
}
g_signal_handlers_unblock_by_func (icon_view->view,
gimp_container_icon_view_selection_changed,
icon_view);
if (free_paths)
g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
}
else
{
gtk_icon_view_unselect_all (icon_view->view);
}
return TRUE;
}
static void
gimp_container_icon_view_clear_items (GimpContainerView *view)
{
@ -568,29 +630,6 @@ gimp_container_icon_view_clear_items (GimpContainerView *view)
parent_view_iface->clear_items (view);
}
static void
gimp_container_icon_view_set_view_size (GimpContainerView *view)
{
GimpContainerIconView *icon_view = GIMP_CONTAINER_ICON_VIEW (view);
if (icon_view->model)
gimp_container_tree_store_set_view_size (GIMP_CONTAINER_TREE_STORE (icon_view->model));
if (icon_view->view)
{
gtk_icon_view_set_columns (icon_view->view, -1);
gtk_icon_view_set_item_width (icon_view->view, -1);
/* ugly workaround to force the icon view to invalidate all its
* cached icon sizes
*/
gtk_icon_view_set_item_orientation (icon_view->view,
GTK_ORIENTATION_VERTICAL);
gtk_icon_view_set_item_orientation (icon_view->view,
GTK_ORIENTATION_HORIZONTAL);
}
}
static void
gimp_container_icon_view_invalidate (GimpContainerIconView *view)
{
@ -620,35 +659,7 @@ static void
gimp_container_icon_view_selection_changed (GtkIconView *gtk_icon_view,
GimpContainerIconView *icon_view)
{
GimpContainerView *view = GIMP_CONTAINER_VIEW (icon_view);
GList *items = NULL;
GList *paths;
GList *list;
paths = gtk_icon_view_get_selected_items (icon_view->view);
for (list = paths; list; list = list->next)
{
GtkTreeIter iter;
GimpViewRenderer *renderer;
gtk_tree_model_get_iter (GTK_TREE_MODEL (icon_view->model), &iter,
(GtkTreePath *) list->data);
gtk_tree_model_get (icon_view->model, &iter,
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
-1);
if (renderer->viewable)
items = g_list_prepend (items, renderer->viewable);
g_object_unref (renderer);
}
gimp_container_view_multi_selected (view, items, paths);
g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
g_list_free (items);
_gimp_container_view_selection_changed (GIMP_CONTAINER_VIEW (icon_view));
}
static void
@ -665,8 +676,8 @@ gimp_container_icon_view_item_activated (GtkIconView *view,
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
-1);
gimp_container_view_item_activated (GIMP_CONTAINER_VIEW (icon_view),
renderer->viewable);
_gimp_container_view_item_activated (GIMP_CONTAINER_VIEW (icon_view),
renderer->viewable);
g_object_unref (renderer);
}
@ -704,11 +715,16 @@ gimp_container_icon_view_button_press (GtkWidget *widget,
* selection. Otherwise, we use the current selection. This
* allows to not break multiple selection when right-clicking.
*/
if (! gimp_container_view_is_item_selected (container_view, renderer->viewable))
gimp_container_view_item_selected (container_view, renderer->viewable);
if (! gimp_container_view_is_item_selected (container_view,
renderer->viewable))
{
gimp_container_view_set_1_selected (container_view,
renderer->viewable);
}
/* Show the context menu. */
handled = gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (icon_view), (GdkEvent *) bevent);
handled = gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (icon_view),
(GdkEvent *) bevent);
}
/* Else LMB down or similar. Propagate. */
@ -721,7 +737,8 @@ gimp_container_icon_view_button_press (GtkWidget *widget,
/* Button down outside any item. */
if (gdk_event_triggers_context_menu ((GdkEvent *) bevent))
{
(void) gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (icon_view), (GdkEvent *) bevent);
(void) gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (icon_view),
(GdkEvent *) bevent);
/* Discard result. Does not actually popup menu except for managed views, e.g. dockable. */
}
@ -864,8 +881,8 @@ gimp_container_icon_view_drag_pixbuf (GtkWidget *widget,
}
static gboolean
gimp_container_icon_view_get_selected_single (GimpContainerIconView *icon_view,
GtkTreeIter *iter)
gimp_container_icon_view_get_1_selected (GimpContainerIconView *icon_view,
GtkTreeIter *iter)
{
GList *selected_items;
gboolean retval;
@ -875,7 +892,7 @@ gimp_container_icon_view_get_selected_single (GimpContainerIconView *icon_view,
if (g_list_length (selected_items) == 1)
{
gtk_tree_model_get_iter (GTK_TREE_MODEL (icon_view->model), iter,
(GtkTreePath *) selected_items->data);
selected_items->data);
retval = TRUE;
}
@ -889,106 +906,6 @@ gimp_container_icon_view_get_selected_single (GimpContainerIconView *icon_view,
return retval;
}
static gint
gimp_container_icon_view_get_selected (GimpContainerView *view,
GList **items,
GList **paths)
{
GimpContainerIconView *icon_view = GIMP_CONTAINER_ICON_VIEW (view);
GList *selected_paths;
gint selected_count;
GimpContainer *container;
container = gimp_container_view_get_container (view);
if (container)
{
const gchar *signal_name;
GimpContext *context;
GType child_type;
context = gimp_container_view_get_context (view);
child_type = gimp_container_get_child_type (container);
signal_name = gimp_context_type_to_signal_name (child_type);
/* As a special case, for containers tied to a context object, we
* look up this object as being selected.
* */
if (signal_name && context)
{
GimpObject *object;
object = gimp_context_get_by_type (context, child_type);
selected_count = object ? 1 : 0;
if (items)
{
if (object)
*items = g_list_prepend (NULL, object);
else
*items = NULL;
}
if (paths)
*paths = NULL;
return selected_count;
}
}
selected_paths = gtk_icon_view_get_selected_items (icon_view->view);
selected_count = g_list_length (selected_paths);
if (items)
{
GList *removed_paths = NULL;
GList *list;
*items = NULL;
for (list = selected_paths;
list;
list = g_list_next (list))
{
GtkTreeIter iter;
GimpViewRenderer *renderer;
gtk_tree_model_get_iter (GTK_TREE_MODEL (icon_view->model), &iter,
(GtkTreePath *) list->data);
gtk_tree_model_get (icon_view->model, &iter,
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
-1);
if (renderer->viewable)
*items = g_list_prepend (*items, renderer->viewable);
else
/* Remove from the selected_paths list but at the end, in order not
* to break the for loop.
*/
removed_paths = g_list_prepend (removed_paths, list);
g_object_unref (renderer);
}
*items = g_list_reverse (*items);
for (list = removed_paths; list; list = list->next)
{
GList *remove_list = list->data;
selected_paths = g_list_remove_link (selected_paths, remove_list);
gtk_tree_path_free (remove_list->data);
}
g_list_free_full (removed_paths, (GDestroyNotify) g_list_free);
}
if (paths)
*paths = selected_paths;
else
g_list_free_full (selected_paths, (GDestroyNotify) gtk_tree_path_free);
return selected_count;
}
static void
gimp_container_icon_view_trigger_redraw (GimpContainerIconView *view)
{

View file

@ -347,15 +347,11 @@ gimp_container_popup_create_view (GimpContainerPopup *popup)
if (signal_name)
{
GimpObject *object;
GList *items = NULL;
object = gimp_context_get_by_type (popup->orig_context, child_type);
if (object)
items = g_list_prepend (NULL, object);
gimp_container_view_select_items (popup->editor->view, items);
g_list_free (items);
gimp_container_view_set_1_selected (popup->editor->view,
GIMP_VIEWABLE (object));
}
}

View file

@ -630,8 +630,8 @@ gimp_container_tree_store_renderer_update (GimpViewRenderer *renderer,
GimpContainerTreeStorePrivate *private = GET_PRIVATE (store);
GtkTreeIter *iter;
iter = gimp_container_view_lookup (private->container_view,
renderer->viewable);
iter = _gimp_container_view_lookup (private->container_view,
renderer->viewable);
if (iter)
{

View file

@ -73,6 +73,11 @@ static void gimp_container_tree_view_set_context (GimpContainerVi
GimpContext *context);
static void gimp_container_tree_view_set_selection_mode(GimpContainerView *view,
GtkSelectionMode mode);
static void gimp_container_tree_view_set_view_size (GimpContainerView *view);
static gboolean gimp_container_tree_view_set_selected (GimpContainerView *view,
GList *items);
static gint gimp_container_tree_view_get_selected (GimpContainerView *view,
GList **items);
static gpointer gimp_container_tree_view_insert_item (GimpContainerView *view,
GimpViewable *viewable,
@ -91,11 +96,7 @@ static void gimp_container_tree_view_rename_item (GimpContainerVi
static void gimp_container_tree_view_expand_item (GimpContainerView *view,
GimpViewable *viewable,
gpointer insert_data);
static gboolean gimp_container_tree_view_select_items (GimpContainerView *view,
GList *viewables,
GList *paths);
static void gimp_container_tree_view_clear_items (GimpContainerView *view);
static void gimp_container_tree_view_set_view_size (GimpContainerView *view);
static void gimp_container_tree_view_real_edit_name (GimpContainerTreeView *tree_view);
@ -138,11 +139,8 @@ static void gimp_container_tree_view_zoom_gesture_update (GtkGestureZoo
GdkEventSequence *sequence,
GimpContainerTreeView *tree_view);
static gboolean gimp_container_tree_view_get_selected_single (GimpContainerTreeView *tree_view,
static gboolean gimp_container_tree_view_get_1_selected (GimpContainerTreeView *tree_view,
GtkTreeIter *iter);
static gint gimp_container_tree_view_get_selected (GimpContainerView *view,
GList **items,
GList **paths);
static void gimp_container_tree_view_row_expanded (GtkTreeView *tree_view,
GtkTreeIter *iter,
GtkTreePath *path,
@ -153,14 +151,6 @@ static void gimp_container_tree_view_expand_rows (GtkTreeModel
static void gimp_container_tree_view_monitor_changed (GimpContainerTreeView *view);
static gboolean gimp_container_tree_view_search_path_foreach (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
gpointer data);
static GtkTreePath * gimp_container_tree_view_get_path (GimpContainerTreeView *tree_view,
GimpViewable *viewable);
G_DEFINE_TYPE_WITH_CODE (GimpContainerTreeView, gimp_container_tree_view,
GIMP_TYPE_CONTAINER_BOX,
@ -223,15 +213,16 @@ gimp_container_tree_view_view_iface_init (GimpContainerViewInterface *iface)
iface->set_container = gimp_container_tree_view_set_container;
iface->set_context = gimp_container_tree_view_set_context;
iface->set_selection_mode = gimp_container_tree_view_set_selection_mode;
iface->set_view_size = gimp_container_tree_view_set_view_size;
iface->set_selected = gimp_container_tree_view_set_selected;
iface->get_selected = gimp_container_tree_view_get_selected;
iface->insert_item = gimp_container_tree_view_insert_item;
iface->remove_item = gimp_container_tree_view_remove_item;
iface->reorder_item = gimp_container_tree_view_reorder_item;
iface->rename_item = gimp_container_tree_view_rename_item;
iface->expand_item = gimp_container_tree_view_expand_item;
iface->select_items = gimp_container_tree_view_select_items;
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;
}
@ -450,7 +441,7 @@ gimp_container_tree_view_popup_menu (GtkWidget *widget)
GtkTreePath *path;
GdkRectangle rect;
if (!gimp_container_tree_view_get_selected_single (tree_view, &iter))
if (! gimp_container_tree_view_get_1_selected (tree_view, &iter))
return FALSE;
path = gtk_tree_model_get_path (tree_view->model, &iter);
@ -741,6 +732,289 @@ gimp_container_tree_view_set_selection_mode (GimpContainerView *view,
parent_view_iface->set_selection_mode (view, mode);
}
static void
gimp_container_tree_view_set_view_size (GimpContainerView *view)
{
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
GtkWidget *tree_widget;
GList *list;
gint view_size;
gint border_width;
view_size = gimp_container_view_get_view_size (view, &border_width);
if (tree_view->model)
gimp_container_tree_store_set_view_size (GIMP_CONTAINER_TREE_STORE (tree_view->model));
tree_widget = GTK_WIDGET (tree_view->view);
if (! tree_widget)
return;
for (list = tree_view->priv->toggle_cells; list; list = g_list_next (list))
{
gchar *icon_name;
gint icon_size;
g_object_get (list->data, "icon-name", &icon_name, NULL);
if (icon_name)
{
GtkStyleContext *style = gtk_widget_get_style_context (tree_widget);
GtkBorder border;
gtk_style_context_save (style);
gtk_style_context_add_class (style, GTK_STYLE_CLASS_BUTTON);
gtk_style_context_get_border (style, 0, &border);
gtk_style_context_restore (style);
g_object_get (list->data, "icon-size", &icon_size, NULL);
icon_size = MIN (icon_size, MAX (view_size - (border.left + border.right),
view_size - (border.top + border.bottom)));
g_object_set (list->data, "icon-size", icon_size, NULL);
g_free (icon_name);
}
}
gtk_tree_view_columns_autosize (tree_view->view);
}
static gboolean
gimp_container_tree_view_set_selected (GimpContainerView *view,
GList *items)
{
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
GList *item;
GList *paths = NULL;
GList *path;
gboolean scroll_to_first = TRUE;
GtkTreePath *focused_path = NULL;
for (item = items; item; item = g_list_next (item))
{
GtkTreeIter *iter = _gimp_container_view_lookup (view, item->data);
GtkTreePath *p;
if (! iter)
/* This may happen when the view only shows a subpart of the
* whole items. We don't select what is not shown.
*/
continue;
p = gtk_tree_model_get_path (tree_view->model, iter);
paths = g_list_prepend (paths, p);
}
paths = g_list_reverse (paths);
g_signal_handlers_block_by_func (tree_view->priv->selection,
gimp_container_tree_view_selection_changed,
tree_view);
gtk_tree_selection_unselect_all (tree_view->priv->selection);
gtk_tree_view_get_cursor (tree_view->view, &focused_path, NULL);
if (focused_path != NULL)
{
GtkTreePath *closer_up = NULL;
GtkTreePath *closer_down = NULL;
for (path = paths; path; path = g_list_next (path))
{
if (gtk_tree_path_compare (path->data, focused_path) == 0)
{
break;
}
else if (gtk_tree_path_compare (path->data, focused_path) == -1)
{
if (closer_up == NULL ||
gtk_tree_path_compare (path->data, closer_up) == 1)
{
closer_up = path->data;
}
}
else
{
if (closer_down == NULL ||
gtk_tree_path_compare (path->data, closer_down) == -1)
{
closer_down = path->data;
}
}
}
if (path == NULL)
{
/* The current cursor is not part of the selection. This may
* happen in particular with a ctrl-click interaction which
* would deselect the item the cursor is now on.
*/
g_clear_pointer (&focused_path, gtk_tree_path_free);
if (closer_up != NULL || closer_down != NULL)
{
GtkTreePath *first = NULL;
GtkTreePath *last = NULL;
if (gtk_tree_view_get_visible_range (tree_view->view,
&first, &last))
{
if (closer_up != NULL &&
gtk_tree_path_compare (closer_up, first) >= 0 &&
gtk_tree_path_compare (closer_up, last) <= 0)
{
focused_path = gtk_tree_path_copy (closer_up);
}
else if (closer_down != NULL &&
gtk_tree_path_compare (closer_down, first) >= 0 &&
gtk_tree_path_compare (closer_down, last) <= 0)
{
focused_path = gtk_tree_path_copy (closer_down);
}
}
if (focused_path == NULL)
{
if (closer_up != NULL)
focused_path = gtk_tree_path_copy (closer_up);
else
focused_path = gtk_tree_path_copy (closer_down);
}
gtk_tree_path_free (first);
gtk_tree_path_free (last);
}
else if (paths != NULL)
{
focused_path = gtk_tree_path_copy (paths->data);
}
}
}
else if (paths != NULL)
{
focused_path = gtk_tree_path_copy (paths->data);
}
/* Setting a cursor will reset the selection, so we must do it first. We don't
* want to change the cursor (which is likely the last clicked item), yet we
* also want to make sure that the cursor cannot end up out of the selected
* items, leading to discrepancy between pointer and keyboard navigation. This
* is why we set the cursor with this priority:
* 1. unchanged if it stays within selection;
* 2. closer item above the current cursor, if visible;
* 3. closer item below the current cursor, if visible;
* 4. closer item above the current cursor (even though invisible, which will
* make the view scroll up);
* 5. closer item below the current cursor if there are no items above (view
* will scroll down);
* 6. top selected item if there was no current cursor;
* 7. nothing if no selected items.
*/
if (focused_path != NULL)
{
gtk_tree_view_set_cursor (tree_view->view, focused_path, NULL, FALSE);
gtk_tree_path_free (focused_path);
}
for (path = paths; path; path = g_list_next (path))
{
GtkTreePath *parent_path = gtk_tree_path_copy (path->data);
/* Expand the parent. */
if (gtk_tree_path_up (parent_path))
gtk_tree_view_expand_to_path (tree_view->view, parent_path);
gtk_tree_path_free (parent_path);
/* Add to the selection. */
gtk_tree_selection_select_path (tree_view->priv->selection, path->data);
}
g_signal_handlers_unblock_by_func (tree_view->priv->selection,
gimp_container_tree_view_selection_changed,
tree_view);
if (paths)
{
GtkTreePath *first;
GtkTreePath *last;
/* Scroll to the top item if and only if none of the selected
* items are already visible. Do nothing otherwise.
*/
if (gtk_tree_view_get_visible_range (tree_view->view, &first, &last))
{
for (path = paths; path; path = g_list_next (path))
{
if (gtk_tree_path_compare (first, path->data) <= 0 &&
gtk_tree_path_compare (path->data, last) <= 0)
{
scroll_to_first = FALSE;
break;
}
}
gtk_tree_path_free (first);
gtk_tree_path_free (last);
}
if (scroll_to_first)
gtk_tree_view_scroll_to_cell (tree_view->view, paths->data,
NULL, FALSE, 0.0, 0.0);
}
g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
_gimp_container_view_selection_changed (view);
return TRUE;
}
static gint
gimp_container_tree_view_get_selected (GimpContainerView *view,
GList **items)
{
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
GtkTreeSelection *selection;
gint n_selected;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree_view->view));
n_selected = gtk_tree_selection_count_selected_rows (selection);
if (items)
{
GList *paths;
GList *list;
paths = gtk_tree_selection_get_selected_rows (selection, NULL);
for (list = paths; list; list = g_list_next (list))
{
GimpViewRenderer *renderer;
GtkTreeIter iter;
gtk_tree_model_get_iter (GTK_TREE_MODEL (tree_view->model), &iter,
list->data);
renderer = gimp_container_tree_store_get_renderer
(GIMP_CONTAINER_TREE_STORE (tree_view->model), &iter);
if (renderer->viewable)
*items = g_list_prepend (*items, renderer->viewable);
else
n_selected--;
g_object_unref (renderer);
}
*items = g_list_reverse (*items);
}
return n_selected;
}
static gpointer
gimp_container_tree_view_insert_item (GimpContainerView *view,
GimpViewable *viewable,
@ -787,37 +1061,12 @@ gimp_container_tree_view_reorder_item (GimpContainerView *view,
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
GtkTreeIter *iter = (GtkTreeIter *) insert_data;
GtkTreeIter parent_iter;
gboolean selected = FALSE;
if (iter)
{
GtkTreeIter selected_iter;
selected = gimp_container_tree_view_get_selected_single (tree_view,
&selected_iter);
if (selected)
{
GimpViewRenderer *renderer;
renderer = gimp_container_tree_store_get_renderer (GIMP_CONTAINER_TREE_STORE (tree_view->model),
&selected_iter);
if (renderer->viewable != viewable)
selected = FALSE;
g_object_unref (renderer);
}
}
gimp_container_tree_store_reorder_item (GIMP_CONTAINER_TREE_STORE (tree_view->model),
viewable,
new_index,
iter);
if (selected)
gimp_container_view_select_item (view, viewable);
if (gtk_tree_model_iter_parent (tree_view->model, &parent_iter, iter))
gimp_container_tree_view_expand_item (view, viewable, &parent_iter);
}
@ -871,185 +1120,6 @@ gimp_container_tree_view_expand_item (GimpContainerView *view,
}
}
static gboolean
gimp_container_tree_view_select_items (GimpContainerView *view,
GList *items,
GList *paths)
{
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
GList *item;
GList *path;
gboolean free_paths = FALSE;
gboolean scroll_to_first = TRUE;
GtkTreePath *focused_path = NULL;
/* If @paths is not set, compute it ourselves. */
if (g_list_length (items) != g_list_length (paths))
{
paths = NULL;
for (item = items; item; item = item->next)
{
GtkTreePath *path;
path = gimp_container_tree_view_get_path (tree_view, item->data);
if (path != NULL)
/* It may happen that some items have no paths when a tree
* view has some filtering logics (for instance Palette or
* Fonts dockables). Then an item which was selected at
* first might become unselected during filtering and has to
* be removed from selection.
*/
paths = g_list_prepend (paths, path);
}
paths = g_list_reverse (paths);
free_paths = TRUE;
}
g_signal_handlers_block_by_func (tree_view->priv->selection,
gimp_container_tree_view_selection_changed,
tree_view);
gtk_tree_selection_unselect_all (tree_view->priv->selection);
gtk_tree_view_get_cursor (tree_view->view, &focused_path, NULL);
if (focused_path != NULL)
{
GtkTreePath *closer_up = NULL;
GtkTreePath *closer_down = NULL;
for (path = paths; path; path = path->next)
{
if (gtk_tree_path_compare (path->data, focused_path) == 0)
{
break;
}
else if (gtk_tree_path_compare (path->data, focused_path) == -1)
{
if (closer_up == NULL || gtk_tree_path_compare (path->data, closer_up) == 1)
closer_up = path->data;
}
else
{
if (closer_down == NULL || gtk_tree_path_compare (path->data, closer_down) == -1)
closer_down = path->data;
}
}
if (path == NULL)
{
/* The current cursor is not part of the selection. This may happen in
* particular with a ctrl-click interaction which would deselect the
* item the cursor is now on.
*/
g_clear_pointer (&focused_path, gtk_tree_path_free);
if (closer_up != NULL || closer_down != NULL)
{
GtkTreePath *first = NULL;
GtkTreePath *last = NULL;
if (gtk_tree_view_get_visible_range (tree_view->view, &first, &last))
{
if (closer_up != NULL &&
gtk_tree_path_compare (closer_up, first) >= 0 &&
gtk_tree_path_compare (closer_up, last) <= 0)
focused_path = gtk_tree_path_copy (closer_up);
else if (closer_down != NULL &&
gtk_tree_path_compare (closer_down, first) >= 0 &&
gtk_tree_path_compare (closer_down, last) <= 0)
focused_path = gtk_tree_path_copy (closer_down);
}
if (focused_path == NULL)
{
if (closer_up != NULL)
focused_path = gtk_tree_path_copy (closer_up);
else
focused_path = gtk_tree_path_copy (closer_down);
}
gtk_tree_path_free (first);
gtk_tree_path_free (last);
}
else if (paths != NULL)
{
focused_path = gtk_tree_path_copy (paths->data);
}
}
}
else if (paths != NULL)
{
focused_path = gtk_tree_path_copy (paths->data);
}
/* Setting a cursor will reset the selection, so we must do it first. We don't
* want to change the cursor (which is likely the last clicked item), yet we
* also want to make sure that the cursor cannot end up out of the selected
* items, leading to discrepancy between pointer and keyboard navigation. This
* is why we set the cursor with this priority:
* 1. unchanged if it stays within selection;
* 2. closer item above the current cursor, if visible;
* 3. closer item below the current cursor, if visible;
* 4. closer item above the current cursor (even though invisible, which will
* make the view scroll up);
* 5. closer item below the current cursor if there are no items above (view
* will scroll down);
* 6. top selected item if there was no current cursor;
* 7. nothing if no selected items.
*/
if (focused_path != NULL)
gtk_tree_view_set_cursor (tree_view->view, focused_path, NULL, FALSE);
gtk_tree_path_free (focused_path);
for (item = items, path = paths; item && path; item = item->next, path = path->next)
{
GtkTreePath *parent_path;
/* Expand if necessary. */
parent_path = gtk_tree_path_copy (path->data);
if (gtk_tree_path_up (parent_path))
gtk_tree_view_expand_to_path (tree_view->view, parent_path);
gtk_tree_path_free (parent_path);
/* Add to the selection. */
gtk_tree_selection_select_path (tree_view->priv->selection, path->data);
}
g_signal_handlers_unblock_by_func (tree_view->priv->selection,
gimp_container_tree_view_selection_changed,
tree_view);
if (paths)
{
GtkTreePath *first;
GtkTreePath *last;
/* Scroll to the top item if and only if none of the selected
* items are already visible. Do nothing otherwise.
*/
if (gtk_tree_view_get_visible_range (tree_view->view, &first, &last))
{
for (item = items, path = paths; item && path; item = item->next, path = path->next)
{
if (gtk_tree_path_compare (first, path->data) <= 0 &&
gtk_tree_path_compare (path->data, last) <= 0)
{
scroll_to_first = FALSE;
break;
}
}
gtk_tree_path_free (first);
gtk_tree_path_free (last);
}
if (scroll_to_first)
gtk_tree_view_scroll_to_cell (tree_view->view, paths->data,
NULL, FALSE, 0.0, 0.0);
}
if (free_paths)
g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
return TRUE;
}
static void
gimp_container_tree_view_clear_items (GimpContainerView *view)
{
@ -1077,54 +1147,6 @@ gimp_container_tree_view_clear_items (GimpContainerView *view)
parent_view_iface->clear_items (view);
}
static void
gimp_container_tree_view_set_view_size (GimpContainerView *view)
{
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
GtkWidget *tree_widget;
GList *list;
gint view_size;
gint border_width;
view_size = gimp_container_view_get_view_size (view, &border_width);
if (tree_view->model)
gimp_container_tree_store_set_view_size (GIMP_CONTAINER_TREE_STORE (tree_view->model));
tree_widget = GTK_WIDGET (tree_view->view);
if (! tree_widget)
return;
for (list = tree_view->priv->toggle_cells; list; list = g_list_next (list))
{
gchar *icon_name;
gint icon_size;
g_object_get (list->data, "icon-name", &icon_name, NULL);
if (icon_name)
{
GtkStyleContext *style = gtk_widget_get_style_context (tree_widget);
GtkBorder border;
gtk_style_context_save (style);
gtk_style_context_add_class (style, GTK_STYLE_CLASS_BUTTON);
gtk_style_context_get_border (style, 0, &border);
gtk_style_context_restore (style);
g_object_get (list->data, "icon-size", &icon_size, NULL);
icon_size = MIN (icon_size, MAX (view_size - (border.left + border.right),
view_size - (border.top + border.bottom)));
g_object_set (list->data, "icon-size", icon_size, NULL);
g_free (icon_name);
}
}
gtk_tree_view_columns_autosize (tree_view->view);
}
/* GimpContainerTreeView methods */
@ -1136,8 +1158,8 @@ gimp_container_tree_view_real_edit_name (GimpContainerTreeView *tree_view)
if (g_list_find (tree_view->priv->editable_cells,
tree_view->priv->name_cell) &&
gimp_container_tree_view_get_selected_single (tree_view,
&selected_iter))
gimp_container_tree_view_get_1_selected (tree_view,
&selected_iter))
{
GimpViewRenderer *renderer;
@ -1227,7 +1249,7 @@ gimp_container_tree_view_name_canceled (GtkCellRendererText *cell,
{
GtkTreeIter iter;
if (gimp_container_tree_view_get_selected_single (tree_view, &iter))
if (gimp_container_tree_view_get_1_selected (tree_view, &iter))
{
GimpViewRenderer *renderer;
gchar *name;
@ -1249,14 +1271,7 @@ static void
gimp_container_tree_view_selection_changed (GtkTreeSelection *selection,
GimpContainerTreeView *tree_view)
{
GimpContainerView *view = GIMP_CONTAINER_VIEW (tree_view);
GList *items;
GList *paths;
gimp_container_tree_view_get_selected (view, &items, &paths);
gimp_container_view_multi_selected (view, items, paths);
g_list_free (items);
g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
_gimp_container_view_selection_changed (GIMP_CONTAINER_VIEW (tree_view));
}
static GtkCellRenderer *
@ -1319,19 +1334,20 @@ gimp_container_tree_view_button (GtkWidget *widget,
bevent->x, bevent->y,
&path, &column, NULL, NULL))
{
GimpViewRenderer *renderer;
GtkCellRenderer *edit_cell = NULL;
GdkRectangle column_area;
GtkTreeIter iter;
gboolean multisel_mode;
GdkModifierType modifiers = (bevent->state & gimp_get_all_modifiers_mask ());
GimpViewRenderer *renderer;
GtkCellRenderer *edit_cell = NULL;
GdkRectangle column_area;
GtkTreeIter iter;
gboolean multisel_mode;
GdkModifierType modifiers = (bevent->state & gimp_get_all_modifiers_mask ());
handled = TRUE;
multisel_mode = (gtk_tree_selection_get_mode (tree_view->priv->selection)
== GTK_SELECTION_MULTIPLE);
if (! modifiers ||
(modifiers & ~(gimp_get_extend_selection_mask () | gimp_get_modify_selection_mask ())))
(modifiers & ~(gimp_get_extend_selection_mask () |
gimp_get_modify_selection_mask ())))
{
/* don't chain up for multi-selection handling if none of
* the participating modifiers is pressed, we implement
@ -1357,12 +1373,14 @@ gimp_container_tree_view_button (GtkWidget *widget,
* in this function.
* See also commit 3e101922, MR !1128 and #10281.
*/
if (multisel_mode && bevent->type == GDK_BUTTON_PRESS && ! gtk_widget_has_focus (widget))
if (multisel_mode && bevent->type == GDK_BUTTON_PRESS &&
! gtk_widget_has_focus (widget))
gtk_widget_grab_focus (widget);
gtk_tree_model_get_iter (tree_view->model, &iter, path);
renderer = gimp_container_tree_store_get_renderer (GIMP_CONTAINER_TREE_STORE (tree_view->model), &iter);
renderer = gimp_container_tree_store_get_renderer
(GIMP_CONTAINER_TREE_STORE (tree_view->model), &iter);
tree_view->priv->dnd_renderer = renderer;
@ -1525,18 +1543,29 @@ gimp_container_tree_view_button (GtkWidget *widget,
{
/* If the clicked item is not selected, it becomes the new
* selection. Otherwise, we use the current selection. This
* allows to not break multiple selection when right-clicking.
* allows to not break multiple selection when
* right-clicking.
*/
if (! gimp_container_view_is_item_selected (container_view, renderer->viewable))
gimp_container_view_item_selected (container_view, renderer->viewable);
if (! gimp_container_view_is_item_selected (container_view,
renderer->viewable))
{
gimp_container_view_set_1_selected (container_view,
renderer->viewable);
}
/* Show the context menu. */
if (gimp_container_view_get_container (container_view))
gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (tree_view), (GdkEvent *) bevent);
{
gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (tree_view),
(GdkEvent *) bevent);
}
}
else if (bevent->button == 1)
{
handled = TRUE;
if (bevent->type == GDK_BUTTON_PRESS || bevent->type == GDK_BUTTON_RELEASE)
if (bevent->type == GDK_BUTTON_PRESS ||
bevent->type == GDK_BUTTON_RELEASE)
{
/* don't select item if a toggle was clicked */
if (! toggled_cell)
@ -1561,8 +1590,8 @@ gimp_container_tree_view_button (GtkWidget *widget,
* click becomes a drag'n drop action.
*/
handled =
gimp_container_view_item_selected (container_view,
renderer->viewable);
gimp_container_view_set_1_selected (container_view,
renderer->viewable);
}
/* Multi selection will be handled by gimp_container_tree_view_selection_changed() */
@ -1617,8 +1646,10 @@ gimp_container_tree_view_button (GtkWidget *widget,
/* don't select item if a toggle was clicked */
if (bevent->type == GDK_BUTTON_RELEASE && ! toggled_cell)
success = gimp_container_view_item_selected (container_view,
renderer->viewable);
{
success = gimp_container_view_set_1_selected (container_view,
renderer->viewable);
}
if (success)
{
@ -1642,8 +1673,8 @@ gimp_container_tree_view_button (GtkWidget *widget,
/* Only activate if we're not in a toggled cell
* and no modifier keys are pressed
*/
gimp_container_view_item_activated (container_view,
renderer->viewable);
_gimp_container_view_item_activated (container_view,
renderer->viewable);
}
}
}
@ -1670,21 +1701,28 @@ gimp_container_tree_view_button (GtkWidget *widget,
gtk_tree_path_free (path);
g_object_unref (renderer);
handled = (multisel_mode ? handled : (bevent->type == GDK_BUTTON_RELEASE ? FALSE : TRUE));
handled = (multisel_mode ? handled :
(bevent->type == GDK_BUTTON_RELEASE ? FALSE : TRUE));
}
else
{
if (gdk_event_triggers_context_menu ((GdkEvent *) bevent))
{
gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (tree_view), (GdkEvent *) bevent);
gimp_editor_popup_menu_at_pointer (GIMP_EDITOR (tree_view),
(GdkEvent *) bevent);
}
handled = TRUE;
}
if (handled && bevent->type == GDK_BUTTON_PRESS && ! gtk_widget_has_focus (widget) &&
! toggled_cell && ! clicked_cell)
gtk_widget_grab_focus (widget);
if (handled &&
bevent->type == GDK_BUTTON_PRESS &&
! gtk_widget_has_focus (widget) &&
! toggled_cell &&
! clicked_cell)
{
gtk_widget_grab_focus (widget);
}
return handled;
}
@ -1810,7 +1848,7 @@ gimp_container_tree_view_drag_viewable_list (GtkWidget *widget,
if (context)
*context = gimp_container_view_get_context (GIMP_CONTAINER_VIEW (data));
gimp_container_tree_view_get_selected (GIMP_CONTAINER_VIEW (data), &items, NULL);
gimp_container_tree_view_get_selected (GIMP_CONTAINER_VIEW (data), &items);
return items;
}
@ -1877,8 +1915,8 @@ gimp_container_tree_view_zoom_gesture_update (GtkGestureZoom *gesture,
}
static gboolean
gimp_container_tree_view_get_selected_single (GimpContainerTreeView *tree_view,
GtkTreeIter *iter)
gimp_container_tree_view_get_1_selected (GimpContainerTreeView *tree_view,
GtkTreeIter *iter)
{
GtkTreeSelection *selection;
@ -1903,74 +1941,6 @@ gimp_container_tree_view_get_selected_single (GimpContainerTreeView *tree_view,
}
}
static gint
gimp_container_tree_view_get_selected (GimpContainerView *view,
GList **items,
GList **paths)
{
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
GtkTreeSelection *selection;
gint selected_count;
GList *selected_paths;
GList *removed_paths = NULL;
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)
{
if (paths)
*paths = NULL;
/* just provide selected count */
return selected_count;
}
selected_paths = gtk_tree_selection_get_selected_rows (selection, NULL);
*items = NULL;
for (current_row = selected_paths;
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);
renderer = gimp_container_tree_store_get_renderer (GIMP_CONTAINER_TREE_STORE (tree_view->model),
&iter);
if (renderer->viewable)
*items = g_list_prepend (*items, renderer->viewable);
else
/* Remove from the selected_paths list but at the end, in order not
* to break the for loop.
*/
removed_paths = g_list_prepend (removed_paths, current_row);
g_object_unref (renderer);
}
*items = g_list_reverse (*items);
for (current_row = removed_paths; current_row; current_row = current_row->next)
{
GList *remove_list = current_row->data;
selected_paths = g_list_remove_link (selected_paths, remove_list);
gtk_tree_path_free (remove_list->data);
}
g_list_free_full (removed_paths, (GDestroyNotify) g_list_free);
if (paths)
*paths = selected_paths;
else
g_list_free_full (selected_paths, (GDestroyNotify) gtk_tree_path_free);
return selected_count;
}
static void
gimp_container_tree_view_row_expanded (GtkTreeView *tree_view,
GtkTreeIter *iter,
@ -2064,45 +2034,3 @@ gimp_container_tree_view_monitor_changed (GimpContainerTreeView *view)
gimp_container_tree_view_monitor_changed_foreach,
NULL);
}
typedef struct
{
GimpViewable *viewable;
GtkTreePath *path;
} SearchData;
static gboolean
gimp_container_tree_view_search_path_foreach (GtkTreeModel *model,
GtkTreePath *path,
GtkTreeIter *iter,
gpointer data)
{
SearchData *search_data = data;
GimpViewRenderer *renderer;
renderer = gimp_container_tree_store_get_renderer (GIMP_CONTAINER_TREE_STORE (model),
iter);
if (renderer->viewable == search_data->viewable)
search_data->path = gtk_tree_path_copy (path);
g_object_unref (renderer);
return (search_data->path != NULL);
}
static GtkTreePath *
gimp_container_tree_view_get_path (GimpContainerTreeView *tree_view,
GimpViewable *viewable)
{
SearchData search_data;
search_data.viewable = viewable;
search_data.path = NULL;
gtk_tree_model_foreach (GTK_TREE_MODEL (tree_view->model),
(GtkTreeModelForeachFunc) gimp_container_tree_view_search_path_foreach,
&search_data);
return search_data.path;
}

View file

@ -193,7 +193,6 @@ gimp_container_view_add_foreach (GimpViewable *viewable,
insert_data = view_iface->insert_item (view, viewable,
parent_insert_data, -1);
g_hash_table_insert (private->item_hash, viewable, insert_data);
children = gimp_viewable_get_children (viewable);
@ -363,7 +362,7 @@ gimp_container_view_thaw (GimpContainerView *view,
object = gimp_context_get_by_type (private->context, child_type);
gimp_container_view_select_item (view, GIMP_VIEWABLE (object));
gimp_container_view_set_1_selected (view, GIMP_VIEWABLE (object));
}
}
}

View file

@ -2,7 +2,7 @@
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpcontainerview.c
* Copyright (C) 2001-2010 Michael Natterer <mitch@gimp.org>
* Copyright (C) 2001-2025 Michael Natterer <mitch@gimp.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -44,14 +44,19 @@
enum
{
SELECT_ITEMS,
ACTIVATE_ITEM,
SELECTION_CHANGED,
ITEM_ACTIVATED,
LAST_SIGNAL
};
/* local function prototypes */
static void gimp_container_view_real_selection_changed
(GimpContainerView *view);
static void gimp_container_view_real_item_activated
(GimpContainerView *view,
GimpViewable *item);
static void gimp_container_view_real_set_container (GimpContainerView *view,
GimpContainer *container);
static void gimp_container_view_real_set_context (GimpContainerView *view,
@ -59,10 +64,11 @@ static void gimp_container_view_real_set_context (GimpContainerView *view,
static void gimp_container_view_real_set_selection_mode
(GimpContainerView *view,
GtkSelectionMode mode);
static gboolean
gimp_container_view_real_set_selected (GimpContainerView *view,
GList *list);
static gint gimp_container_view_real_get_selected (GimpContainerView *view,
GList **list,
GList **paths);
GList **list);
static void gimp_container_view_connect_context (GimpContainerView *view);
static void gimp_container_view_disconnect_context (GimpContainerView *view);
@ -98,34 +104,35 @@ static guint view_signals[LAST_SIGNAL] = { 0 };
static void
gimp_container_view_default_init (GimpContainerViewInterface *iface)
{
view_signals[SELECT_ITEMS] =
g_signal_new ("select-items",
G_TYPE_FROM_INTERFACE (iface),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GimpContainerViewInterface, select_items),
NULL, NULL,
NULL,
G_TYPE_BOOLEAN, 2,
G_TYPE_POINTER,
G_TYPE_POINTER);
view_signals[ACTIVATE_ITEM] =
g_signal_new ("activate-item",
view_signals[SELECTION_CHANGED] =
g_signal_new ("selection-changed",
G_TYPE_FROM_INTERFACE (iface),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpContainerViewInterface, activate_item),
G_STRUCT_OFFSET (GimpContainerViewInterface, selection_changed),
NULL, NULL,
gimp_marshal_VOID__OBJECT_POINTER,
G_TYPE_NONE, 2,
GIMP_TYPE_OBJECT,
G_TYPE_POINTER);
NULL,
G_TYPE_NONE, 0);
iface->select_items = NULL;
iface->activate_item = NULL;
view_signals[ITEM_ACTIVATED] =
g_signal_new ("item-activated",
G_TYPE_FROM_INTERFACE (iface),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET (GimpContainerViewInterface, item_activated),
NULL, NULL,
NULL,
G_TYPE_NONE, 1,
GIMP_TYPE_OBJECT);
iface->selection_changed = gimp_container_view_real_selection_changed;
iface->item_activated = gimp_container_view_real_item_activated;
iface->set_container = gimp_container_view_real_set_container;
iface->set_context = gimp_container_view_real_set_context;
iface->set_selection_mode = gimp_container_view_real_set_selection_mode;
iface->set_view_size = NULL;
iface->set_selected = gimp_container_view_real_set_selected;
iface->get_selected = gimp_container_view_real_get_selected;
iface->insert_item = NULL;
iface->insert_items_after = NULL;
iface->remove_item = NULL;
@ -133,8 +140,6 @@ gimp_container_view_default_init (GimpContainerViewInterface *iface)
iface->rename_item = NULL;
iface->expand_item = NULL;
iface->clear_items = _gimp_container_view_real_clear_items;
iface->set_view_size = NULL;
iface->get_selected = gimp_container_view_real_get_selected;
iface->insert_data_free = NULL;
iface->model_is_tree = FALSE;
@ -183,39 +188,8 @@ gimp_container_view_default_init (GimpContainerViewInterface *iface)
G_PARAM_CONSTRUCT));
}
/**
* gimp_container_view_install_properties:
* @klass: the class structure for a type deriving from #GObject
*
* Installs the necessary properties for a class implementing
* #GimpContainerView. A #GimpContainerViewProp property is installed
* for each property, using the values from the #GimpContainerViewProp
* enumeration. The caller must make sure itself that the enumeration
* values don't collide with some other property values they
* are using (that's what %GIMP_CONTAINER_VIEW_PROP_LAST is good for).
**/
void
gimp_container_view_install_properties (GObjectClass *klass)
{
g_object_class_override_property (klass,
GIMP_CONTAINER_VIEW_PROP_CONTAINER,
"container");
g_object_class_override_property (klass,
GIMP_CONTAINER_VIEW_PROP_CONTEXT,
"context");
g_object_class_override_property (klass,
GIMP_CONTAINER_VIEW_PROP_SELECTION_MODE,
"selection-mode");
g_object_class_override_property (klass,
GIMP_CONTAINER_VIEW_PROP_REORDERABLE,
"reorderable");
g_object_class_override_property (klass,
GIMP_CONTAINER_VIEW_PROP_VIEW_SIZE,
"view-size");
g_object_class_override_property (klass,
GIMP_CONTAINER_VIEW_PROP_VIEW_BORDER_WIDTH,
"view-border-width");
}
/* public functions */
GimpContainer *
gimp_container_view_get_container (GimpContainerView *view)
@ -418,66 +392,105 @@ gimp_container_view_enable_dnd (GimpContainerView *view,
}
gboolean
gimp_container_view_select_items (GimpContainerView *view,
gimp_container_view_set_selected (GimpContainerView *view,
GList *viewables)
{
GimpContainerViewPrivate *private;
gboolean success = FALSE;
g_return_val_if_fail (GIMP_IS_CONTAINER_VIEW (view), FALSE);
private = GIMP_CONTAINER_VIEW_GET_PRIVATE (view);
if (gimp_container_frozen (private->container))
return TRUE;
return FALSE;
g_signal_emit (view, view_signals[SELECT_ITEMS], 0,
viewables, NULL, &success);
return success;
return GIMP_CONTAINER_VIEW_GET_IFACE (view)->set_selected (view, viewables);
}
gboolean
gimp_container_view_select_item (GimpContainerView *view,
GimpViewable *viewable)
gimp_container_view_set_1_selected (GimpContainerView *view,
GimpViewable *viewable)
{
GList *viewables = NULL;
gboolean success;
g_return_val_if_fail (GIMP_IS_CONTAINER_VIEW (view), FALSE);
if (viewable)
viewables = g_list_prepend (viewables, viewable);
success = gimp_container_view_select_items (view, viewables);
success = gimp_container_view_set_selected (view, viewables);
g_list_free (viewables);
return success;
}
void
gimp_container_view_activate_item (GimpContainerView *view,
GimpViewable *viewable)
/**
* gimp_container_view_get_selected:
* @view:
* @items:
*
* Get the selected items in @view.
*
* If @items is not %NULL, fills it with a newly allocated #GList of the
* selected items.
*
* Note that by default, the interface only implements some basic single
* selection. Override select_items() signal to get more complete
* selection support.
*
* Returns: the number of selected items.
*/
gint
gimp_container_view_get_selected (GimpContainerView *view,
GList **items)
{
GimpContainerViewPrivate *private;
gpointer insert_data;
g_return_val_if_fail (GIMP_IS_CONTAINER_VIEW (view), 0);
g_return_if_fail (GIMP_IS_CONTAINER_VIEW (view));
g_return_if_fail (GIMP_IS_VIEWABLE (viewable));
if (items)
*items = NULL;
private = GIMP_CONTAINER_VIEW_GET_PRIVATE (view);
if (gimp_container_frozen (private->container))
return;
insert_data = g_hash_table_lookup (private->item_hash, viewable);
g_signal_emit (view, view_signals[ACTIVATE_ITEM], 0,
viewable, insert_data);
return GIMP_CONTAINER_VIEW_GET_IFACE (view)->get_selected (view, items);
}
GimpViewable *
gimp_container_view_get_1_selected (GimpContainerView *view)
{
GimpViewable *item = NULL;
GList *items;
g_return_val_if_fail (GIMP_IS_CONTAINER_VIEW (view), NULL);
if (gimp_container_view_get_selected (view, &items) == 1)
item = items->data;
g_list_free (items);
return item;
}
gboolean
gimp_container_view_is_item_selected (GimpContainerView *view,
GimpViewable *viewable)
{
GList *items;
gboolean found;
gimp_container_view_get_selected (view, &items);
found = (g_list_find (items, viewable) != NULL);
g_list_free (items);
return found;
}
/* protected functions, only to be used by implementors */
gpointer
gimp_container_view_lookup (GimpContainerView *view,
GimpViewable *viewable)
_gimp_container_view_lookup (GimpContainerView *view,
GimpViewable *viewable)
{
GimpContainerViewPrivate *private;
@ -494,8 +507,8 @@ gimp_container_view_lookup (GimpContainerView *view,
}
gboolean
gimp_container_view_contains (GimpContainerView *view,
GList *viewables)
_gimp_container_view_contains (GimpContainerView *view,
GList *viewables)
{
GimpContainerViewPrivate *private;
GList *iter;
@ -514,143 +527,64 @@ gimp_container_view_contains (GimpContainerView *view,
return TRUE;
}
gboolean
gimp_container_view_item_selected (GimpContainerView *view,
GimpViewable *viewable)
void
_gimp_container_view_selection_changed (GimpContainerView *view)
{
GimpContainerViewPrivate *private;
gboolean success;
g_return_if_fail (GIMP_IS_CONTAINER_VIEW (view));
g_return_val_if_fail (GIMP_IS_CONTAINER_VIEW (view), FALSE);
g_return_val_if_fail (GIMP_IS_VIEWABLE (viewable), FALSE);
private = GIMP_CONTAINER_VIEW_GET_PRIVATE (view);
/* HACK */
if (private->container && private->context)
{
GType child_type;
const gchar *signal_name;
child_type = gimp_container_get_child_type (private->container);
signal_name = gimp_context_type_to_signal_name (child_type);
if (signal_name)
{
gimp_context_set_by_type (private->context, child_type,
GIMP_OBJECT (viewable));
return TRUE;
}
}
success = gimp_container_view_select_item (view, viewable);
#if 0
if (success && private->container && private->context)
{
GimpContext *context;
GType child_type;
/* ref and remember the context because private->context may
* become NULL by calling gimp_context_set_by_type()
*/
context = g_object_ref (private->context);
child_type = gimp_container_get_child_type (private->container);
g_signal_handlers_block_by_func (context,
gimp_container_view_context_changed,
view);
gimp_context_set_by_type (context, child_type, GIMP_OBJECT (viewable));
g_signal_handlers_unblock_by_func (context,
gimp_container_view_context_changed,
view);
g_object_unref (context);
}
#endif
return success;
}
gboolean
gimp_container_view_multi_selected (GimpContainerView *view,
GList *items,
GList *items_data)
{
gboolean success = FALSE;
g_return_val_if_fail (GIMP_IS_CONTAINER_VIEW (view), FALSE);
g_signal_emit (view, view_signals[SELECT_ITEMS], 0,
items, items_data, &success);
return success;
}
/**
* gimp_container_view_get_selected:
* @view:
* @items:
* @items_data:
*
* Get the selected items in @view.
*
* If @items is not %NULL, fills it with a newly allocated #GList of the
* selected items.
* If @items_data is not %NULL and if the implementing class associates
* data to its contents, it will be filled with a newly allocated #GList
* of the same size as @items, or will be %NULL otherwise. It is up to
* the class to decide what type of data is passed along.
*
* Note that by default, the interface only implements some basic single
* selection. Override select_items() signal to get more complete
* selection support.
*
* Returns: the number of selected items.
*/
gint
gimp_container_view_get_selected (GimpContainerView *view,
GList **items,
GList **items_data)
{
g_return_val_if_fail (GIMP_IS_CONTAINER_VIEW (view), 0);
return GIMP_CONTAINER_VIEW_GET_IFACE (view)->get_selected (view, items,
items_data);
}
gboolean
gimp_container_view_is_item_selected (GimpContainerView *view,
GimpViewable *viewable)
{
GList *items;
gboolean found;
gimp_container_view_get_selected (view, &items, NULL);
found = (g_list_find (items, viewable) != NULL);
g_list_free (items);
return found;
g_signal_emit (view, view_signals[SELECTION_CHANGED], 0);
}
void
gimp_container_view_item_activated (GimpContainerView *view,
GimpViewable *viewable)
_gimp_container_view_item_activated (GimpContainerView *view,
GimpViewable *viewable)
{
g_return_if_fail (GIMP_IS_CONTAINER_VIEW (view));
g_return_if_fail (GIMP_IS_VIEWABLE (viewable));
gimp_container_view_activate_item (view, viewable);
g_signal_emit (view, view_signals[ITEM_ACTIVATED], 0,
viewable);
}
/**
* gimp_container_view_install_properties:
* @klass: the class structure for a type deriving from #GObject
*
* Installs the necessary properties for a class implementing
* #GimpContainerView. A #GimpContainerViewProp property is installed
* for each property, using the values from the #GimpContainerViewProp
* enumeration. The caller must make sure itself that the enumeration
* values don't collide with some other property values they
* are using (that's what %GIMP_CONTAINER_VIEW_PROP_LAST is good for).
**/
void
_gimp_container_view_install_properties (GObjectClass *klass)
{
g_object_class_override_property (klass,
GIMP_CONTAINER_VIEW_PROP_CONTAINER,
"container");
g_object_class_override_property (klass,
GIMP_CONTAINER_VIEW_PROP_CONTEXT,
"context");
g_object_class_override_property (klass,
GIMP_CONTAINER_VIEW_PROP_SELECTION_MODE,
"selection-mode");
g_object_class_override_property (klass,
GIMP_CONTAINER_VIEW_PROP_REORDERABLE,
"reorderable");
g_object_class_override_property (klass,
GIMP_CONTAINER_VIEW_PROP_VIEW_SIZE,
"view-size");
g_object_class_override_property (klass,
GIMP_CONTAINER_VIEW_PROP_VIEW_BORDER_WIDTH,
"view-border-width");
}
void
gimp_container_view_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
_gimp_container_view_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
GimpContainerView *view = GIMP_CONTAINER_VIEW (object);
@ -684,6 +618,7 @@ gimp_container_view_set_property (GObject *object,
gimp_container_view_set_view_size (view, size, border);
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -691,10 +626,10 @@ gimp_container_view_set_property (GObject *object,
}
void
gimp_container_view_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
_gimp_container_view_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
GimpContainerView *view = GIMP_CONTAINER_VIEW (object);
@ -726,6 +661,7 @@ gimp_container_view_get_property (GObject *object,
g_value_set_int (value, border);
}
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
@ -735,6 +671,58 @@ gimp_container_view_get_property (GObject *object,
/* Private functions */
static void
gimp_container_view_real_selection_changed (GimpContainerView *view)
{
GimpContainerViewPrivate *private = GIMP_CONTAINER_VIEW_GET_PRIVATE (view);
if (private->container && private->context)
{
GType child_type = gimp_container_get_child_type (private->container);
if (gimp_context_type_to_signal_name (child_type))
{
GList *items = NULL;
gint n_items;
n_items = gimp_container_view_get_selected (view, &items);
if (n_items == 1 &&
gimp_context_get_by_type (private->context, child_type) !=
GIMP_OBJECT (items->data))
{
GimpContext *context;
/* ref and remember the context because
* private->context may become NULL by calling
* gimp_context_set_by_type()
*/
context = g_object_ref (private->context);
g_signal_handlers_block_by_func (context,
gimp_container_view_context_changed,
view);
gimp_context_set_by_type (context, child_type, items->data);
g_signal_handlers_unblock_by_func (context,
gimp_container_view_context_changed,
view);
g_object_unref (context);
}
g_list_free (items);
}
}
}
static void
gimp_container_view_real_item_activated (GimpContainerView *view,
GimpViewable *item)
{
}
static void
gimp_container_view_real_set_container (GimpContainerView *view,
GimpContainer *container)
@ -746,7 +734,10 @@ gimp_container_view_real_set_container (GimpContainerView *view,
if (private->context)
gimp_container_view_disconnect_context (view);
gimp_container_view_select_items (view, NULL);
#if 0
/* needed? */
gimp_container_view_set_selected (view, NULL);
#endif
if (! GIMP_CONTAINER_VIEW_GET_IFACE (view)->use_list_model)
_gimp_container_view_disconnect_cruft (view);
@ -792,53 +783,21 @@ gimp_container_view_real_set_selection_mode (GimpContainerView *view,
private->selection_mode = mode;
}
static gboolean
gimp_container_view_real_set_selected (GimpContainerView *view,
GList *items)
{
return FALSE;
}
static gint
gimp_container_view_real_get_selected (GimpContainerView *view,
GList **items,
GList **items_data)
GList **items)
{
GimpContainerViewPrivate *private = GIMP_CONTAINER_VIEW_GET_PRIVATE (view);
GType child_type;
GimpObject *object;
if (items)
if (*items)
*items = NULL;
/* In base interface, @items_data just stays NULL. We don't have a
* concept for it. Classes implementing this interface may want to
* store and pass data for their items, but they will have to
* implement themselves which data, and pass through with this
* parameter.
*/
if (items_data)
*items_data = NULL;
if (! private->container || ! private->context)
return 0;
child_type = gimp_container_get_child_type (private->container);
if (gimp_context_type_to_property (child_type) == -1)
{
/* If you experience this warning, it means you should implement
* your own definition for get_selected() because the default one
* won't work for you (only made for context properties).
*/
g_warning ("%s: TODO: implement GimpContainerViewInterface's get_selected() for type '%s'.\n",
G_STRFUNC, g_type_name (G_OBJECT_TYPE (view)));
return 0;
}
object = gimp_context_get_by_type (private->context,
child_type);
/* Base interface provides the API for multi-selection but only
* implements single selection. Classes must implement their own
* multi-selection.
*/
if (items && object)
*items = g_list_append (*items, object);
return object ? 1 : 0;
return 0;
}
static void
@ -869,7 +828,7 @@ gimp_container_view_connect_context (GimpContainerView *view)
GimpObject *object = gimp_context_get_by_type (private->context,
child_type);
gimp_container_view_select_item (view, GIMP_VIEWABLE (object));
gimp_container_view_set_1_selected (view, GIMP_VIEWABLE (object));
}
}
}
@ -904,23 +863,7 @@ gimp_container_view_context_changed (GimpContext *context,
GimpViewable *viewable,
GimpContainerView *view)
{
GList *viewables = NULL;
if (viewable)
viewables = g_list_prepend (viewables, viewable);
g_signal_handlers_block_by_func (context,
gimp_container_view_context_changed,
view);
if (! gimp_container_view_select_items (view, viewables))
g_warning ("%s: select_items() failed (should not happen)", G_STRFUNC);
g_signal_handlers_unblock_by_func (context,
gimp_container_view_context_changed,
view);
g_list_free (viewables);
gimp_container_view_set_1_selected (view, viewable);
}
static void
@ -936,7 +879,7 @@ gimp_container_view_viewable_dropped (GtkWidget *widget,
if (viewable && private->container &&
gimp_container_have (private->container, GIMP_OBJECT (viewable)))
{
gimp_container_view_item_selected (view, viewable);
gimp_container_view_set_1_selected (view, viewable);
}
}
@ -951,7 +894,7 @@ gimp_container_view_button_viewables_dropped (GtkWidget *widget,
if (viewables)
{
gimp_container_view_multi_selected (view, viewables, NULL);
gimp_container_view_set_selected (view, viewables);
gtk_button_clicked (GTK_BUTTON (widget));
}
@ -966,9 +909,9 @@ gimp_container_view_button_viewable_dropped (GtkWidget *widget,
{
GimpContainerView *view = GIMP_CONTAINER_VIEW (data);
if (viewable && gimp_container_view_lookup (view, viewable))
if (viewable && _gimp_container_view_lookup (view, viewable))
{
gimp_container_view_item_selected (view, viewable);
gimp_container_view_set_1_selected (view, viewable);
gtk_button_clicked (GTK_BUTTON (widget));
}

View file

@ -2,7 +2,7 @@
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
*
* gimpcontainerview.h
* Copyright (C) 2001-2010 Michael Natterer <mitch@gimp.org>
* Copyright (C) 2001-2025 Michael Natterer <mitch@gimp.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -35,7 +35,10 @@ typedef enum
#define GIMP_TYPE_CONTAINER_VIEW (gimp_container_view_get_type ())
G_DECLARE_INTERFACE (GimpContainerView, gimp_container_view, GIMP, CONTAINER_VIEW, GtkWidget)
G_DECLARE_INTERFACE (GimpContainerView,
gimp_container_view,
GIMP, CONTAINER_VIEW,
GtkWidget)
struct _GimpContainerViewInterface
@ -43,22 +46,25 @@ struct _GimpContainerViewInterface
GTypeInterface base_iface;
/* signals */
gboolean (* select_items) (GimpContainerView *view,
GList *items,
GList *paths);
void (* activate_item) (GimpContainerView *view,
GimpViewable *object,
gpointer insert_data);
void (* selection_changed) (GimpContainerView *view);
void (* item_activated) (GimpContainerView *view,
GimpViewable *object);
/* virtual functions */
void (* set_container) (GimpContainerView *view,
GimpContainer *container);
void (* set_context) (GimpContainerView *view,
GimpContext *context);
void (* set_selection_mode) (GimpContainerView *view,
GtkSelectionMode mode);
void (* set_container) (GimpContainerView *view,
GimpContainer *container);
void (* set_context) (GimpContainerView *view,
GimpContext *context);
void (* set_selection_mode) (GimpContainerView *view,
GtkSelectionMode mode);
void (* set_view_size) (GimpContainerView *view);
gboolean (* set_selected) (GimpContainerView *view,
GList *items);
gint (* get_selected) (GimpContainerView *view,
GList **items);
/* cruft */
gpointer (* insert_item) (GimpContainerView *view,
GimpViewable *object,
gpointer parent_insert_data,
@ -78,11 +84,6 @@ struct _GimpContainerViewInterface
GimpViewable *object,
gpointer insert_data);
void (* clear_items) (GimpContainerView *view);
void (* set_view_size) (GimpContainerView *view);
gint (* get_selected) (GimpContainerView *view,
GList **items,
GList **insert_data);
/* the destroy notifier for private->hash_table's values */
GDestroyNotify insert_data_free;
@ -121,42 +122,37 @@ void gimp_container_view_enable_dnd (GimpContainerView *e
GtkButton *button,
GType child_type);
gboolean gimp_container_view_select_items (GimpContainerView *view,
gboolean gimp_container_view_set_selected (GimpContainerView *view,
GList *viewables);
gboolean gimp_container_view_select_item (GimpContainerView *view,
GimpViewable *viewable);
void gimp_container_view_activate_item (GimpContainerView *view,
gboolean gimp_container_view_set_1_selected (GimpContainerView *view,
GimpViewable *viewable);
gint gimp_container_view_get_selected (GimpContainerView *view,
GList **items,
GList **items_data);
GList **items);
GimpViewable * gimp_container_view_get_1_selected (GimpContainerView *view);
gboolean gimp_container_view_is_item_selected (GimpContainerView *view,
GimpViewable *viewable);
/* protected */
gpointer gimp_container_view_lookup (GimpContainerView *view,
gpointer _gimp_container_view_lookup (GimpContainerView *view,
GimpViewable *viewable);
gboolean gimp_container_view_contains (GimpContainerView *view,
gboolean _gimp_container_view_contains (GimpContainerView *view,
GList *viewables);
gboolean gimp_container_view_item_selected (GimpContainerView *view,
GimpViewable *item);
gboolean gimp_container_view_multi_selected (GimpContainerView *view,
GList *items,
GList *paths);
void gimp_container_view_item_activated (GimpContainerView *view,
void _gimp_container_view_selection_changed (GimpContainerView *view);
void _gimp_container_view_item_activated (GimpContainerView *view,
GimpViewable *item);
/* convenience functions */
void gimp_container_view_install_properties (GObjectClass *klass);
void gimp_container_view_set_property (GObject *object,
void _gimp_container_view_install_properties(GObjectClass *klass);
void _gimp_container_view_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec);
void gimp_container_view_get_property (GObject *object,
void _gimp_container_view_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec);

View file

@ -567,7 +567,7 @@ gimp_data_factory_view_select_item (GimpContainerEditor *editor,
GimpContainerView *container_view = GIMP_CONTAINER_VIEW (editor->view);
GList *active_items = NULL;
gimp_container_view_get_selected (container_view, &active_items, NULL);
gimp_container_view_get_selected (container_view, &active_items);
gimp_tag_entry_set_selected_items (GIMP_TAG_ENTRY (view->priv->assign_tag_entry),
active_items);
g_list_free (active_items);

View file

@ -97,10 +97,8 @@ static void gimp_device_editor_remove_device (GimpContainer *container,
static void gimp_device_editor_device_changed (GimpDeviceInfo *info,
GimpDeviceEditor *editor);
static gboolean gimp_device_editor_select_device (GimpContainerView *view,
GList *viewables,
GList *paths,
GimpDeviceEditor *editor);
static void gimp_device_editor_select_device (GimpContainerView *view,
GimpDeviceEditor *editor);
static void gimp_device_editor_delete_clicked (GtkWidget *button,
GimpDeviceEditor *editor);
@ -150,7 +148,7 @@ gimp_device_editor_init (GimpDeviceEditor *editor)
gtk_paned_pack1 (GTK_PANED (editor), private->treeview, TRUE, FALSE);
gtk_widget_show (private->treeview);
g_signal_connect_object (private->treeview, "select-items",
g_signal_connect_object (private->treeview, "selection-changed",
G_CALLBACK (gimp_device_editor_select_device),
G_OBJECT (editor), 0);
@ -367,8 +365,8 @@ gimp_device_editor_add_device (GimpContainer *container,
gimp_object_get_name (info));
gtk_widget_show (widget);
iter = gimp_container_view_lookup (GIMP_CONTAINER_VIEW (private->treeview),
GIMP_VIEWABLE (info));
iter = _gimp_container_view_lookup (GIMP_CONTAINER_VIEW (private->treeview),
GIMP_VIEWABLE (info));
if (iter)
{
@ -392,8 +390,8 @@ gimp_device_editor_remove_device (GimpContainer *container,
GimpDeviceEditorPrivate *private = GIMP_DEVICE_EDITOR_GET_PRIVATE (editor);
GtkTreeIter *iter;
iter = gimp_container_view_lookup (GIMP_CONTAINER_VIEW (private->treeview),
GIMP_VIEWABLE (info));
iter = _gimp_container_view_lookup (GIMP_CONTAINER_VIEW (private->treeview),
GIMP_VIEWABLE (info));
if (iter)
{
@ -418,8 +416,8 @@ gimp_device_editor_device_changed (GimpDeviceInfo *info,
GimpDeviceEditorPrivate *private = GIMP_DEVICE_EDITOR_GET_PRIVATE (editor);
GtkTreeIter *iter;
iter = gimp_container_view_lookup (GIMP_CONTAINER_VIEW (private->treeview),
GIMP_VIEWABLE (info));
iter = _gimp_container_view_lookup (GIMP_CONTAINER_VIEW (private->treeview),
GIMP_VIEWABLE (info));
if (iter)
{
@ -434,17 +432,16 @@ gimp_device_editor_device_changed (GimpDeviceInfo *info,
}
}
static gboolean
static void
gimp_device_editor_select_device (GimpContainerView *view,
GList *viewables,
GList *paths,
GimpDeviceEditor *editor)
{
GimpDeviceEditorPrivate *private = GIMP_DEVICE_EDITOR_GET_PRIVATE (editor);
GimpViewable *item;
g_return_val_if_fail (g_list_length (viewables) < 2, FALSE);
item = gimp_container_view_get_1_selected (view);
if (viewables)
if (item)
{
GimpContainerTreeView *treeview;
GtkWidget *widget;
@ -463,14 +460,15 @@ gimp_device_editor_select_device (GimpContainerView *view,
GIMP_CONTAINER_TREE_STORE_COLUMN_USER_DATA, &widget,
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
-1);
if (renderer->viewable == viewables->data && widget)
if (renderer->viewable == item && widget)
{
GimpDeviceInfo *info;
gboolean delete_sensitive = FALSE;
gtk_stack_set_visible_child (GTK_STACK (private->stack), widget);
g_object_get (widget ,"info", &info, NULL);
g_object_get (widget, "info", &info, NULL);
gtk_label_set_text (GTK_LABEL (private->label),
gimp_object_get_name (info));
@ -488,11 +486,10 @@ gimp_device_editor_select_device (GimpContainerView *view,
break;
}
g_object_unref (renderer);
}
}
return TRUE;
}
static void
@ -506,18 +503,17 @@ gimp_device_editor_delete_response (GtkWidget *dialog,
if (response_id == GTK_RESPONSE_OK)
{
GList *selected;
GimpViewable *item;
if (gimp_container_view_get_selected (GIMP_CONTAINER_VIEW (private->treeview),
&selected, NULL))
item = gimp_container_view_get_1_selected (GIMP_CONTAINER_VIEW (private->treeview));
if (item)
{
GimpContainer *devices;
devices = GIMP_CONTAINER (gimp_devices_get_manager (private->gimp));
gimp_container_remove (devices, selected->data);
g_list_free (selected);
gimp_container_remove (devices, GIMP_OBJECT (item));
}
}
@ -530,10 +526,11 @@ gimp_device_editor_delete_clicked (GtkWidget *button,
{
GimpDeviceEditorPrivate *private = GIMP_DEVICE_EDITOR_GET_PRIVATE (editor);
GtkWidget *dialog;
GList *selected;
GimpViewable *item;
if (! gimp_container_view_get_selected (GIMP_CONTAINER_VIEW (private->treeview),
&selected, NULL))
item = gimp_container_view_get_1_selected (GIMP_CONTAINER_VIEW (private->treeview));
if (! item)
return;
dialog = gimp_message_dialog_new (_("Delete Device Settings"),
@ -558,15 +555,13 @@ gimp_device_editor_delete_clicked (GtkWidget *button,
gimp_message_box_set_primary_text (GIMP_MESSAGE_DIALOG (dialog)->box,
_("Delete \"%s\"?"),
gimp_object_get_name (selected->data));
gimp_object_get_name (item));
gimp_message_box_set_text (GIMP_MESSAGE_DIALOG (dialog)->box,
_("You are about to delete this device's "
"stored settings.\n"
"The next time this device is plugged, "
"default settings will be used."));
g_list_free (selected);
gtk_widget_set_sensitive (GTK_WIDGET (editor), FALSE);
gtk_widget_show (dialog);

View file

@ -83,16 +83,12 @@ struct _GimpDrawableTreeViewFiltersEditor
static void gimp_drawable_filters_editor_set_sensitive
(GimpDrawableTreeView *view);
static gboolean
gimp_drawable_filters_editor_view_select_items
static void gimp_drawable_filters_editor_view_selection_changed
(GimpContainerView *view,
GList *filters,
GList *paths,
GimpDrawableTreeView *drawable_view);
static void gimp_drawable_filters_editor_view_activate_item
static void gimp_drawable_filters_editor_view_item_activated
(GtkWidget *widget,
GimpViewable *viewable,
gpointer insert_data,
GimpDrawableTreeView *view);
static void gimp_drawable_filters_editor_view_visible_cell_toggled
(GtkCellRendererToggle *toggle,
@ -386,11 +382,11 @@ _gimp_drawable_tree_view_filter_editor_show (GimpDrawableTreeView *view,
}
}
g_signal_connect (filter_tree_view, "select-items",
G_CALLBACK (gimp_drawable_filters_editor_view_select_items),
g_signal_connect (filter_tree_view, "selection-changed",
G_CALLBACK (gimp_drawable_filters_editor_view_selection_changed),
view);
g_signal_connect_object (filter_tree_view, "activate-item",
G_CALLBACK (gimp_drawable_filters_editor_view_activate_item),
g_signal_connect_object (filter_tree_view, "item-activated",
G_CALLBACK (gimp_drawable_filters_editor_view_item_activated),
view, 0);
gtk_box_pack_start (GTK_BOX (editor->vbox),
@ -446,10 +442,10 @@ _gimp_drawable_tree_view_filter_editor_hide (GimpDrawableTreeView *view)
if (editor->view)
{
g_signal_handlers_disconnect_by_func (editor->view,
gimp_drawable_filters_editor_view_select_items,
gimp_drawable_filters_editor_view_selection_changed,
view);
g_signal_handlers_disconnect_by_func (editor->view,
gimp_drawable_filters_editor_view_activate_item,
gimp_drawable_filters_editor_view_item_activated,
view);
g_clear_pointer (&editor->view, gtk_widget_destroy);
@ -529,37 +525,38 @@ gimp_drawable_filters_editor_set_sensitive (GimpDrawableTreeView *view)
}
}
static gboolean
gimp_drawable_filters_editor_view_select_items (GimpContainerView *view,
GList *filters,
GList *paths,
GimpDrawableTreeView *drawable_view)
static void
gimp_drawable_filters_editor_view_selection_changed (GimpContainerView *view,
GimpDrawableTreeView *drawable_view)
{
GimpDrawableTreeViewFiltersEditor *editor = drawable_view->editor;
GList *items;
gint n_items;
g_return_val_if_fail (g_list_length (filters) <= 1, FALSE);
n_items = gimp_container_view_get_selected (view, &items);
g_warn_if_fail (n_items <= 1);
editor->filter = NULL;
if (filters)
if (items)
{
/* Don't set floating selection as active filter */
if (GIMP_IS_DRAWABLE_FILTER (filters->data))
if (GIMP_IS_DRAWABLE_FILTER (items->data))
{
editor->filter = filters->data;
editor->filter = items->data;
}
}
gimp_drawable_filters_editor_set_sensitive (drawable_view);
return FALSE;
g_list_free (items);
}
static void
gimp_drawable_filters_editor_view_activate_item (GtkWidget *widget,
GimpViewable *viewable,
gpointer insert_data,
GimpDrawableTreeView *view)
gimp_drawable_filters_editor_view_item_activated (GtkWidget *widget,
GimpViewable *viewable,
GimpDrawableTreeView *view)
{
GimpDrawableTreeViewFiltersEditor *editor = view->editor;
@ -614,8 +611,8 @@ gimp_drawable_filters_editor_active_changed (GimpFilter *filter,
{
GtkTreeIter *iter;
iter = gimp_container_view_lookup (GIMP_CONTAINER_VIEW (view),
(GimpViewable *) filter);
iter = _gimp_container_view_lookup (GIMP_CONTAINER_VIEW (view),
(GimpViewable *) filter);
if (iter)
gtk_tree_store_set (GTK_TREE_STORE (view->model), iter,

View file

@ -76,15 +76,14 @@ static void gimp_drawable_tree_view_style_updated (GtkWidget
static void gimp_drawable_tree_view_set_container (GimpContainerView *view,
GimpContainer *container);
static gboolean gimp_drawable_tree_view_set_selected (GimpContainerView *view,
GList *items);
static gpointer gimp_drawable_tree_view_insert_item (GimpContainerView *view,
GimpViewable *viewable,
gpointer parent_insert_data,
gint index);
static gboolean gimp_drawable_tree_view_select_items (GimpContainerView *view,
GList *items,
GList *paths);
static gboolean gimp_drawable_tree_view_drop_possible (GimpContainerTreeView *view,
GimpDndType src_type,
GList *src_viewables,
@ -182,8 +181,9 @@ gimp_drawable_tree_view_view_iface_init (GimpContainerViewInterface *iface)
parent_view_iface = g_type_interface_peek_parent (iface);
iface->set_container = gimp_drawable_tree_view_set_container;
iface->set_selected = gimp_drawable_tree_view_set_selected;
iface->insert_item = gimp_drawable_tree_view_insert_item;
iface->select_items = gimp_drawable_tree_view_select_items;
}
static void
@ -340,36 +340,9 @@ gimp_drawable_tree_view_set_container (GimpContainerView *view,
view);
}
static gpointer
gimp_drawable_tree_view_insert_item (GimpContainerView *view,
GimpViewable *viewable,
gpointer parent_insert_data,
gint index)
{
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
GimpDrawableTreeView *drawable_view = GIMP_DRAWABLE_TREE_VIEW (view);
GimpContainer *filters;
GtkTreeIter *iter;
gint n_filters;
iter = parent_view_iface->insert_item (view, viewable,
parent_insert_data, index);
filters = gimp_drawable_get_filters (GIMP_DRAWABLE (viewable));
n_filters = gimp_container_get_n_children (filters);
gtk_tree_store_set (GTK_TREE_STORE (tree_view->model), iter,
drawable_view->priv->model_column_filters,
n_filters > 0,
-1);
return iter;
}
static gboolean
gimp_drawable_tree_view_select_items (GimpContainerView *view,
GList *items,
GList *paths)
gimp_drawable_tree_view_set_selected (GimpContainerView *view,
GList *items)
{
GimpItemTreeView *item_view = GIMP_ITEM_TREE_VIEW (view);
GimpImage *image = gimp_item_tree_view_get_image (item_view);
@ -397,11 +370,38 @@ gimp_drawable_tree_view_select_items (GimpContainerView *view,
}
if (success)
success = parent_view_iface->select_items (view, items, paths);
success = parent_view_iface->set_selected (view, items);
return success;
}
static gpointer
gimp_drawable_tree_view_insert_item (GimpContainerView *view,
GimpViewable *viewable,
gpointer parent_insert_data,
gint index)
{
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
GimpDrawableTreeView *drawable_view = GIMP_DRAWABLE_TREE_VIEW (view);
GimpContainer *filters;
GtkTreeIter *iter;
gint n_filters;
iter = parent_view_iface->insert_item (view, viewable,
parent_insert_data, index);
filters = gimp_drawable_get_filters (GIMP_DRAWABLE (viewable));
n_filters = gimp_container_get_n_children (filters);
gtk_tree_store_set (GTK_TREE_STORE (tree_view->model), iter,
drawable_view->priv->model_column_filters,
n_filters > 0,
-1);
return iter;
}
/* GimpContainerTreeView methods */
static gboolean
@ -567,7 +567,7 @@ gimp_drawable_tree_view_floating_selection_changed (GimpImage *image,
items = g_list_copy (items);
/* update button states */
gimp_container_view_select_items (GIMP_CONTAINER_VIEW (view), items);
gimp_container_view_set_selected (GIMP_CONTAINER_VIEW (view), items);
g_list_free (items);
}
@ -582,8 +582,8 @@ gimp_drawable_tree_view_filters_changed (GimpDrawable *drawable,
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
GtkTreeIter *iter;
iter = gimp_container_view_lookup (GIMP_CONTAINER_VIEW (view),
(GimpViewable *) drawable);
iter = _gimp_container_view_lookup (GIMP_CONTAINER_VIEW (view),
(GimpViewable *) drawable);
if (iter)
{

View file

@ -105,6 +105,8 @@ struct _GimpItemTreeViewPrivate
GtkWidget *multi_selection_label;
GtkWidget *search_button;
gint block_selection_changed;
};
typedef struct
@ -153,6 +155,10 @@ static void gimp_item_tree_view_image_flush (GimpImage *image,
static gboolean
gimp_item_tree_view_image_flush_idle (gpointer user_data);
static void gimp_item_tree_view_selection_changed (GimpContainerView *view);
static void gimp_item_tree_view_item_activated (GimpContainerView *view,
GimpViewable *item);
static void gimp_item_tree_view_set_container (GimpContainerView *view,
GimpContainer *container);
static void gimp_item_tree_view_set_context (GimpContainerView *view,
@ -163,12 +169,6 @@ static gpointer gimp_item_tree_view_insert_item (GimpContainerView *view,
gpointer parent_insert_data,
gint index);
static void gimp_item_tree_view_insert_items_after (GimpContainerView *view);
static gboolean gimp_item_tree_view_select_items (GimpContainerView *view,
GList *items,
GList *paths);
static void gimp_item_tree_view_activate_item (GimpContainerView *view,
GimpViewable *item,
gpointer insert_data);
static gboolean gimp_item_tree_view_drop_possible (GimpContainerTreeView *view,
GimpDndType src_type,
@ -194,7 +194,7 @@ static void gimp_item_tree_view_new_list_dropped (GtkWidget *widget,
GList *viewables,
gpointer data);
static void gimp_item_tree_view_item_changed (GimpImage *image,
static void gimp_item_tree_view_items_changed (GimpImage *image,
GimpItemTreeView *view);
static void gimp_item_tree_view_size_changed (GimpImage *image,
GimpItemTreeView *view);
@ -346,12 +346,13 @@ gimp_item_tree_view_view_iface_init (GimpContainerViewInterface *iface)
{
parent_view_iface = g_type_interface_peek_parent (iface);
iface->selection_changed = gimp_item_tree_view_selection_changed;
iface->item_activated = gimp_item_tree_view_item_activated;
iface->set_container = gimp_item_tree_view_set_container;
iface->set_context = gimp_item_tree_view_set_context;
iface->insert_item = gimp_item_tree_view_insert_item;
iface->insert_items_after = gimp_item_tree_view_insert_items_after;
iface->select_items = gimp_item_tree_view_select_items;
iface->activate_item = gimp_item_tree_view_activate_item;
}
static void
@ -862,8 +863,6 @@ gimp_item_tree_view_set_image (GimpItemTreeView *view,
g_return_if_fail (image == NULL || GIMP_IS_IMAGE (image));
g_signal_emit (view, view_signals[SET_IMAGE], 0, image);
gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (view)), view);
}
GimpImage *
@ -1022,8 +1021,8 @@ gimp_item_tree_view_blink_lock (GimpItemTreeView *view,
g_return_if_fail (GIMP_IS_ITEM (item));
/* Find the item in the tree view. */
iter = gimp_container_view_lookup (GIMP_CONTAINER_VIEW (view),
(GimpViewable *) item);
iter = _gimp_container_view_lookup (GIMP_CONTAINER_VIEW (view),
GIMP_VIEWABLE (item));
path = gtk_tree_model_get_path (GIMP_CONTAINER_TREE_VIEW (view)->model, iter);
/* Scroll dockable to make sure the cell is showing. */
@ -1113,7 +1112,7 @@ gimp_item_tree_view_real_set_image (GimpItemTreeView *view,
if (view->priv->image)
{
g_signal_handlers_disconnect_by_func (view->priv->image,
gimp_item_tree_view_item_changed,
gimp_item_tree_view_items_changed,
view);
g_signal_handlers_disconnect_by_func (view->priv->image,
gimp_item_tree_view_size_changed,
@ -1148,7 +1147,7 @@ gimp_item_tree_view_real_set_image (GimpItemTreeView *view,
g_signal_connect (view->priv->image,
GIMP_ITEM_TREE_VIEW_GET_CLASS (view)->signal_name,
G_CALLBACK (gimp_item_tree_view_item_changed),
G_CALLBACK (gimp_item_tree_view_items_changed),
view);
g_signal_connect (view->priv->image, "size-changed",
G_CALLBACK (gimp_item_tree_view_size_changed),
@ -1167,7 +1166,7 @@ gimp_item_tree_view_real_set_image (GimpItemTreeView *view,
G_CALLBACK (gimp_item_tree_view_floating_selection_changed),
view);
gimp_item_tree_view_item_changed (view->priv->image, view);
gimp_item_tree_view_items_changed (view->priv->image, view);
}
/* Call this even with no image, allowing to empty the link list. */
@ -1244,6 +1243,44 @@ gimp_item_tree_view_image_flush_idle (gpointer user_data)
/* GimpContainerView methods */
static void
gimp_item_tree_view_selection_changed (GimpContainerView *view)
{
GimpItemTreeViewClass *item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (view);
GimpItemTreeView *item_view = GIMP_ITEM_TREE_VIEW (view);
parent_view_iface->selection_changed (view);
if (item_view->priv->block_selection_changed == 0)
{
GList *items;
gimp_container_view_get_selected (view, &items);
gimp_image_set_selected_items (item_view->priv->image,
item_view_class->item_type,
items);
g_list_free (items);
}
}
static void
gimp_item_tree_view_item_activated (GimpContainerView *view,
GimpViewable *item)
{
GimpItemTreeViewClass *item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (view);
parent_view_iface->item_activated (view, item);
if (item_view_class->activate_action)
{
gimp_ui_manager_activate_action (gimp_editor_get_ui_manager (GIMP_EDITOR (view)),
item_view_class->action_group,
item_view_class->activate_action);
}
}
static void
gimp_item_tree_view_set_container (GimpContainerView *view,
GimpContainer *container)
@ -1409,79 +1446,7 @@ gimp_item_tree_view_insert_items_after (GimpContainerView *view)
selected_items = gimp_image_get_selected_items (item_view->priv->image,
item_view_class->item_type);
gimp_container_view_select_items (view, selected_items);
}
static gboolean
gimp_item_tree_view_select_items (GimpContainerView *view,
GList *items,
GList *paths)
{
GimpItemTreeView *tree_view = GIMP_ITEM_TREE_VIEW (view);
gboolean options_sensitive = FALSE;
gboolean success;
success = parent_view_iface->select_items (view, items, paths);
if (items)
{
GimpItemTreeViewClass *item_view_class;
item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (tree_view);
if (TRUE) /* XXX: test if new selection same as old. */
{
gimp_image_set_selected_items (tree_view->priv->image,
item_view_class->item_type,
items);
items = gimp_image_get_selected_items (tree_view->priv->image,
item_view_class->item_type);
}
options_sensitive = TRUE;
}
gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (tree_view)), tree_view);
if (tree_view->priv->options_box)
gtk_widget_set_sensitive (tree_view->priv->options_box, options_sensitive);
if (g_list_length (items) > 1)
{
gchar *str;
str = g_strdup_printf (ngettext ("%d item selected", "%d items selected",
g_list_length (items)),
g_list_length (items));
gtk_label_set_text (GTK_LABEL (tree_view->priv->multi_selection_label), str);
g_free (str);
gtk_widget_set_opacity (tree_view->priv->multi_selection_label, 1.0);
}
else
{
gtk_widget_set_opacity (tree_view->priv->multi_selection_label, 0.0);
}
return success;
}
static void
gimp_item_tree_view_activate_item (GimpContainerView *view,
GimpViewable *item,
gpointer insert_data)
{
GimpItemTreeViewClass *item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (view);
if (parent_view_iface->activate_item)
parent_view_iface->activate_item (view, item, insert_data);
if (item_view_class->activate_action)
{
gimp_ui_manager_activate_action (gimp_editor_get_ui_manager (GIMP_EDITOR (view)),
item_view_class->action_group,
item_view_class->activate_action);
}
gimp_container_view_set_selected (view, selected_items);
}
static gboolean
@ -1707,7 +1672,7 @@ gimp_item_tree_view_new_dropped (GtkWidget *widget,
GimpContainerView *view = GIMP_CONTAINER_VIEW (data);
if (item_view_class->new_default_action &&
viewable && gimp_container_view_lookup (view, viewable))
viewable && _gimp_container_view_lookup (view, viewable))
{
GimpAction *action;
@ -1740,24 +1705,52 @@ gimp_item_tree_view_new_list_dropped (GtkWidget *widget,
item_view_class->new_default_action);
if (item_view_class->new_default_action && viewables && action &&
gimp_container_view_contains (view, viewables))
_gimp_container_view_contains (view, viewables))
gimp_action_activate (action);
}
/* GimpImage callbacks */
static void
gimp_item_tree_view_item_changed (GimpImage *image,
GimpItemTreeView *view)
gimp_item_tree_view_items_changed (GimpImage *image,
GimpItemTreeView *item_view)
{
GType item_type;
GList *items;
item_type = GIMP_ITEM_TREE_VIEW_GET_CLASS (view)->item_type;
item_type = GIMP_ITEM_TREE_VIEW_GET_CLASS (item_view)->item_type;
items = gimp_image_get_selected_items (view->priv->image, item_type);
items = gimp_image_get_selected_items (item_view->priv->image, item_type);
gimp_container_view_select_items (GIMP_CONTAINER_VIEW (view), items);
item_view->priv->block_selection_changed++;
gimp_container_view_set_selected (GIMP_CONTAINER_VIEW (item_view), items);
item_view->priv->block_selection_changed--;
gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (item_view)),
item_view);
if (item_view->priv->options_box)
gtk_widget_set_sensitive (item_view->priv->options_box, items != NULL);
if (g_list_length (items) > 1)
{
gchar *str;
str = g_strdup_printf (ngettext ("%d item selected", "%d items selected",
g_list_length (items)),
g_list_length (items));
gtk_label_set_text (GTK_LABEL (item_view->priv->multi_selection_label),
str);
g_free (str);
gtk_widget_set_opacity (item_view->priv->multi_selection_label, 1.0);
}
else
{
gtk_widget_set_opacity (item_view->priv->multi_selection_label, 0.0);
}
}
static void
@ -1842,8 +1835,7 @@ gimp_item_tree_view_visible_changed (GimpItem *item,
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
GtkTreeIter *iter;
iter = gimp_container_view_lookup (container_view,
(GimpViewable *) item);
iter = _gimp_container_view_lookup (container_view, GIMP_VIEWABLE (item));
if (iter)
{
@ -1980,8 +1972,7 @@ gimp_item_tree_view_color_tag_changed (GimpItem *item,
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
GtkTreeIter *iter;
iter = gimp_container_view_lookup (container_view,
(GimpViewable *) item);
iter = _gimp_container_view_lookup (container_view, GIMP_VIEWABLE (item));
if (iter)
{
@ -2024,8 +2015,7 @@ gimp_item_tree_view_lock_changed (GimpItem *item,
const gchar *icon_name;
gint n_locks;
iter = gimp_container_view_lookup (container_view,
(GimpViewable *) item);
iter = _gimp_container_view_lookup (container_view, GIMP_VIEWABLE (item));
n_locks = gimp_item_tree_view_get_n_locks (view, item, &icon_name);
@ -2291,7 +2281,7 @@ gimp_item_tree_view_row_expanded (GtkTreeView *tree_view,
GimpViewRenderer *renderer;
GimpItem *expanded_item;
store = GIMP_CONTAINER_TREE_STORE (GIMP_CONTAINER_TREE_VIEW (item_view)->model);
store = GIMP_CONTAINER_TREE_STORE (GIMP_CONTAINER_TREE_VIEW (item_view)->model);
renderer = gimp_container_tree_store_get_renderer (store, iter);
expanded_item = GIMP_ITEM (renderer->viewable);
g_object_unref (renderer);
@ -2299,8 +2289,8 @@ gimp_item_tree_view_row_expanded (GtkTreeView *tree_view,
for (list = selected_items; list; list = list->next)
{
/* don't select an item while it is being inserted */
if (! gimp_container_view_lookup (GIMP_CONTAINER_VIEW (item_view),
list->data))
if (! _gimp_container_view_lookup (GIMP_CONTAINER_VIEW (item_view),
list->data))
return;
/* select items only if they were made visible by expanding
@ -2310,8 +2300,12 @@ gimp_item_tree_view_row_expanded (GtkTreeView *tree_view,
return;
}
gimp_container_view_select_items (GIMP_CONTAINER_VIEW (item_view),
item_view->priv->block_selection_changed++;
gimp_container_view_set_selected (GIMP_CONTAINER_VIEW (item_view),
selected_items);
item_view->priv->block_selection_changed--;
}
}

View file

@ -100,14 +100,14 @@ static void gimp_layer_tree_view_set_container (GimpContainer
GimpContainer *container);
static void gimp_layer_tree_view_set_context (GimpContainerView *view,
GimpContext *context);
static void gimp_layer_tree_view_set_view_size (GimpContainerView *view);
static gboolean gimp_layer_tree_view_set_selected (GimpContainerView *view,
GList *items);
static gpointer gimp_layer_tree_view_insert_item (GimpContainerView *view,
GimpViewable *viewable,
gpointer parent_insert_data,
gint index);
static gboolean gimp_layer_tree_view_select_items (GimpContainerView *view,
GList *items,
GList *paths);
static void gimp_layer_tree_view_set_view_size (GimpContainerView *view);
static gboolean gimp_layer_tree_view_drop_possible (GimpContainerTreeView *view,
GimpDndType src_type,
GList *src_viewables,
@ -242,9 +242,10 @@ gimp_layer_tree_view_view_iface_init (GimpContainerViewInterface *iface)
iface->set_container = gimp_layer_tree_view_set_container;
iface->set_context = gimp_layer_tree_view_set_context;
iface->insert_item = gimp_layer_tree_view_insert_item;
iface->select_items = gimp_layer_tree_view_select_items;
iface->set_view_size = gimp_layer_tree_view_set_view_size;
iface->set_selected = gimp_layer_tree_view_set_selected;
iface->insert_item = gimp_layer_tree_view_insert_item;
iface->model_is_tree = TRUE;
}
@ -539,114 +540,6 @@ gimp_layer_tree_view_set_context (GimpContainerView *view,
}
}
static gpointer
gimp_layer_tree_view_insert_item (GimpContainerView *view,
GimpViewable *viewable,
gpointer parent_insert_data,
gint index)
{
GimpLayerTreeView *layer_view = GIMP_LAYER_TREE_VIEW (view);
GimpLayer *layer;
GtkTreeIter *iter;
iter = parent_view_iface->insert_item (view, viewable,
parent_insert_data, index);
layer = GIMP_LAYER (viewable);
if (! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
gimp_layer_tree_view_alpha_update (layer_view, iter, layer);
gimp_layer_tree_view_mask_update (layer_view, iter, layer);
if (GIMP_IS_LAYER (viewable) && gimp_layer_is_floating_sel (GIMP_LAYER (viewable)))
{
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
GimpLayer *floating = GIMP_LAYER (viewable);
GimpDrawable *drawable = gimp_layer_get_floating_sel_drawable (floating);
if (GIMP_IS_LAYER_MASK (drawable))
{
/* Display floating mask in the mask column. */
GimpViewRenderer *renderer = NULL;
gtk_tree_model_get (GTK_TREE_MODEL (tree_view->model), iter,
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
-1);
if (renderer)
{
gtk_tree_store_set (GTK_TREE_STORE (tree_view->model), iter,
layer_view->priv->model_column_mask, renderer,
layer_view->priv->model_column_mask_visible, TRUE,
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, NULL,
-1);
g_object_unref (renderer);
}
}
}
return iter;
}
static gboolean
gimp_layer_tree_view_select_items (GimpContainerView *view,
GList *items,
GList *paths)
{
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
GimpLayerTreeView *layer_view = GIMP_LAYER_TREE_VIEW (view);
GList *layers = items;
GList *path = paths;
gboolean success;
success = parent_view_iface->select_items (view, items, paths);
if (layers)
{
if (success)
{
if (g_list_length (items) == 1)
{
GtkTreeIter *iter = NULL;
iter =
gimp_container_view_lookup (GIMP_CONTAINER_VIEW (layer_view),
GIMP_VIEWABLE (layers->data));
if (iter)
gimp_layer_tree_view_update_borders (layer_view, iter);
}
else
{
for (layers = items, path = paths;
layers && path;
layers = layers->next, path = path->next)
{
GtkTreeIter iter;
gtk_tree_model_get_iter (tree_view->model, &iter,
path->data);
gimp_layer_tree_view_update_borders (layer_view, &iter);
}
}
gimp_layer_tree_view_update_options (layer_view, items);
}
}
if (! success)
{
GimpEditor *editor = GIMP_EDITOR (view);
/* currently, select_items() only ever fails when there is a floating
* selection, which can be committed/canceled through the editor buttons.
*/
gimp_widget_blink (GTK_WIDGET (gimp_editor_get_button_box (editor)));
}
return success;
}
typedef struct
{
gint mask_column;
@ -702,6 +595,95 @@ gimp_layer_tree_view_set_view_size (GimpContainerView *view)
parent_view_iface->set_view_size (view);
}
static gboolean
gimp_layer_tree_view_set_selected (GimpContainerView *view,
GList *items)
{
GimpLayerTreeView *layer_view = GIMP_LAYER_TREE_VIEW (view);
gboolean success;
success = parent_view_iface->set_selected (view, items);
if (items && success)
{
GList *list;
for (list = items; list; list = g_list_next (list))
{
GtkTreeIter *iter;
iter = _gimp_container_view_lookup (view, list->data);
if (iter)
gimp_layer_tree_view_update_borders (layer_view, iter);
}
gimp_layer_tree_view_update_options (layer_view, items);
}
if (! success)
{
GimpEditor *editor = GIMP_EDITOR (view);
/* currently, select_items() only ever fails when there is a
* floating selection, which can be committed/canceled through
* the editor buttons.
*/
gimp_widget_blink (GTK_WIDGET (gimp_editor_get_button_box (editor)));
}
return success;
}
static gpointer
gimp_layer_tree_view_insert_item (GimpContainerView *view,
GimpViewable *viewable,
gpointer parent_insert_data,
gint index)
{
GimpLayerTreeView *layer_view = GIMP_LAYER_TREE_VIEW (view);
GimpLayer *layer;
GtkTreeIter *iter;
iter = parent_view_iface->insert_item (view, viewable,
parent_insert_data, index);
layer = GIMP_LAYER (viewable);
if (! gimp_drawable_has_alpha (GIMP_DRAWABLE (layer)))
gimp_layer_tree_view_alpha_update (layer_view, iter, layer);
gimp_layer_tree_view_mask_update (layer_view, iter, layer);
if (GIMP_IS_LAYER (viewable) && gimp_layer_is_floating_sel (GIMP_LAYER (viewable)))
{
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
GimpLayer *floating = GIMP_LAYER (viewable);
GimpDrawable *drawable = gimp_layer_get_floating_sel_drawable (floating);
if (GIMP_IS_LAYER_MASK (drawable))
{
/* Display floating mask in the mask column. */
GimpViewRenderer *renderer = NULL;
gtk_tree_model_get (GTK_TREE_MODEL (tree_view->model), iter,
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, &renderer,
-1);
if (renderer)
{
gtk_tree_store_set (GTK_TREE_STORE (tree_view->model), iter,
layer_view->priv->model_column_mask, renderer,
layer_view->priv->model_column_mask_visible, TRUE,
GIMP_CONTAINER_TREE_STORE_COLUMN_RENDERER, NULL,
-1);
g_object_unref (renderer);
}
}
}
return iter;
}
/* GimpContainerTreeView methods */
@ -963,7 +945,7 @@ gimp_layer_tree_view_floating_selection_changed (GimpImage *image,
if (floating_sel)
{
iter = gimp_container_view_lookup (view, (GimpViewable *) floating_sel);
iter = _gimp_container_view_lookup (view, (GimpViewable *) floating_sel);
if (iter)
gtk_tree_store_set (GTK_TREE_STORE (tree_view->model), iter,
@ -982,7 +964,7 @@ gimp_layer_tree_view_floating_selection_changed (GimpImage *image,
{
GimpDrawable *drawable = list->data;
iter = gimp_container_view_lookup (view, (GimpViewable *) drawable);
iter = _gimp_container_view_lookup (view, (GimpViewable *) drawable);
if (iter)
gtk_tree_store_set (GTK_TREE_STORE (tree_view->model), iter,
@ -1333,7 +1315,7 @@ gimp_layer_tree_view_mask_changed (GimpLayer *layer,
GimpContainerView *view = GIMP_CONTAINER_VIEW (layer_view);
GtkTreeIter *iter;
iter = gimp_container_view_lookup (view, GIMP_VIEWABLE (layer));
iter = _gimp_container_view_lookup (view, GIMP_VIEWABLE (layer));
if (iter)
gimp_layer_tree_view_mask_update (layer_view, iter, layer);
@ -1350,8 +1332,8 @@ gimp_layer_tree_view_renderer_update (GimpViewRenderer *renderer,
mask = GIMP_LAYER_MASK (renderer->viewable);
iter = gimp_container_view_lookup (view, (GimpViewable *)
gimp_layer_mask_get_layer (mask));
iter = _gimp_container_view_lookup (view, (GimpViewable *)
gimp_layer_mask_get_layer (mask));
if (iter)
{
@ -1440,7 +1422,7 @@ gimp_layer_tree_view_mask_callback (GimpLayer *layer,
GimpContainerView *view = GIMP_CONTAINER_VIEW (layer_view);
GtkTreeIter *iter;
iter = gimp_container_view_lookup (view, (GimpViewable *) layer);
iter = _gimp_container_view_lookup (view, (GimpViewable *) layer);
gimp_layer_tree_view_update_borders (layer_view, iter);
}
@ -1667,18 +1649,22 @@ gimp_layer_tree_view_alpha_changed (GimpLayer *layer,
GimpContainerView *view = GIMP_CONTAINER_VIEW (layer_view);
GtkTreeIter *iter;
iter = gimp_container_view_lookup (view, (GimpViewable *) layer);
iter = _gimp_container_view_lookup (view, (GimpViewable *) layer);
if (iter)
{
GimpItemTreeView *item_view = GIMP_ITEM_TREE_VIEW (view);
GimpImage *image;
GList *layers;
gimp_layer_tree_view_alpha_update (layer_view, iter, layer);
image = gimp_item_tree_view_get_image (item_view);
layers = gimp_image_get_selected_layers (image);
/* update button states */
if (g_list_find (gimp_image_get_selected_layers (gimp_item_tree_view_get_image (item_view)),
layer))
gimp_container_view_select_items (GIMP_CONTAINER_VIEW (view),
gimp_image_get_selected_layers (gimp_item_tree_view_get_image (item_view)));
if (g_list_find (layers, layer))
gimp_container_view_set_selected (GIMP_CONTAINER_VIEW (view),
layers);
}
}

View file

@ -91,13 +91,10 @@ static void gimp_pickable_chooser_get_property (GObject *object,
static void gimp_pickable_chooser_image_changed (GimpContext *context,
GimpImage *image,
GimpPickableChooser *chooser);
static void gimp_pickable_chooser_item_activate (GimpContainerView *view,
static void gimp_pickable_chooser_item_activated (GimpContainerView *view,
GimpPickable *pickable,
gpointer unused,
GimpPickableChooser *chooser);
static void gimp_pickable_chooser_items_selected (GimpContainerView *view,
GList *items,
GList *paths,
GimpPickableChooser *chooser);
@ -122,7 +119,7 @@ gimp_pickable_chooser_class_init (GimpPickableChooserClass *klass)
* @chooser:
*
* Emitted when a pickable is activated, which is mostly forwarding when
* "activate-item" signal is emitted from any of either the image, layer or
* "item-activated" signal is emitted from any of either the image, layer or
* channel view. E.g. this happens when one double-click on one of the
* pickables.
*/
@ -229,10 +226,10 @@ gimp_pickable_chooser_constructed (GObject *object)
gtk_box_pack_start (GTK_BOX (vbox), chooser->priv->image_view, TRUE, TRUE, 0);
gtk_widget_show (chooser->priv->image_view);
g_signal_connect_object (chooser->priv->image_view, "activate-item",
G_CALLBACK (gimp_pickable_chooser_item_activate),
g_signal_connect_object (chooser->priv->image_view, "item-activated",
G_CALLBACK (gimp_pickable_chooser_item_activated),
G_OBJECT (chooser), 0);
g_signal_connect_object (chooser->priv->image_view, "select-items",
g_signal_connect_object (chooser->priv->image_view, "selection-changed",
G_CALLBACK (gimp_pickable_chooser_items_selected),
G_OBJECT (chooser), 0);
@ -270,10 +267,10 @@ gimp_pickable_chooser_constructed (GObject *object)
gtk_label_new (_("Layers")));
gtk_widget_show (chooser->priv->layer_view);
g_signal_connect_object (chooser->priv->layer_view, "activate-item",
G_CALLBACK (gimp_pickable_chooser_item_activate),
g_signal_connect_object (chooser->priv->layer_view, "item-activated",
G_CALLBACK (gimp_pickable_chooser_item_activated),
G_OBJECT (chooser), 0);
g_signal_connect_object (chooser->priv->layer_view, "select-items",
g_signal_connect_object (chooser->priv->layer_view, "selection-changed",
G_CALLBACK (gimp_pickable_chooser_items_selected),
G_OBJECT (chooser), 0);
}
@ -295,10 +292,10 @@ gimp_pickable_chooser_constructed (GObject *object)
gtk_label_new (_("Channels")));
gtk_widget_show (chooser->priv->channel_view);
g_signal_connect_object (chooser->priv->channel_view, "activate-item",
G_CALLBACK (gimp_pickable_chooser_item_activate),
g_signal_connect_object (chooser->priv->channel_view, "item-activated",
G_CALLBACK (gimp_pickable_chooser_item_activated),
G_OBJECT (chooser), 0);
g_signal_connect_object (chooser->priv->channel_view, "select-items",
g_signal_connect_object (chooser->priv->channel_view, "selection-changed",
G_CALLBACK (gimp_pickable_chooser_items_selected),
G_OBJECT (chooser), 0);
}
@ -456,37 +453,37 @@ gimp_pickable_chooser_set_pickable (GimpPickableChooser *chooser,
if (GIMP_IS_IMAGE (pickable))
{
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (chooser->priv->image_view),
GIMP_VIEWABLE (pickable));
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (chooser->priv->image_view),
GIMP_VIEWABLE (pickable));
gimp_context_set_image (chooser->priv->context, GIMP_IMAGE (pickable));
}
else if (GIMP_IS_LAYER (pickable))
{
gimp_context_set_image (chooser->priv->context, gimp_item_get_image (GIMP_ITEM (pickable)));
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (chooser->priv->layer_view),
GIMP_VIEWABLE (pickable));
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (chooser->priv->layer_view),
GIMP_VIEWABLE (pickable));
}
else if (GIMP_IS_CHANNEL (pickable))
{
gimp_context_set_image (chooser->priv->context, gimp_item_get_image (GIMP_ITEM (pickable)));
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (chooser->priv->channel_view),
GIMP_VIEWABLE (pickable));
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (chooser->priv->channel_view),
GIMP_VIEWABLE (pickable));
}
else
{
g_return_if_fail (pickable == NULL);
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (chooser->priv->image_view), NULL);
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (chooser->priv->image_view), NULL);
gimp_context_set_image (chooser->priv->context, NULL);
}
g_signal_connect_object (chooser->priv->image_view, "select-items",
g_signal_connect_object (chooser->priv->image_view, "selection-changed",
G_CALLBACK (gimp_pickable_chooser_items_selected),
G_OBJECT (chooser), 0);
if (chooser->priv->layer_view != NULL)
g_signal_connect_object (chooser->priv->layer_view, "select-items",
g_signal_connect_object (chooser->priv->layer_view, "selection-changed",
G_CALLBACK (gimp_pickable_chooser_items_selected),
G_OBJECT (chooser), 0);
if (chooser->priv->channel_view != NULL)
g_signal_connect_object (chooser->priv->channel_view, "select-items",
g_signal_connect_object (chooser->priv->channel_view, "selection-changed",
G_CALLBACK (gimp_pickable_chooser_items_selected),
G_OBJECT (chooser), 0);
}
@ -537,7 +534,7 @@ gimp_pickable_chooser_image_changed (GimpContext *context,
chooser);
gimp_container_view_set_container (GIMP_CONTAINER_VIEW (chooser->priv->layer_view),
layers);
g_signal_connect_object (chooser->priv->layer_view, "select-items",
g_signal_connect_object (chooser->priv->layer_view, "selection-changed",
G_CALLBACK (gimp_pickable_chooser_items_selected),
G_OBJECT (chooser), 0);
}
@ -548,35 +545,36 @@ gimp_pickable_chooser_image_changed (GimpContext *context,
chooser);
gimp_container_view_set_container (GIMP_CONTAINER_VIEW (chooser->priv->channel_view),
channels);
g_signal_connect_object (chooser->priv->channel_view, "select-items",
g_signal_connect_object (chooser->priv->channel_view, "selection-changed",
G_CALLBACK (gimp_pickable_chooser_items_selected),
G_OBJECT (chooser), 0);
}
g_signal_connect_object (chooser->priv->image_view, "select-items",
g_signal_connect_object (chooser->priv->image_view, "selection-changed",
G_CALLBACK (gimp_pickable_chooser_items_selected),
G_OBJECT (chooser), 0);
}
static void
gimp_pickable_chooser_item_activate (GimpContainerView *view,
GimpPickable *pickable,
gpointer unused,
GimpPickableChooser *chooser)
gimp_pickable_chooser_item_activated (GimpContainerView *view,
GimpPickable *pickable,
GimpPickableChooser *chooser)
{
g_signal_emit (chooser, signals[ACTIVATE], 0, pickable);
}
static void
gimp_pickable_chooser_items_selected (GimpContainerView *view,
GList *items,
GList *paths,
GimpPickableChooser *chooser)
{
GimpPickable *pickable = NULL;
gint n_items;
GList *items;
g_return_if_fail (g_list_length (items) <= 1);
n_items = gimp_container_view_get_selected (view, &items);
if (items != NULL)
g_return_if_fail (n_items <= 1);
if (items)
pickable = items->data;
gimp_pickable_chooser_set_pickable (chooser, pickable);

View file

@ -90,7 +90,8 @@ struct _GimpSettingsBoxPrivate
GFile *last_file;
};
#define GET_PRIVATE(item) ((GimpSettingsBoxPrivate *) gimp_settings_box_get_instance_private ((GimpSettingsBox *) (item)))
#define GET_PRIVATE(item) \
((GimpSettingsBoxPrivate *) gimp_settings_box_get_instance_private ((GimpSettingsBox *) (item)))
static void gimp_settings_box_constructed (GObject *object);
@ -112,10 +113,7 @@ static gboolean
gimp_settings_box_row_separator_func (GtkTreeModel *model,
GtkTreeIter *iter,
gpointer data);
static gboolean
gimp_settings_box_setting_selected (GimpContainerView *view,
GList *objects,
GList *paths,
static void gimp_settings_box_setting_selected (GimpContainerView *view,
GimpSettingsBox *box);
static gboolean gimp_settings_box_menu_press (GtkWidget *widget,
GdkEventButton *bevent,
@ -304,7 +302,7 @@ gimp_settings_box_constructed (GObject *object)
gimp_help_set_help_data (private->combo, _("Pick a preset from the list"),
NULL);
g_signal_connect_after (private->combo, "select-items",
g_signal_connect_after (private->combo, "selection_changed",
G_CALLBACK (gimp_settings_box_setting_selected),
box);
@ -541,19 +539,22 @@ gimp_settings_box_row_separator_func (GtkTreeModel *model,
return name == NULL;
}
static gboolean
static void
gimp_settings_box_setting_selected (GimpContainerView *view,
GList *objects,
GList *paths,
GimpSettingsBox *box)
{
g_return_val_if_fail (g_list_length (objects) < 2, FALSE);
GList *items;
gint n_items;
if (objects)
n_items = gimp_container_view_get_selected (view, &items);
g_warn_if_fail (n_items < 2);
if (items)
g_signal_emit (box, settings_box_signals[SELECTED], 0,
objects->data);
items->data);
return TRUE;
g_list_free (items);
}
static gboolean
@ -920,14 +921,12 @@ void
gimp_settings_box_add_current (GimpSettingsBox *box,
gint max_recent)
{
GimpSettingsBoxPrivate *private;
GimpConfig *config = NULL;
GimpSettingsBoxPrivate *private = GET_PRIVATE (box);
GimpConfig *config = NULL;
GList *list;
g_return_if_fail (GIMP_IS_SETTINGS_BOX (box));
private = GET_PRIVATE (box);
for (list = GIMP_LIST (private->container)->queue->head;
list;
list = g_list_next (list))
@ -977,11 +976,9 @@ gimp_settings_box_add_current (GimpSettingsBox *box,
void
gimp_settings_box_unset (GimpSettingsBox *box)
{
GimpSettingsBoxPrivate *private;
GimpSettingsBoxPrivate *private = GET_PRIVATE (box);;
g_return_if_fail (GIMP_IS_SETTINGS_BOX (box));
private = GET_PRIVATE (box);
gimp_container_view_select_items (GIMP_CONTAINER_VIEW (private->combo), NULL);
gimp_container_view_set_selected (GIMP_CONTAINER_VIEW (private->combo), NULL);
}

View file

@ -89,9 +89,8 @@ static gboolean
gimp_settings_editor_row_separator_func (GtkTreeModel *model,
GtkTreeIter *iter,
gpointer data);
static gboolean gimp_settings_editor_select_items (GimpContainerView *view,
GList *viewables,
GList *paths,
static void gimp_settings_editor_selection_changed
(GimpContainerView *view,
GimpSettingsEditor *editor);
static void gimp_settings_editor_import_clicked (GtkWidget *widget,
GimpSettingsEditor *editor);
@ -178,8 +177,8 @@ gimp_settings_editor_constructed (GObject *object)
gimp_settings_editor_row_separator_func,
private->view, NULL);
g_signal_connect (tree_view, "select-items",
G_CALLBACK (gimp_settings_editor_select_items),
g_signal_connect (tree_view, "selection-changed",
G_CALLBACK (gimp_settings_editor_selection_changed),
editor);
gimp_container_tree_view_connect_name_edited (tree_view,
@ -298,26 +297,31 @@ gimp_settings_editor_row_separator_func (GtkTreeModel *model,
return name == NULL;
}
static gboolean
gimp_settings_editor_select_items (GimpContainerView *view,
GList *viewables,
GList *paths,
GimpSettingsEditor *editor)
static void
gimp_settings_editor_selection_changed (GimpContainerView *view,
GimpSettingsEditor *editor)
{
GimpSettingsEditorPrivate *private = GET_PRIVATE (editor);
gboolean sensitive;
GList *items;
gint n_items;
g_return_val_if_fail (g_list_length (viewables) < 2, FALSE);
n_items = gimp_container_view_get_selected (view, &items);
private->selected_setting = viewables ? G_OBJECT (viewables->data) : NULL;
g_warn_if_fail (n_items < 2);
if (n_items == 1)
private->selected_setting = items->data;
else
private->selected_setting = NULL;
g_list_free (items);
sensitive = (private->selected_setting != NULL &&
gimp_object_get_name (private->selected_setting));
gtk_widget_set_sensitive (private->export_button, sensitive);
gtk_widget_set_sensitive (private->delete_button, sensitive);
return TRUE;
}
static void
@ -352,8 +356,8 @@ gimp_settings_editor_delete_clicked (GtkWidget *widget,
gimp_container_remove (private->container,
GIMP_OBJECT (private->selected_setting));
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (private->view),
GIMP_VIEWABLE (new));
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (private->view),
GIMP_VIEWABLE (new));
gimp_operation_config_serialize (private->gimp, private->container, NULL);
}

View file

@ -76,13 +76,12 @@ static void gimp_tool_editor_view_iface_init (GimpContainer
static void gimp_tool_editor_constructed (GObject *object);
static gboolean gimp_tool_editor_select_items (GimpContainerView *view,
GList *items,
GList *paths);
static void gimp_tool_editor_set_container (GimpContainerView *container_view,
GimpContainer *container);
static void gimp_tool_editor_set_context (GimpContainerView *container_view,
GimpContext *context);
static gboolean gimp_tool_editor_set_selected (GimpContainerView *view,
GList *items);
static gboolean gimp_tool_editor_drop_possible (GimpContainerTreeView *tree_view,
GimpDndType src_type,
@ -169,9 +168,9 @@ gimp_tool_editor_view_iface_init (GimpContainerViewInterface *iface)
if (! parent_view_iface)
parent_view_iface = g_type_default_interface_peek (GIMP_TYPE_CONTAINER_VIEW);
iface->select_items = gimp_tool_editor_select_items;
iface->set_container = gimp_tool_editor_set_container;
iface->set_context = gimp_tool_editor_set_context;
iface->set_selected = gimp_tool_editor_set_selected;
}
static void
@ -278,22 +277,6 @@ gimp_tool_editor_constructed (GObject *object)
gimp_tool_editor_update_sensitivity (tool_editor);
}
static gboolean
gimp_tool_editor_select_items (GimpContainerView *container_view,
GList *viewables,
GList *paths)
{
GimpToolEditor *tool_editor = GIMP_TOOL_EDITOR (container_view);
gboolean result;
result = parent_view_iface->select_items (container_view,
viewables, paths);
gimp_tool_editor_update_sensitivity (tool_editor);
return result;
}
static void
gimp_tool_editor_set_container (GimpContainerView *container_view,
GimpContainer *container)
@ -316,6 +299,20 @@ gimp_tool_editor_set_context (GimpContainerView *container_view,
gimp_tool_editor_update_container (tool_editor);
}
static gboolean
gimp_tool_editor_set_selected (GimpContainerView *container_view,
GList *items)
{
GimpToolEditor *tool_editor = GIMP_TOOL_EDITOR (container_view);
gboolean result;
result = parent_view_iface->set_selected (container_view, items);
gimp_tool_editor_update_sensitivity (tool_editor);
return result;
}
static gboolean
gimp_tool_editor_drop_possible (GimpContainerTreeView *tree_view,
GimpDndType src_type,
@ -367,7 +364,7 @@ gimp_tool_editor_drop_viewables (GimpContainerTreeView *tree_view,
drop_pos);
if (src_viewables)
gimp_container_view_select_items (container_view, src_viewables);
gimp_container_view_set_selected (container_view, src_viewables);
}
static void
@ -406,7 +403,8 @@ gimp_tool_editor_new_group_clicked (GtkButton *button,
g_object_unref (group);
gimp_container_view_select_item (container_view, GIMP_VIEWABLE (group));
gimp_container_view_set_1_selected (container_view,
GIMP_VIEWABLE (group));
}
}
@ -566,10 +564,10 @@ gimp_tool_editor_delete_clicked (GtkButton *button,
gimp_container_thaw (dest_container);
gimp_container_thaw (src_container);
gimp_container_view_select_item (
container_view,
GIMP_VIEWABLE (gimp_container_get_child_by_index (dest_container,
index)));
gimp_container_view_set_1_selected
(container_view,
GIMP_VIEWABLE (gimp_container_get_child_by_index (dest_container,
index)));
g_object_unref (tool_item);
}
@ -593,7 +591,7 @@ gimp_tool_editor_tool_item_notify (GimpToolItem *tool_item,
GimpContainerView *container_view = GIMP_CONTAINER_VIEW (tool_editor);
GtkTreeIter *iter;
iter = gimp_container_view_lookup (container_view,
iter = _gimp_container_view_lookup (container_view,
GIMP_VIEWABLE (tool_item));
if (iter)

View file

@ -72,9 +72,8 @@ static void gimp_undo_editor_undo_event (GimpImage *image,
GimpUndo *undo,
GimpUndoEditor *editor);
static gboolean gimp_undo_editor_select_items (GimpContainerView *view,
GList *undos,
GList *paths,
static void gimp_undo_editor_selection_changed
(GimpContainerView *view,
GimpUndoEditor *editor);
@ -138,8 +137,8 @@ gimp_undo_editor_constructed (GObject *object)
gtk_box_pack_start (GTK_BOX (undo_editor), undo_editor->view, TRUE, TRUE, 0);
gtk_widget_show (undo_editor->view);
g_signal_connect (undo_editor->view, "select-items",
G_CALLBACK (gimp_undo_editor_select_items),
g_signal_connect (undo_editor->view, "selection-changed",
G_CALLBACK (gimp_undo_editor_selection_changed),
undo_editor);
undo_editor->undo_button =
@ -299,25 +298,25 @@ gimp_undo_editor_fill (GimpUndoEditor *editor)
top_undo_item = gimp_undo_stack_peek (undo_stack);
g_signal_handlers_block_by_func (editor->view,
gimp_undo_editor_select_items,
gimp_undo_editor_selection_changed,
editor);
/* select the current state of the image */
if (top_undo_item)
{
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (editor->view),
GIMP_VIEWABLE (top_undo_item));
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (editor->view),
GIMP_VIEWABLE (top_undo_item));
gimp_undo_create_preview (top_undo_item, editor->context, FALSE);
}
else
{
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (editor->view),
GIMP_VIEWABLE (editor->base_item));
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (editor->view),
GIMP_VIEWABLE (editor->base_item));
gimp_undo_create_preview (editor->base_item, editor->context, TRUE);
}
g_signal_handlers_unblock_by_func (editor->view,
gimp_undo_editor_select_items,
gimp_undo_editor_selection_changed,
editor);
}
@ -347,16 +346,16 @@ gimp_undo_editor_undo_event (GimpImage *image,
{
case GIMP_UNDO_EVENT_UNDO_PUSHED:
g_signal_handlers_block_by_func (editor->view,
gimp_undo_editor_select_items,
gimp_undo_editor_selection_changed,
editor);
gimp_container_insert (editor->container, GIMP_OBJECT (undo), -1);
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (editor->view),
GIMP_VIEWABLE (undo));
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (editor->view),
GIMP_VIEWABLE (undo));
gimp_undo_create_preview (undo, editor->context, FALSE);
g_signal_handlers_unblock_by_func (editor->view,
gimp_undo_editor_select_items,
gimp_undo_editor_selection_changed,
editor);
break;
@ -368,24 +367,24 @@ gimp_undo_editor_undo_event (GimpImage *image,
case GIMP_UNDO_EVENT_UNDO:
case GIMP_UNDO_EVENT_REDO:
g_signal_handlers_block_by_func (editor->view,
gimp_undo_editor_select_items,
gimp_undo_editor_selection_changed,
editor);
if (top_undo_item)
{
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (editor->view),
GIMP_VIEWABLE (top_undo_item));
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (editor->view),
GIMP_VIEWABLE (top_undo_item));
gimp_undo_create_preview (top_undo_item, editor->context, FALSE);
}
else
{
gimp_container_view_select_item (GIMP_CONTAINER_VIEW (editor->view),
GIMP_VIEWABLE (editor->base_item));
gimp_container_view_set_1_selected (GIMP_CONTAINER_VIEW (editor->view),
GIMP_VIEWABLE (editor->base_item));
gimp_undo_create_preview (editor->base_item, editor->context, TRUE);
}
g_signal_handlers_unblock_by_func (editor->view,
gimp_undo_editor_select_items,
gimp_undo_editor_selection_changed,
editor);
break;
@ -404,11 +403,9 @@ gimp_undo_editor_undo_event (GimpImage *image,
}
}
static gboolean
gimp_undo_editor_select_items (GimpContainerView *view,
GList *undos,
GList *paths,
GimpUndoEditor *editor)
static void
gimp_undo_editor_selection_changed (GimpContainerView *view,
GimpUndoEditor *editor)
{
GimpImage *image = GIMP_IMAGE_EDITOR (editor)->image;
GimpUndoStack *undo_stack = gimp_image_get_undo_stack (image);
@ -416,12 +413,10 @@ gimp_undo_editor_select_items (GimpContainerView *view,
GimpUndo *top_undo_item;
GimpUndo *undo;
g_return_val_if_fail (g_list_length (undos) < 2, FALSE);
undo = GIMP_UNDO (gimp_container_view_get_1_selected (view));
if (! undos)
return TRUE;
undo = undos->data;
if (! undo)
return;
top_undo_item = gimp_undo_stack_peek (undo_stack);
@ -465,6 +460,4 @@ gimp_undo_editor_select_items (GimpContainerView *view,
}
gimp_image_flush (image);
return TRUE;
}