mirror of https://github.com/GNOME/gimp.git
Issue #10745: move the "item set" icon above layer list.
- The icon itself was changed to a "search" icon. Though it kinda made sense to keep the "link" reference when I first implemented this, as a reference to how we used to link items (whereas now we select them together), in the grand scheme of things, it's not such a good idea and many won't likely understand. But everyone will understand a "search" button. :-) - It's now next to the label displaying the number of selected items, in the item tree view header. This makes much more sense there. Also it makes the long list of bottom buttons slighly shorter. - Finally I make this feature accessible to the channels and paths, by actually moving it out of GimpLayerTreeView and into GimpItemTreeView.
This commit is contained in:
parent
d6edd71c4f
commit
25145b9684
|
@ -130,9 +130,7 @@ enum
|
|||
PARASITE_DETACHED,
|
||||
COLORMAP_CHANGED,
|
||||
UNDO_EVENT,
|
||||
LAYER_SETS_CHANGED,
|
||||
CHANNEL_SETS_CHANGED,
|
||||
VECTORS_SETS_CHANGED,
|
||||
ITEM_SETS_CHANGED,
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
|
@ -587,29 +585,14 @@ gimp_image_class_init (GimpImageClass *klass)
|
|||
GIMP_TYPE_UNDO_EVENT,
|
||||
GIMP_TYPE_UNDO);
|
||||
|
||||
gimp_image_signals[LAYER_SETS_CHANGED] =
|
||||
g_signal_new ("layer-sets-changed",
|
||||
gimp_image_signals[ITEM_SETS_CHANGED] =
|
||||
g_signal_new ("item-sets-changed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (GimpImageClass, layer_sets_changed),
|
||||
G_STRUCT_OFFSET (GimpImageClass, item_sets_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
gimp_image_signals[CHANNEL_SETS_CHANGED] =
|
||||
g_signal_new ("channel-sets-changed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (GimpImageClass, channel_sets_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
|
||||
gimp_image_signals[VECTORS_SETS_CHANGED] =
|
||||
g_signal_new ("vectors-sets-changed",
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_FIRST,
|
||||
G_STRUCT_OFFSET (GimpImageClass, vectors_sets_changed),
|
||||
NULL, NULL, NULL,
|
||||
G_TYPE_NONE, 0);
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_GTYPE);
|
||||
|
||||
object_class->constructed = gimp_image_constructed;
|
||||
object_class->set_property = gimp_image_set_property;
|
||||
|
@ -5476,31 +5459,23 @@ gimp_image_store_item_set (GimpImage *image,
|
|||
GList **stored_sets;
|
||||
GList *iter;
|
||||
guint signal;
|
||||
GType item_type;
|
||||
|
||||
g_return_if_fail (GIMP_IS_IMAGE (image));
|
||||
g_return_if_fail (GIMP_IS_ITEM_LIST (set));
|
||||
|
||||
private = GIMP_IMAGE_GET_PRIVATE (image);
|
||||
|
||||
if (gimp_item_list_get_item_type (set) == GIMP_TYPE_LAYER)
|
||||
{
|
||||
stored_sets = &private->stored_layer_sets;
|
||||
signal = gimp_image_signals[LAYER_SETS_CHANGED];
|
||||
}
|
||||
else if (gimp_item_list_get_item_type (set) == GIMP_TYPE_CHANNEL)
|
||||
{
|
||||
stored_sets = &private->stored_channel_sets;
|
||||
signal = gimp_image_signals[CHANNEL_SETS_CHANGED];
|
||||
}
|
||||
else if (gimp_item_list_get_item_type (set) == GIMP_TYPE_VECTORS)
|
||||
{
|
||||
stored_sets = &private->stored_vectors_sets;
|
||||
signal = gimp_image_signals[VECTORS_SETS_CHANGED];
|
||||
}
|
||||
signal = gimp_image_signals[ITEM_SETS_CHANGED];
|
||||
item_type = gimp_item_list_get_item_type (set);
|
||||
if (item_type == GIMP_TYPE_LAYER)
|
||||
stored_sets = &private->stored_layer_sets;
|
||||
else if (item_type == GIMP_TYPE_CHANNEL)
|
||||
stored_sets = &private->stored_channel_sets;
|
||||
else if (item_type == GIMP_TYPE_VECTORS)
|
||||
stored_sets = &private->stored_vectors_sets;
|
||||
else
|
||||
{
|
||||
g_return_if_reached ();
|
||||
}
|
||||
g_return_if_reached ();
|
||||
|
||||
for (iter = *stored_sets; iter; iter = iter->next)
|
||||
{
|
||||
|
@ -5524,7 +5499,7 @@ gimp_image_store_item_set (GimpImage *image,
|
|||
}
|
||||
|
||||
*stored_sets = g_list_prepend (*stored_sets, set);
|
||||
g_signal_emit (image, signal, 0);
|
||||
g_signal_emit (image, signal, 0, item_type);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -5545,31 +5520,23 @@ gimp_image_unlink_item_set (GimpImage *image,
|
|||
GList *found;
|
||||
GList **stored_sets;
|
||||
guint signal;
|
||||
GType item_type;
|
||||
gboolean success;
|
||||
|
||||
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
|
||||
|
||||
private = GIMP_IMAGE_GET_PRIVATE (image);
|
||||
|
||||
if (gimp_item_list_get_item_type (set) == GIMP_TYPE_LAYER)
|
||||
{
|
||||
stored_sets = &private->stored_layer_sets;
|
||||
signal = gimp_image_signals[LAYER_SETS_CHANGED];
|
||||
}
|
||||
else if (gimp_item_list_get_item_type (set) == GIMP_TYPE_CHANNEL)
|
||||
{
|
||||
stored_sets = &private->stored_channel_sets;
|
||||
signal = gimp_image_signals[CHANNEL_SETS_CHANGED];
|
||||
}
|
||||
else if (gimp_item_list_get_item_type (set) == GIMP_TYPE_VECTORS)
|
||||
{
|
||||
stored_sets = &private->stored_vectors_sets;
|
||||
signal = gimp_image_signals[VECTORS_SETS_CHANGED];
|
||||
}
|
||||
signal = gimp_image_signals[ITEM_SETS_CHANGED];
|
||||
item_type = gimp_item_list_get_item_type (set);
|
||||
if (item_type == GIMP_TYPE_LAYER)
|
||||
stored_sets = &private->stored_layer_sets;
|
||||
else if (item_type == GIMP_TYPE_CHANNEL)
|
||||
stored_sets = &private->stored_channel_sets;
|
||||
else if (item_type == GIMP_TYPE_VECTORS)
|
||||
stored_sets = &private->stored_vectors_sets;
|
||||
else
|
||||
{
|
||||
g_return_val_if_reached (FALSE);
|
||||
}
|
||||
g_return_val_if_reached (FALSE);
|
||||
|
||||
found = g_list_find (*stored_sets, set);
|
||||
success = (found != NULL);
|
||||
|
@ -5577,7 +5544,7 @@ gimp_image_unlink_item_set (GimpImage *image,
|
|||
{
|
||||
*stored_sets = g_list_delete_link (*stored_sets, found);
|
||||
g_object_unref (set);
|
||||
g_signal_emit (image, signal, 0);
|
||||
g_signal_emit (image, signal, 0, item_type);
|
||||
}
|
||||
|
||||
return success;
|
||||
|
|
|
@ -103,9 +103,8 @@ struct _GimpImageClass
|
|||
void (* undo_event) (GimpImage *image,
|
||||
GimpUndoEvent event,
|
||||
GimpUndo *undo);
|
||||
void (* layer_sets_changed) (GimpImage *image);
|
||||
void (* channel_sets_changed) (GimpImage *image);
|
||||
void (* vectors_sets_changed) (GimpImage *image);
|
||||
void (* item_sets_changed) (GimpImage *image,
|
||||
GType item_type);
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -28,8 +28,6 @@ struct _GimpContainerTreeViewPrivate
|
|||
|
||||
GtkCellRenderer *name_cell;
|
||||
|
||||
GtkWidget *multi_selection_label;
|
||||
|
||||
GList *editable_cells;
|
||||
gchar *editing_path;
|
||||
|
||||
|
|
|
@ -284,14 +284,9 @@ gimp_container_tree_view_constructed (GObject *object)
|
|||
gimp_container_view_set_dnd_widget (view, GTK_WIDGET (tree_view->view));
|
||||
|
||||
tree_view->main_column = gtk_tree_view_column_new ();
|
||||
tree_view->priv->multi_selection_label = gtk_label_new (NULL);
|
||||
gtk_label_set_selectable (GTK_LABEL (tree_view->priv->multi_selection_label), TRUE);
|
||||
gtk_tree_view_column_set_widget (tree_view->main_column,
|
||||
tree_view->priv->multi_selection_label);
|
||||
gtk_widget_show (tree_view->priv->multi_selection_label);
|
||||
gtk_tree_view_insert_column (tree_view->view, tree_view->main_column, 0);
|
||||
|
||||
gtk_tree_view_set_expander_column (tree_view->view, tree_view->main_column);
|
||||
gtk_tree_view_column_set_clickable (tree_view->main_column, FALSE);
|
||||
gtk_tree_view_set_enable_tree_lines (tree_view->view, TRUE);
|
||||
|
||||
tree_view->renderer_cell = gimp_cell_renderer_viewable_new ();
|
||||
|
@ -1051,22 +1046,6 @@ gimp_container_tree_view_select_items (GimpContainerView *view,
|
|||
if (free_paths)
|
||||
g_list_free_full (paths, (GDestroyNotify) gtk_tree_path_free);
|
||||
|
||||
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_show (tree_view->priv->multi_selection_label);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_hide (tree_view->priv->multi_selection_label);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "core/gimpimage-undo.h"
|
||||
#include "core/gimpimage-undo-push.h"
|
||||
#include "core/gimpitem-exclusive.h"
|
||||
#include "core/gimpitemlist.h"
|
||||
#include "core/gimpitemundo.h"
|
||||
#include "core/gimplist.h"
|
||||
#include "core/gimptoolinfo.h"
|
||||
|
@ -133,6 +134,15 @@ struct _GimpItemTreeViewPrivate
|
|||
GimpTreeHandler *color_tag_changed_handler;
|
||||
GimpTreeHandler *filters_changed_handler;
|
||||
GimpTreeHandler *filters_active_changed_handler;
|
||||
|
||||
GtkWidget *multi_selection_label;
|
||||
GtkWidget *search_button;
|
||||
GtkWidget *search_popover;
|
||||
GtkWidget *new_link_button;
|
||||
GtkWidget *link_list;
|
||||
GtkWidget *link_entry;
|
||||
GtkWidget *link_search_entry;
|
||||
GimpItemList *link_pattern_set;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
|
@ -319,6 +329,35 @@ static gint gimp_item_tree_view_get_n_locks (GimpItemTreeView *view,
|
|||
static void gimp_item_tree_effects_set_sensitive (GimpItemTreeView *view,
|
||||
gboolean is_sensitive);
|
||||
|
||||
/* Functions for the item search/selection feature. */
|
||||
|
||||
static void gimp_item_tree_view_create_search_popover (GimpItemTreeView *view,
|
||||
GtkIconSize button_size);
|
||||
static void gimp_item_tree_view_search_popover_shown (GtkPopover *popover,
|
||||
GimpItemTreeView *view);
|
||||
|
||||
static void gimp_item_tree_view_floating_selection_changed (GimpImage *image,
|
||||
GimpItemTreeView *view);
|
||||
static void gimp_item_tree_view_item_links_changed (GimpImage *image,
|
||||
GType item_type,
|
||||
GimpItemTreeView *view);
|
||||
static gboolean gimp_item_tree_view_link_clicked (GtkWidget *box,
|
||||
GdkEvent *event,
|
||||
GimpItemTreeView *view);
|
||||
static gboolean gimp_item_tree_view_unlink_clicked (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
GimpItemTreeView *view);
|
||||
static gboolean gimp_item_tree_view_search_key_release (GtkWidget *widget,
|
||||
GdkEventKey *event,
|
||||
GimpItemTreeView *view);
|
||||
static gboolean gimp_item_tree_view_start_interactive_search (GtkTreeView *tree_view,
|
||||
GimpItemTreeView *layer_view);
|
||||
static gboolean gimp_item_tree_view_new_link_clicked (GimpItemTreeView *view);
|
||||
static void gimp_item_tree_view_new_link_exit (GimpItemTreeView *view);
|
||||
static gboolean gimp_item_tree_view_search_clicked (GtkWidget *main_column_button,
|
||||
GdkEventButton *event,
|
||||
GimpItemTreeView *view);
|
||||
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (GimpItemTreeView, gimp_item_tree_view,
|
||||
GIMP_TYPE_CONTAINER_TREE_VIEW,
|
||||
|
@ -457,6 +496,8 @@ gimp_item_tree_view_init (GimpItemTreeView *view)
|
|||
view->priv->image = NULL;
|
||||
view->priv->effects_drawable = NULL;
|
||||
view->priv->effects_filter = NULL;
|
||||
|
||||
view->priv->link_pattern_set = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -469,6 +510,7 @@ gimp_item_tree_view_constructed (GObject *object)
|
|||
GtkTreeViewColumn *column;
|
||||
GtkWidget *image;
|
||||
GtkWidget *label;
|
||||
GtkWidget *items_header;
|
||||
gchar *text;
|
||||
GtkIconSize button_icon_size = GTK_ICON_SIZE_SMALL_TOOLBAR;
|
||||
gint pixel_icon_size = 16;
|
||||
|
@ -814,6 +856,50 @@ gimp_item_tree_view_constructed (GObject *object)
|
|||
gtk_widget_set_visible (item_view->priv->effects_options, TRUE);
|
||||
gtk_widget_set_visible (item_view->priv->effects_filters, TRUE);
|
||||
}
|
||||
|
||||
items_header = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 1);
|
||||
gtk_widget_set_hexpand (items_header, TRUE);
|
||||
gtk_widget_set_halign (items_header, GTK_ALIGN_FILL);
|
||||
gtk_widget_set_margin_end (items_header, 1);
|
||||
|
||||
/* Link popover menu. */
|
||||
|
||||
item_view->priv->search_button = gtk_image_new_from_icon_name (GIMP_ICON_EDIT_FIND,
|
||||
button_icon_size);
|
||||
gtk_widget_set_tooltip_text (item_view->priv->search_button,
|
||||
_("Select items by patterns and store item sets"));
|
||||
gtk_box_pack_end (GTK_BOX (items_header), item_view->priv->search_button,
|
||||
FALSE, FALSE, 2);
|
||||
gimp_item_tree_view_create_search_popover (item_view, button_icon_size);
|
||||
gtk_widget_show (item_view->priv->search_button);
|
||||
|
||||
/* Search label */
|
||||
|
||||
item_view->priv->multi_selection_label = gtk_label_new (NULL);
|
||||
gtk_label_set_selectable (GTK_LABEL (item_view->priv->multi_selection_label), FALSE);
|
||||
gtk_widget_set_halign (item_view->priv->multi_selection_label, GTK_ALIGN_START);
|
||||
gtk_box_pack_end (GTK_BOX (items_header), item_view->priv->multi_selection_label,
|
||||
FALSE, FALSE, 4);
|
||||
gtk_widget_show (item_view->priv->multi_selection_label);
|
||||
|
||||
gtk_tree_view_column_set_widget (GIMP_CONTAINER_TREE_VIEW (item_view)->main_column, items_header);
|
||||
gtk_tree_view_column_set_alignment (GIMP_CONTAINER_TREE_VIEW (item_view)->main_column, 1.0);
|
||||
gtk_tree_view_column_set_clickable (GIMP_CONTAINER_TREE_VIEW (item_view)->main_column, TRUE);
|
||||
g_signal_connect (gtk_tree_view_column_get_button (GIMP_CONTAINER_TREE_VIEW (item_view)->main_column),
|
||||
"button-release-event",
|
||||
G_CALLBACK (gtk_true),
|
||||
item_view);
|
||||
/* XXX: I don't use the "clicked" signal of the GtkTreeViewColumn main_column,
|
||||
* because the event goes through and reaches gimp_container_tree_view_button()
|
||||
* code, provoking selection of the top item, depending on where we click.
|
||||
* Catching the signal at the column's button level, we manage to block the
|
||||
* event from having any side effect other than opening our popup.
|
||||
*/
|
||||
g_signal_connect (gtk_tree_view_column_get_button (GIMP_CONTAINER_TREE_VIEW (item_view)->main_column),
|
||||
"button-press-event",
|
||||
G_CALLBACK (gimp_item_tree_view_search_clicked),
|
||||
item_view);
|
||||
gtk_widget_show (items_header);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -956,6 +1042,26 @@ gimp_item_tree_view_style_updated (GtkWidget *widget)
|
|||
g_free (icon_name);
|
||||
}
|
||||
|
||||
gtk_image_get_icon_name (GTK_IMAGE (view->priv->search_button),
|
||||
&old_icon_name, &old_size);
|
||||
if (button_icon_size != old_size)
|
||||
{
|
||||
GtkWidget *image;
|
||||
|
||||
icon_name = g_strdup (old_icon_name);
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (view->priv->search_button),
|
||||
icon_name, button_icon_size);
|
||||
g_free (icon_name);
|
||||
|
||||
/* Changing the new link button inside the popover. */
|
||||
image = gtk_button_get_image (GTK_BUTTON (view->priv->new_link_button));
|
||||
gtk_image_get_icon_name (GTK_IMAGE (image), &old_icon_name, &old_size);
|
||||
icon_name = g_strdup (old_icon_name);
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (image), icon_name,
|
||||
button_icon_size);
|
||||
g_free (icon_name);
|
||||
}
|
||||
|
||||
if (GIMP_IS_LAYER_TREE_VIEW (view))
|
||||
{
|
||||
gtk_image_get_icon_name (GTK_IMAGE (view->priv->effect_header_image),
|
||||
|
@ -1278,6 +1384,8 @@ static void
|
|||
gimp_item_tree_view_real_set_image (GimpItemTreeView *view,
|
||||
GimpImage *image)
|
||||
{
|
||||
GimpItemTreeViewClass *item_view_class;
|
||||
|
||||
if (view->priv->image == image)
|
||||
return;
|
||||
|
||||
|
@ -1295,6 +1403,13 @@ gimp_item_tree_view_real_set_image (GimpItemTreeView *view,
|
|||
g_signal_handlers_disconnect_by_func (view->priv->image,
|
||||
gimp_item_tree_view_image_flush,
|
||||
view);
|
||||
|
||||
g_signal_handlers_disconnect_by_func (view->priv->image,
|
||||
G_CALLBACK (gimp_item_tree_view_item_links_changed),
|
||||
view);
|
||||
g_signal_handlers_disconnect_by_func (view->priv->image,
|
||||
G_CALLBACK (gimp_item_tree_view_floating_selection_changed),
|
||||
view);
|
||||
}
|
||||
|
||||
view->priv->image = image;
|
||||
|
@ -1323,8 +1438,24 @@ gimp_item_tree_view_real_set_image (GimpItemTreeView *view,
|
|||
G_CALLBACK (gimp_item_tree_view_image_flush),
|
||||
view);
|
||||
|
||||
g_signal_connect (view->priv->image,
|
||||
"item-sets-changed",
|
||||
G_CALLBACK (gimp_item_tree_view_item_links_changed),
|
||||
view);
|
||||
g_signal_connect (view->priv->image,
|
||||
"floating-selection-changed",
|
||||
G_CALLBACK (gimp_item_tree_view_floating_selection_changed),
|
||||
view);
|
||||
|
||||
gimp_item_tree_view_item_changed (view->priv->image, view);
|
||||
}
|
||||
|
||||
/* Call this even with no image, allowing to empty the link list. */
|
||||
item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (view);
|
||||
gimp_item_tree_view_item_links_changed (view->priv->image,
|
||||
item_view_class->item_type,
|
||||
view);
|
||||
gimp_item_tree_view_floating_selection_changed (view->priv->image, view);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1581,6 +1712,22 @@ gimp_item_tree_view_select_items (GimpContainerView *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_show (tree_view->priv->multi_selection_label);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_hide (tree_view->priv->multi_selection_label);
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
@ -3086,3 +3233,475 @@ gimp_item_tree_effects_set_sensitive (GimpItemTreeView *view,
|
|||
gtk_widget_set_sensitive (view->priv->effects_merge_button, is_sensitive);
|
||||
gtk_widget_set_sensitive (view->priv->effects_remove_button, is_sensitive);
|
||||
}
|
||||
|
||||
/* Functions for the item search/selection feature. */
|
||||
|
||||
static void
|
||||
gimp_item_tree_view_create_search_popover (GimpItemTreeView *view,
|
||||
GtkIconSize button_size)
|
||||
{
|
||||
PangoAttrList *attrs;
|
||||
GtkWidget *grid;
|
||||
GtkWidget *placeholder;
|
||||
GtkWidget *button;
|
||||
|
||||
g_return_if_fail (GIMP_IS_ITEM_TREE_VIEW (view));
|
||||
g_return_if_fail (view->priv->search_popover == NULL);
|
||||
g_return_if_fail (GTK_IS_IMAGE (view->priv->search_button));
|
||||
|
||||
view->priv->search_popover = gtk_popover_new (view->priv->search_button);
|
||||
gtk_popover_set_modal (GTK_POPOVER (view->priv->search_popover), TRUE);
|
||||
|
||||
g_signal_connect (view->priv->search_popover,
|
||||
"show",
|
||||
G_CALLBACK (gimp_item_tree_view_search_popover_shown),
|
||||
view);
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
|
||||
/* Link popover: regexp search. */
|
||||
view->priv->link_search_entry = gtk_entry_new ();
|
||||
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (view->priv->link_search_entry),
|
||||
GTK_ENTRY_ICON_SECONDARY,
|
||||
"system-search");
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
view->priv->link_search_entry,
|
||||
0, 0, 2, 1);
|
||||
gtk_widget_show (view->priv->link_search_entry);
|
||||
g_signal_connect (view->priv->link_search_entry,
|
||||
"key-release-event",
|
||||
G_CALLBACK (gimp_item_tree_view_search_key_release),
|
||||
view);
|
||||
|
||||
g_signal_connect (GIMP_CONTAINER_TREE_VIEW (view)->view,
|
||||
"start-interactive-search",
|
||||
G_CALLBACK (gimp_item_tree_view_start_interactive_search),
|
||||
view);
|
||||
|
||||
/* Link popover: existing links. */
|
||||
view->priv->link_list = gtk_list_box_new ();
|
||||
placeholder = gtk_label_new (_("No layer set stored"));
|
||||
attrs = pango_attr_list_new ();
|
||||
gtk_label_set_attributes (GTK_LABEL (placeholder),
|
||||
attrs);
|
||||
pango_attr_list_insert (attrs, pango_attr_style_new (PANGO_STYLE_ITALIC));
|
||||
pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_ULTRALIGHT));
|
||||
pango_attr_list_unref (attrs);
|
||||
gtk_list_box_set_placeholder (GTK_LIST_BOX (view->priv->link_list),
|
||||
placeholder);
|
||||
gtk_widget_show (placeholder);
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
view->priv->link_list,
|
||||
0, 1, 2, 1);
|
||||
gtk_widget_show (view->priv->link_list);
|
||||
|
||||
gtk_list_box_set_activate_on_single_click (GTK_LIST_BOX (view->priv->link_list),
|
||||
TRUE);
|
||||
|
||||
/* Link popover: new links. */
|
||||
|
||||
view->priv->link_entry = gtk_entry_new ();
|
||||
gtk_entry_set_placeholder_text (GTK_ENTRY (view->priv->link_entry),
|
||||
_("New layer set's name"));
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
view->priv->link_entry,
|
||||
0, 2, 1, 1);
|
||||
gtk_widget_show (view->priv->link_entry);
|
||||
|
||||
button = gtk_button_new_from_icon_name (GIMP_ICON_LIST_ADD, button_size);
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
button,
|
||||
1, 2, 1, 1);
|
||||
g_signal_connect_swapped (button,
|
||||
"clicked",
|
||||
G_CALLBACK (gimp_item_tree_view_new_link_clicked),
|
||||
view);
|
||||
gtk_widget_show (button);
|
||||
view->priv->new_link_button = button;
|
||||
|
||||
/* Enter on any entry activates the link creation then exits in case
|
||||
* of success.
|
||||
*/
|
||||
g_signal_connect_swapped (view->priv->link_entry,
|
||||
"activate",
|
||||
G_CALLBACK (gimp_item_tree_view_new_link_exit),
|
||||
view);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (view->priv->search_popover), grid);
|
||||
gtk_widget_show (grid);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_item_tree_view_search_popover_shown (GtkPopover *popover,
|
||||
GimpItemTreeView *view)
|
||||
{
|
||||
GimpImage *image;
|
||||
GimpSelectMethod pattern_syntax;
|
||||
|
||||
image = gimp_item_tree_view_get_image (GIMP_ITEM_TREE_VIEW (view));
|
||||
|
||||
gtk_widget_set_sensitive (view->priv->link_entry, FALSE);
|
||||
if (! image)
|
||||
{
|
||||
gtk_widget_set_tooltip_text (view->priv->link_search_entry,
|
||||
_("Select layers by text search"));
|
||||
gtk_entry_set_placeholder_text (GTK_ENTRY (view->priv->link_search_entry),
|
||||
_("Text search"));
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_widget_set_sensitive (view->priv->link_entry, TRUE);
|
||||
gtk_widget_grab_focus (view->priv->link_search_entry);
|
||||
g_object_get (image->gimp->config,
|
||||
"items-select-method", &pattern_syntax,
|
||||
NULL);
|
||||
switch (pattern_syntax)
|
||||
{
|
||||
case GIMP_SELECT_PLAIN_TEXT:
|
||||
gtk_widget_set_tooltip_text (view->priv->link_search_entry,
|
||||
_("Select layers by text search"));
|
||||
gtk_entry_set_placeholder_text (GTK_ENTRY (view->priv->link_search_entry),
|
||||
_("Text search"));
|
||||
break;
|
||||
case GIMP_SELECT_GLOB_PATTERN:
|
||||
gtk_widget_set_tooltip_text (view->priv->link_search_entry,
|
||||
_("Select layers by glob patterns"));
|
||||
gtk_entry_set_placeholder_text (GTK_ENTRY (view->priv->link_search_entry),
|
||||
_("Glob pattern search"));
|
||||
break;
|
||||
case GIMP_SELECT_REGEX_PATTERN:
|
||||
gtk_widget_set_tooltip_text (view->priv->link_search_entry,
|
||||
_("Select layers by regular expressions"));
|
||||
gtk_entry_set_placeholder_text (GTK_ENTRY (view->priv->link_search_entry),
|
||||
_("Regular Expression search"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_item_tree_view_floating_selection_changed (GimpImage *image,
|
||||
GimpItemTreeView *view)
|
||||
{
|
||||
gtk_widget_set_sensitive (view->priv->search_button,
|
||||
image && ! gimp_image_get_floating_selection (image));
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_item_tree_view_item_links_changed (GimpImage *image,
|
||||
GType item_type,
|
||||
GimpItemTreeView *view)
|
||||
{
|
||||
GimpItemTreeViewClass *item_view_class;
|
||||
GtkWidget *grid;
|
||||
GtkWidget *label;
|
||||
GtkWidget *event_box;
|
||||
GtkWidget *icon;
|
||||
GtkSizeGroup *label_size;
|
||||
GList *links;
|
||||
GList *iter;
|
||||
|
||||
item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (view);
|
||||
if (item_type != item_view_class->item_type)
|
||||
return;
|
||||
|
||||
gtk_container_foreach (GTK_CONTAINER (view->priv->link_list),
|
||||
(GtkCallback) gtk_widget_destroy, NULL);
|
||||
gtk_widget_set_sensitive (view->priv->search_button, image != NULL);
|
||||
|
||||
if (! image)
|
||||
return;
|
||||
|
||||
links = gimp_image_get_stored_item_sets (image, item_type);
|
||||
|
||||
label_size = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
|
||||
for (iter = links; iter; iter = iter->next)
|
||||
{
|
||||
GimpSelectMethod method;
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
|
||||
label = gtk_label_new (gimp_object_get_name (iter->data));
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||
if (gimp_item_list_is_pattern (iter->data, &method))
|
||||
{
|
||||
gchar *display_name;
|
||||
PangoAttrList *attrs;
|
||||
|
||||
display_name = g_strdup_printf ("<small>[%s]</small> %s",
|
||||
method == GIMP_SELECT_PLAIN_TEXT ? _("search") :
|
||||
(method == GIMP_SELECT_GLOB_PATTERN ? _("glob") : _("regexp")),
|
||||
gimp_object_get_name (iter->data));
|
||||
gtk_label_set_markup (GTK_LABEL (label), display_name);
|
||||
g_free (display_name);
|
||||
|
||||
attrs = pango_attr_list_new ();
|
||||
pango_attr_list_insert (attrs, pango_attr_style_new (PANGO_STYLE_OBLIQUE));
|
||||
gtk_label_set_attributes (GTK_LABEL (label), attrs);
|
||||
pango_attr_list_unref (attrs);
|
||||
}
|
||||
gtk_widget_set_hexpand (GTK_WIDGET (label), TRUE);
|
||||
gtk_widget_set_halign (GTK_WIDGET (label), GTK_ALIGN_START);
|
||||
gtk_size_group_add_widget (label_size, label);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
|
||||
gtk_widget_show (label);
|
||||
|
||||
/* I don't use a GtkButton because the minimum size is 16 which is
|
||||
* weird and ugly here. And somehow if I force smaller GtkImage
|
||||
* size then add it to the GtkButton, I still get a giant button
|
||||
* with a small image in it, which is even worse. XXX
|
||||
*/
|
||||
event_box = gtk_event_box_new ();
|
||||
gtk_event_box_set_above_child (GTK_EVENT_BOX (event_box), TRUE);
|
||||
gtk_widget_add_events (event_box, GDK_BUTTON_RELEASE_MASK);
|
||||
g_object_set_data (G_OBJECT (event_box), "link-set", iter->data);
|
||||
g_signal_connect (event_box, "button-release-event",
|
||||
G_CALLBACK (gimp_item_tree_view_unlink_clicked),
|
||||
view);
|
||||
gtk_grid_attach (GTK_GRID (grid), event_box, 2, 0, 1, 1);
|
||||
gtk_widget_show (event_box);
|
||||
|
||||
icon = gtk_image_new_from_icon_name (GIMP_ICON_EDIT_DELETE, GTK_ICON_SIZE_MENU);
|
||||
gtk_image_set_pixel_size (GTK_IMAGE (icon), 10);
|
||||
gtk_container_add (GTK_CONTAINER (event_box), icon);
|
||||
gtk_widget_show (icon);
|
||||
|
||||
/* Now using again an event box on the whole grid, but behind its
|
||||
* child (so that the delete button is processed first. I do it
|
||||
* this way instead of using the "row-activated" of GtkListBox
|
||||
* because this signal does not give us event info, and in
|
||||
* particular modifier state. Yet I want to be able to process
|
||||
* Shift/Ctrl state for logical operations on layer sets.
|
||||
*/
|
||||
event_box = gtk_event_box_new ();
|
||||
gtk_event_box_set_above_child (GTK_EVENT_BOX (event_box), FALSE);
|
||||
gtk_widget_add_events (event_box, GDK_BUTTON_RELEASE_MASK);
|
||||
g_object_set_data (G_OBJECT (event_box), "link-set", iter->data);
|
||||
gtk_container_add (GTK_CONTAINER (event_box), grid);
|
||||
gtk_list_box_prepend (GTK_LIST_BOX (view->priv->link_list), event_box);
|
||||
gtk_widget_show (event_box);
|
||||
|
||||
g_signal_connect (event_box,
|
||||
"button-release-event",
|
||||
G_CALLBACK (gimp_item_tree_view_link_clicked),
|
||||
view);
|
||||
|
||||
gtk_widget_show (grid);
|
||||
}
|
||||
g_object_unref (label_size);
|
||||
gtk_list_box_unselect_all (GTK_LIST_BOX (view->priv->link_list));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_item_tree_view_link_clicked (GtkWidget *box,
|
||||
GdkEvent *event,
|
||||
GimpItemTreeView *view)
|
||||
{
|
||||
GimpImage *image;
|
||||
GdkEventButton *bevent = (GdkEventButton *) event;
|
||||
GdkModifierType modifiers;
|
||||
|
||||
image = gimp_item_tree_view_get_image (view);
|
||||
|
||||
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
|
||||
g_return_val_if_fail (GTK_IS_EVENT_BOX (box), FALSE);
|
||||
|
||||
modifiers = bevent->state & gimp_get_all_modifiers_mask ();
|
||||
if (modifiers == GDK_SHIFT_MASK)
|
||||
gimp_image_add_item_set (image, g_object_get_data (G_OBJECT (box), "link-set"));
|
||||
else if (modifiers == GDK_CONTROL_MASK)
|
||||
gimp_image_remove_item_set (image, g_object_get_data (G_OBJECT (box), "link-set"));
|
||||
else if (modifiers == (GDK_CONTROL_MASK | GDK_SHIFT_MASK))
|
||||
gimp_image_intersect_item_set (image, g_object_get_data (G_OBJECT (box), "link-set"));
|
||||
else
|
||||
gimp_image_select_item_set (image, g_object_get_data (G_OBJECT (box), "link-set"));
|
||||
|
||||
gtk_entry_set_text (GTK_ENTRY (view->priv->link_search_entry), "");
|
||||
/* TODO: if clicking on pattern link, fill in the pattern field? */
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_item_tree_view_unlink_clicked (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
GimpItemTreeView *view)
|
||||
{
|
||||
GimpImage *image;
|
||||
|
||||
image = gimp_item_tree_view_get_image (view);
|
||||
|
||||
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
|
||||
|
||||
gimp_image_unlink_item_set (image, g_object_get_data (G_OBJECT (widget), "link-set"));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
static gboolean
|
||||
gimp_item_tree_view_search_key_release (GtkWidget *widget,
|
||||
GdkEventKey *event,
|
||||
GimpItemTreeView *view)
|
||||
{
|
||||
GimpItemTreeViewClass *item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (view);
|
||||
GimpImage *image;
|
||||
const gchar *pattern;
|
||||
GimpSelectMethod pattern_syntax;
|
||||
|
||||
if (event->keyval == GDK_KEY_Escape ||
|
||||
event->keyval == GDK_KEY_Return ||
|
||||
event->keyval == GDK_KEY_KP_Enter ||
|
||||
event->keyval == GDK_KEY_ISO_Enter)
|
||||
{
|
||||
if (event->state & GDK_SHIFT_MASK)
|
||||
{
|
||||
if (gimp_item_tree_view_new_link_clicked (view))
|
||||
gtk_widget_hide (view->priv->search_popover);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_hide (view->priv->search_popover);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gtk_entry_set_attributes (GTK_ENTRY (view->priv->link_search_entry),
|
||||
NULL);
|
||||
|
||||
image = gimp_item_tree_view_get_image (GIMP_ITEM_TREE_VIEW (view));
|
||||
g_clear_object (&view->priv->link_pattern_set);
|
||||
|
||||
if (! image)
|
||||
return TRUE;
|
||||
|
||||
g_object_get (image->gimp->config,
|
||||
"items-select-method", &pattern_syntax,
|
||||
NULL);
|
||||
pattern = gtk_entry_get_text (GTK_ENTRY (view->priv->link_search_entry));
|
||||
if (pattern && strlen (pattern) > 0)
|
||||
{
|
||||
GList *items;
|
||||
GError *error = NULL;
|
||||
|
||||
gtk_entry_set_text (GTK_ENTRY (view->priv->link_entry), "");
|
||||
gtk_widget_set_sensitive (view->priv->link_entry, FALSE);
|
||||
|
||||
view->priv->link_pattern_set = gimp_item_list_pattern_new (image,
|
||||
item_view_class->item_type,
|
||||
pattern_syntax,
|
||||
pattern);
|
||||
items = gimp_item_list_get_items (view->priv->link_pattern_set, &error);
|
||||
if (error)
|
||||
{
|
||||
/* Invalid regular expression. */
|
||||
PangoAttrList *attrs = pango_attr_list_new ();
|
||||
gchar *tooltip;
|
||||
|
||||
pango_attr_list_insert (attrs, pango_attr_strikethrough_new (TRUE));
|
||||
tooltip = g_strdup_printf (_("Invalid regular expression: %s\n"),
|
||||
error->message);
|
||||
gtk_widget_set_tooltip_text (view->priv->link_search_entry,
|
||||
tooltip);
|
||||
gimp_image_set_selected_layers (image, NULL);
|
||||
gtk_entry_set_attributes (GTK_ENTRY (view->priv->link_search_entry),
|
||||
attrs);
|
||||
g_free (tooltip);
|
||||
g_error_free (error);
|
||||
pango_attr_list_unref (attrs);
|
||||
|
||||
g_clear_object (&view->priv->link_pattern_set);
|
||||
}
|
||||
else if (items == NULL)
|
||||
{
|
||||
/* Pattern does not match any results. */
|
||||
gimp_image_set_selected_layers (image, NULL);
|
||||
gimp_widget_blink (view->priv->link_search_entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_image_set_selected_layers (image, items);
|
||||
g_list_free (items);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_set_sensitive (view->priv->link_entry, TRUE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_item_tree_view_start_interactive_search (GtkTreeView *tree_view,
|
||||
GimpItemTreeView *layer_view)
|
||||
{
|
||||
gtk_widget_show (layer_view->priv->search_popover);
|
||||
gtk_widget_grab_focus (layer_view->priv->link_search_entry);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_item_tree_view_new_link_clicked (GimpItemTreeView *view)
|
||||
{
|
||||
GimpItemTreeViewClass *item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (view);
|
||||
GimpImage *image;
|
||||
const gchar *name;
|
||||
|
||||
image = gimp_item_tree_view_get_image (GIMP_ITEM_TREE_VIEW (view));
|
||||
|
||||
if (! image)
|
||||
return TRUE;
|
||||
|
||||
name = gtk_entry_get_text (GTK_ENTRY (view->priv->link_entry));
|
||||
if (name && strlen (name) > 0)
|
||||
{
|
||||
GimpItemList *set;
|
||||
|
||||
set = gimp_item_list_named_new (image,
|
||||
item_view_class->item_type,
|
||||
name, NULL);
|
||||
if (set)
|
||||
{
|
||||
gimp_image_store_item_set (image, set);
|
||||
gtk_entry_set_text (GTK_ENTRY (view->priv->link_entry), "");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No existing selection. */
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if (view->priv->link_pattern_set != NULL)
|
||||
{
|
||||
gimp_image_store_item_set (image, view->priv->link_pattern_set);
|
||||
view->priv->link_pattern_set = NULL;
|
||||
gtk_entry_set_text (GTK_ENTRY (view->priv->link_search_entry), "");
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_widget_blink (view->priv->link_entry);
|
||||
gimp_widget_blink (view->priv->link_search_entry);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_item_tree_view_new_link_exit (GimpItemTreeView *view)
|
||||
{
|
||||
if (gimp_item_tree_view_new_link_clicked (view))
|
||||
gtk_widget_hide (view->priv->search_popover);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_item_tree_view_search_clicked (GtkWidget *main_column_button,
|
||||
GdkEventButton *event,
|
||||
GimpItemTreeView *view)
|
||||
{
|
||||
gtk_popover_popup (GTK_POPOVER (view->priv->search_popover));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -77,14 +77,6 @@ struct _GimpLayerTreeViewPrivate
|
|||
GtkAdjustment *opacity_adjustment;
|
||||
GtkWidget *anchor_button;
|
||||
|
||||
GtkWidget *link_button;
|
||||
GtkWidget *link_popover;
|
||||
GtkWidget *new_link_button;
|
||||
GtkWidget *link_list;
|
||||
GtkWidget *link_entry;
|
||||
GtkWidget *link_search_entry;
|
||||
GimpItemList *link_pattern_set;
|
||||
|
||||
gint model_column_mask;
|
||||
gint model_column_mask_visible;
|
||||
|
||||
|
@ -105,8 +97,6 @@ static void gimp_layer_tree_view_view_iface_init (GimpContainer
|
|||
static void gimp_layer_tree_view_constructed (GObject *object);
|
||||
static void gimp_layer_tree_view_finalize (GObject *object);
|
||||
|
||||
static void gimp_layer_tree_view_style_updated (GtkWidget *widget);
|
||||
|
||||
static void gimp_layer_tree_view_set_container (GimpContainerView *view,
|
||||
GimpContainer *container);
|
||||
static void gimp_layer_tree_view_set_context (GimpContainerView *view,
|
||||
|
@ -150,26 +140,6 @@ static GimpItem * gimp_layer_tree_view_item_new (GimpImage
|
|||
static void gimp_layer_tree_view_floating_selection_changed (GimpImage *image,
|
||||
GimpLayerTreeView *view);
|
||||
|
||||
static void gimp_layer_tree_view_layer_links_changed (GimpImage *image,
|
||||
GimpLayerTreeView *view);
|
||||
static gboolean gimp_layer_tree_view_link_clicked (GtkWidget *box,
|
||||
GdkEvent *event,
|
||||
GimpLayerTreeView *view);
|
||||
static void gimp_layer_tree_view_link_popover_shown (GtkPopover *popover,
|
||||
GimpLayerTreeView *view);
|
||||
|
||||
static gboolean gimp_layer_tree_view_search_key_release (GtkWidget *widget,
|
||||
GdkEventKey *event,
|
||||
GimpLayerTreeView *view);
|
||||
static gboolean gimp_layer_tree_view_start_interactive_search (GtkTreeView *tree_view,
|
||||
GimpLayerTreeView *layer_view);
|
||||
|
||||
static void gimp_layer_tree_view_new_link_exit (GimpLayerTreeView *view);
|
||||
static gboolean gimp_layer_tree_view_new_link_clicked (GimpLayerTreeView *view);
|
||||
static gboolean gimp_layer_tree_view_unlink_clicked (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
GimpLayerTreeView *view);
|
||||
|
||||
static void gimp_layer_tree_view_layer_mode_box_callback (GtkWidget *widget,
|
||||
const GParamSpec *pspec,
|
||||
GimpLayerTreeView *view);
|
||||
|
@ -225,17 +195,13 @@ gimp_layer_tree_view_class_init (GimpLayerTreeViewClass *klass)
|
|||
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
||||
GimpContainerTreeViewClass *tree_view_class;
|
||||
GimpItemTreeViewClass *item_view_class;
|
||||
GtkWidgetClass *widget_class;
|
||||
|
||||
widget_class = GTK_WIDGET_CLASS (klass);
|
||||
tree_view_class = GIMP_CONTAINER_TREE_VIEW_CLASS (klass);
|
||||
item_view_class = GIMP_ITEM_TREE_VIEW_CLASS (klass);
|
||||
|
||||
object_class->constructed = gimp_layer_tree_view_constructed;
|
||||
object_class->finalize = gimp_layer_tree_view_finalize;
|
||||
|
||||
widget_class->style_updated = gimp_layer_tree_view_style_updated;
|
||||
|
||||
tree_view_class->drop_possible = gimp_layer_tree_view_drop_possible;
|
||||
tree_view_class->drop_color = gimp_layer_tree_view_drop_color;
|
||||
tree_view_class->drop_uri_list = gimp_layer_tree_view_drop_uri_list;
|
||||
|
@ -290,8 +256,6 @@ gimp_layer_tree_view_init (GimpLayerTreeView *view)
|
|||
|
||||
view->priv = gimp_layer_tree_view_get_instance_private (view);
|
||||
|
||||
view->priv->link_pattern_set = NULL;
|
||||
|
||||
view->priv->model_column_mask =
|
||||
gimp_container_tree_store_columns_add (tree_view->model_columns,
|
||||
&tree_view->n_model_columns,
|
||||
|
@ -351,10 +315,6 @@ gimp_layer_tree_view_constructed (GObject *object)
|
|||
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (object);
|
||||
GimpLayerTreeView *layer_view = GIMP_LAYER_TREE_VIEW (object);
|
||||
GtkWidget *button;
|
||||
GtkWidget *placeholder;
|
||||
GtkWidget *grid;
|
||||
PangoAttrList *attrs;
|
||||
GtkIconSize button_size;
|
||||
|
||||
G_OBJECT_CLASS (parent_class)->constructed (object);
|
||||
|
||||
|
@ -438,111 +398,6 @@ gimp_layer_tree_view_constructed (GObject *object)
|
|||
gtk_box_reorder_child (gimp_editor_get_button_box (GIMP_EDITOR (layer_view)),
|
||||
button, 7);
|
||||
|
||||
/* Link popover menu. */
|
||||
|
||||
layer_view->priv->link_button = gtk_menu_button_new ();
|
||||
gtk_widget_set_tooltip_text (layer_view->priv->link_button,
|
||||
_("Select layers by patterns and store layer sets"));
|
||||
gtk_widget_style_get (GTK_WIDGET (layer_view),
|
||||
"button-icon-size", &button_size,
|
||||
NULL);
|
||||
gtk_button_set_image (GTK_BUTTON (layer_view->priv->link_button),
|
||||
gtk_image_new_from_icon_name (GIMP_ICON_LINKED,
|
||||
button_size));
|
||||
gtk_box_pack_start (gimp_editor_get_button_box (GIMP_EDITOR (layer_view)),
|
||||
layer_view->priv->link_button, TRUE, TRUE, 0);
|
||||
gtk_widget_show (layer_view->priv->link_button);
|
||||
gimp_container_view_enable_dnd (GIMP_CONTAINER_VIEW (layer_view),
|
||||
GTK_BUTTON (layer_view->priv->link_button),
|
||||
GIMP_TYPE_LAYER);
|
||||
gtk_box_reorder_child (gimp_editor_get_button_box (GIMP_EDITOR (layer_view)),
|
||||
layer_view->priv->link_button, 8);
|
||||
|
||||
layer_view->priv->link_popover = gtk_popover_new (layer_view->priv->link_button);
|
||||
gtk_popover_set_modal (GTK_POPOVER (layer_view->priv->link_popover), TRUE);
|
||||
gtk_menu_button_set_popover (GTK_MENU_BUTTON (layer_view->priv->link_button),
|
||||
layer_view->priv->link_popover);
|
||||
|
||||
g_signal_connect (layer_view->priv->link_popover,
|
||||
"show",
|
||||
G_CALLBACK (gimp_layer_tree_view_link_popover_shown),
|
||||
layer_view);
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
|
||||
/* Link popover: regexp search. */
|
||||
layer_view->priv->link_search_entry = gtk_entry_new ();
|
||||
gtk_entry_set_icon_from_icon_name (GTK_ENTRY (layer_view->priv->link_search_entry),
|
||||
GTK_ENTRY_ICON_SECONDARY,
|
||||
"system-search");
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
layer_view->priv->link_search_entry,
|
||||
0, 0, 2, 1);
|
||||
gtk_widget_show (layer_view->priv->link_search_entry);
|
||||
g_signal_connect (layer_view->priv->link_search_entry,
|
||||
"key-release-event",
|
||||
G_CALLBACK (gimp_layer_tree_view_search_key_release),
|
||||
layer_view);
|
||||
|
||||
g_signal_connect (GIMP_CONTAINER_TREE_VIEW (layer_view)->view,
|
||||
"start-interactive-search",
|
||||
G_CALLBACK (gimp_layer_tree_view_start_interactive_search),
|
||||
layer_view);
|
||||
gtk_tree_view_set_search_entry (GIMP_CONTAINER_TREE_VIEW (layer_view)->view,
|
||||
GTK_ENTRY (layer_view->priv->link_search_entry));
|
||||
|
||||
/* Link popover: existing links. */
|
||||
layer_view->priv->link_list = gtk_list_box_new ();
|
||||
placeholder = gtk_label_new (_("No layer set stored"));
|
||||
attrs = pango_attr_list_new ();
|
||||
gtk_label_set_attributes (GTK_LABEL (placeholder),
|
||||
attrs);
|
||||
pango_attr_list_insert (attrs, pango_attr_style_new (PANGO_STYLE_ITALIC));
|
||||
pango_attr_list_insert (attrs, pango_attr_weight_new (PANGO_WEIGHT_ULTRALIGHT));
|
||||
pango_attr_list_unref (attrs);
|
||||
gtk_list_box_set_placeholder (GTK_LIST_BOX (layer_view->priv->link_list),
|
||||
placeholder);
|
||||
gtk_widget_show (placeholder);
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
layer_view->priv->link_list,
|
||||
0, 1, 2, 1);
|
||||
gtk_widget_show (layer_view->priv->link_list);
|
||||
|
||||
gtk_list_box_set_activate_on_single_click (GTK_LIST_BOX (layer_view->priv->link_list),
|
||||
TRUE);
|
||||
|
||||
/* Link popover: new links. */
|
||||
|
||||
layer_view->priv->link_entry = gtk_entry_new ();
|
||||
gtk_entry_set_placeholder_text (GTK_ENTRY (layer_view->priv->link_entry),
|
||||
_("New layer set's name"));
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
layer_view->priv->link_entry,
|
||||
0, 2, 1, 1);
|
||||
gtk_widget_show (layer_view->priv->link_entry);
|
||||
|
||||
button = gtk_button_new_from_icon_name (GIMP_ICON_LIST_ADD, button_size);
|
||||
gtk_grid_attach (GTK_GRID (grid),
|
||||
button,
|
||||
1, 2, 1, 1);
|
||||
g_signal_connect_swapped (button,
|
||||
"clicked",
|
||||
G_CALLBACK (gimp_layer_tree_view_new_link_clicked),
|
||||
layer_view);
|
||||
gtk_widget_show (button);
|
||||
layer_view->priv->new_link_button = button;
|
||||
|
||||
/* Enter on any entry activates the link creation then exits in case
|
||||
* of success.
|
||||
*/
|
||||
g_signal_connect_swapped (layer_view->priv->link_entry,
|
||||
"activate",
|
||||
G_CALLBACK (gimp_layer_tree_view_new_link_exit),
|
||||
layer_view);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (layer_view->priv->link_popover), grid);
|
||||
gtk_widget_show (grid);
|
||||
|
||||
/* Lock alpha toggle */
|
||||
|
||||
gimp_item_tree_view_add_lock (GIMP_ITEM_TREE_VIEW (tree_view),
|
||||
|
@ -582,50 +437,6 @@ gimp_layer_tree_view_finalize (GObject *object)
|
|||
}
|
||||
|
||||
|
||||
/* GimpWidget methods */
|
||||
|
||||
static void
|
||||
gimp_layer_tree_view_style_updated (GtkWidget *widget)
|
||||
{
|
||||
GimpLayerTreeView *view = GIMP_LAYER_TREE_VIEW (widget);
|
||||
GtkWidget *image;
|
||||
const gchar *old_icon_name;
|
||||
GtkReliefStyle button_relief;
|
||||
GtkIconSize old_size;
|
||||
GtkIconSize button_size;
|
||||
|
||||
gtk_widget_style_get (widget,
|
||||
"button-relief", &button_relief,
|
||||
"button-icon-size", &button_size,
|
||||
NULL);
|
||||
|
||||
gtk_button_set_relief (GTK_BUTTON (view->priv->link_button),
|
||||
button_relief);
|
||||
|
||||
image = gtk_button_get_image (GTK_BUTTON (view->priv->link_button));
|
||||
|
||||
gtk_image_get_icon_name (GTK_IMAGE (image), &old_icon_name, &old_size);
|
||||
|
||||
if (button_size != old_size)
|
||||
{
|
||||
gchar *icon_name;
|
||||
|
||||
/* Changing the link button in dockable button box. */
|
||||
icon_name = g_strdup (old_icon_name);
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (image),
|
||||
icon_name, button_size);
|
||||
g_free (icon_name);
|
||||
|
||||
/* Changing the new link button inside the popover. */
|
||||
image = gtk_button_get_image (GTK_BUTTON (view->priv->new_link_button));
|
||||
gtk_image_get_icon_name (GTK_IMAGE (image), &old_icon_name, &old_size);
|
||||
icon_name = g_strdup (old_icon_name);
|
||||
gtk_image_set_from_icon_name (GTK_IMAGE (image),
|
||||
icon_name, button_size);
|
||||
g_free (icon_name);
|
||||
}
|
||||
}
|
||||
|
||||
/* GimpContainerView methods */
|
||||
|
||||
static void
|
||||
|
@ -713,35 +524,9 @@ gimp_layer_tree_view_set_context (GimpContainerView *view,
|
|||
{
|
||||
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
|
||||
GimpLayerTreeView *layer_view = GIMP_LAYER_TREE_VIEW (view);
|
||||
GimpContext *old_context;
|
||||
|
||||
old_context = gimp_container_view_get_context (view);
|
||||
|
||||
if (old_context)
|
||||
{
|
||||
g_signal_handlers_disconnect_by_func (old_context->gimp->config,
|
||||
G_CALLBACK (gimp_layer_tree_view_style_updated),
|
||||
view);
|
||||
}
|
||||
|
||||
parent_view_iface->set_context (view, context);
|
||||
|
||||
if (context)
|
||||
{
|
||||
g_signal_connect_object (context->gimp->config,
|
||||
"notify::theme",
|
||||
G_CALLBACK (gimp_layer_tree_view_style_updated),
|
||||
view, G_CONNECT_AFTER | G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (context->gimp->config,
|
||||
"notify::override-theme-icon-size",
|
||||
G_CALLBACK (gimp_layer_tree_view_style_updated),
|
||||
view, G_CONNECT_AFTER | G_CONNECT_SWAPPED);
|
||||
g_signal_connect_object (context->gimp->config,
|
||||
"notify::custom-icon-size",
|
||||
G_CALLBACK (gimp_layer_tree_view_style_updated),
|
||||
view, G_CONNECT_AFTER | G_CONNECT_SWAPPED);
|
||||
}
|
||||
|
||||
if (tree_view->model)
|
||||
{
|
||||
SetContextForeachData context_data = { layer_view->priv->model_column_mask,
|
||||
|
@ -1116,9 +901,6 @@ gimp_layer_tree_view_set_image (GimpItemTreeView *view,
|
|||
g_signal_handlers_disconnect_by_func (gimp_item_tree_view_get_image (view),
|
||||
gimp_layer_tree_view_floating_selection_changed,
|
||||
view);
|
||||
g_signal_handlers_disconnect_by_func (gimp_item_tree_view_get_image (view),
|
||||
G_CALLBACK (gimp_layer_tree_view_layer_links_changed),
|
||||
view);
|
||||
}
|
||||
|
||||
GIMP_ITEM_TREE_VIEW_CLASS (parent_class)->set_image (view, image);
|
||||
|
@ -1129,10 +911,6 @@ gimp_layer_tree_view_set_image (GimpItemTreeView *view,
|
|||
"floating-selection-changed",
|
||||
G_CALLBACK (gimp_layer_tree_view_floating_selection_changed),
|
||||
view);
|
||||
g_signal_connect (gimp_item_tree_view_get_image (view),
|
||||
"layer-sets-changed",
|
||||
G_CALLBACK (gimp_layer_tree_view_layer_links_changed),
|
||||
view);
|
||||
|
||||
/* call gimp_layer_tree_view_floating_selection_changed() now, to update
|
||||
* the floating selection's row attributes.
|
||||
|
@ -1141,9 +919,6 @@ gimp_layer_tree_view_set_image (GimpItemTreeView *view,
|
|||
gimp_item_tree_view_get_image (view),
|
||||
layer_view);
|
||||
}
|
||||
/* Call this even with no image, allowing to empty the link list. */
|
||||
gimp_layer_tree_view_layer_links_changed (gimp_item_tree_view_get_image (view),
|
||||
layer_view);
|
||||
|
||||
gimp_layer_tree_view_update_highlight (layer_view);
|
||||
}
|
||||
|
@ -1220,356 +995,9 @@ gimp_layer_tree_view_floating_selection_changed (GimpImage *image,
|
|||
g_list_free (all_layers);
|
||||
}
|
||||
|
||||
gtk_widget_set_sensitive (layer_view->priv->link_button, ! floating_sel);
|
||||
|
||||
gimp_layer_tree_view_update_highlight (layer_view);
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_layer_tree_view_layer_links_changed (GimpImage *image,
|
||||
GimpLayerTreeView *view)
|
||||
{
|
||||
GtkWidget *grid;
|
||||
GtkWidget *label;
|
||||
GtkWidget *event_box;
|
||||
GtkWidget *icon;
|
||||
GtkSizeGroup *label_size;
|
||||
GList *links;
|
||||
GList *iter;
|
||||
|
||||
gtk_container_foreach (GTK_CONTAINER (view->priv->link_list),
|
||||
(GtkCallback) gtk_widget_destroy, NULL);
|
||||
gtk_widget_set_sensitive (view->priv->link_button, image != NULL);
|
||||
|
||||
if (! image)
|
||||
return;
|
||||
|
||||
links = gimp_image_get_stored_item_sets (image, GIMP_TYPE_LAYER);
|
||||
|
||||
label_size = gtk_size_group_new (GTK_SIZE_GROUP_BOTH);
|
||||
for (iter = links; iter; iter = iter->next)
|
||||
{
|
||||
GimpSelectMethod method;
|
||||
|
||||
grid = gtk_grid_new ();
|
||||
|
||||
label = gtk_label_new (gimp_object_get_name (iter->data));
|
||||
gtk_label_set_xalign (GTK_LABEL (label), 0.0);
|
||||
if (gimp_item_list_is_pattern (iter->data, &method))
|
||||
{
|
||||
gchar *display_name;
|
||||
PangoAttrList *attrs;
|
||||
|
||||
display_name = g_strdup_printf ("<small>[%s]</small> %s",
|
||||
method == GIMP_SELECT_PLAIN_TEXT ? _("search") :
|
||||
(method == GIMP_SELECT_GLOB_PATTERN ? _("glob") : _("regexp")),
|
||||
gimp_object_get_name (iter->data));
|
||||
gtk_label_set_markup (GTK_LABEL (label), display_name);
|
||||
g_free (display_name);
|
||||
|
||||
attrs = pango_attr_list_new ();
|
||||
pango_attr_list_insert (attrs, pango_attr_style_new (PANGO_STYLE_OBLIQUE));
|
||||
gtk_label_set_attributes (GTK_LABEL (label), attrs);
|
||||
pango_attr_list_unref (attrs);
|
||||
}
|
||||
gtk_widget_set_hexpand (GTK_WIDGET (label), TRUE);
|
||||
gtk_widget_set_halign (GTK_WIDGET (label), GTK_ALIGN_START);
|
||||
gtk_size_group_add_widget (label_size, label);
|
||||
gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
|
||||
gtk_widget_show (label);
|
||||
|
||||
/* I don't use a GtkButton because the minimum size is 16 which is
|
||||
* weird and ugly here. And somehow if I force smaller GtkImage
|
||||
* size then add it to the GtkButton, I still get a giant button
|
||||
* with a small image in it, which is even worse. XXX
|
||||
*/
|
||||
event_box = gtk_event_box_new ();
|
||||
gtk_event_box_set_above_child (GTK_EVENT_BOX (event_box), TRUE);
|
||||
gtk_widget_add_events (event_box, GDK_BUTTON_RELEASE_MASK);
|
||||
g_object_set_data (G_OBJECT (event_box), "link-set", iter->data);
|
||||
g_signal_connect (event_box, "button-release-event",
|
||||
G_CALLBACK (gimp_layer_tree_view_unlink_clicked),
|
||||
view);
|
||||
gtk_grid_attach (GTK_GRID (grid), event_box, 2, 0, 1, 1);
|
||||
gtk_widget_show (event_box);
|
||||
|
||||
icon = gtk_image_new_from_icon_name (GIMP_ICON_EDIT_DELETE, GTK_ICON_SIZE_MENU);
|
||||
gtk_image_set_pixel_size (GTK_IMAGE (icon), 10);
|
||||
gtk_container_add (GTK_CONTAINER (event_box), icon);
|
||||
gtk_widget_show (icon);
|
||||
|
||||
/* Now using again an event box on the whole grid, but behind its
|
||||
* child (so that the delete button is processed first. I do it
|
||||
* this way instead of using the "row-activated" of GtkListBox
|
||||
* because this signal does not give us event info, and in
|
||||
* particular modifier state. Yet I want to be able to process
|
||||
* Shift/Ctrl state for logical operations on layer sets.
|
||||
*/
|
||||
event_box = gtk_event_box_new ();
|
||||
gtk_event_box_set_above_child (GTK_EVENT_BOX (event_box), FALSE);
|
||||
gtk_widget_add_events (event_box, GDK_BUTTON_RELEASE_MASK);
|
||||
g_object_set_data (G_OBJECT (event_box), "link-set", iter->data);
|
||||
gtk_container_add (GTK_CONTAINER (event_box), grid);
|
||||
gtk_list_box_prepend (GTK_LIST_BOX (view->priv->link_list), event_box);
|
||||
gtk_widget_show (event_box);
|
||||
|
||||
g_signal_connect (event_box,
|
||||
"button-release-event",
|
||||
G_CALLBACK (gimp_layer_tree_view_link_clicked),
|
||||
view);
|
||||
|
||||
gtk_widget_show (grid);
|
||||
}
|
||||
g_object_unref (label_size);
|
||||
gtk_list_box_unselect_all (GTK_LIST_BOX (view->priv->link_list));
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_layer_tree_view_link_clicked (GtkWidget *box,
|
||||
GdkEvent *event,
|
||||
GimpLayerTreeView *view)
|
||||
{
|
||||
GimpImage *image;
|
||||
GdkEventButton *bevent = (GdkEventButton *) event;
|
||||
GdkModifierType modifiers;
|
||||
|
||||
image = gimp_item_tree_view_get_image (GIMP_ITEM_TREE_VIEW (view));
|
||||
|
||||
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
|
||||
g_return_val_if_fail (GTK_IS_EVENT_BOX (box), FALSE);
|
||||
|
||||
modifiers = bevent->state & gimp_get_all_modifiers_mask ();
|
||||
if (modifiers == GDK_SHIFT_MASK)
|
||||
gimp_image_add_item_set (image, g_object_get_data (G_OBJECT (box), "link-set"));
|
||||
else if (modifiers == GDK_CONTROL_MASK)
|
||||
gimp_image_remove_item_set (image, g_object_get_data (G_OBJECT (box), "link-set"));
|
||||
else if (modifiers == (GDK_CONTROL_MASK | GDK_SHIFT_MASK))
|
||||
gimp_image_intersect_item_set (image, g_object_get_data (G_OBJECT (box), "link-set"));
|
||||
else
|
||||
gimp_image_select_item_set (image, g_object_get_data (G_OBJECT (box), "link-set"));
|
||||
|
||||
gtk_entry_set_text (GTK_ENTRY (view->priv->link_search_entry), "");
|
||||
/* TODO: if clicking on pattern link, fill in the pattern field? */
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_layer_tree_view_link_popover_shown (GtkPopover *popover,
|
||||
GimpLayerTreeView *view)
|
||||
{
|
||||
GimpImage *image;
|
||||
GimpSelectMethod pattern_syntax;
|
||||
|
||||
image = gimp_item_tree_view_get_image (GIMP_ITEM_TREE_VIEW (view));
|
||||
|
||||
if (! image)
|
||||
{
|
||||
gtk_widget_set_tooltip_text (view->priv->link_search_entry,
|
||||
_("Select layers by text search"));
|
||||
gtk_entry_set_placeholder_text (GTK_ENTRY (view->priv->link_search_entry),
|
||||
_("Text search"));
|
||||
return;
|
||||
}
|
||||
|
||||
g_object_get (image->gimp->config,
|
||||
"items-select-method", &pattern_syntax,
|
||||
NULL);
|
||||
switch (pattern_syntax)
|
||||
{
|
||||
case GIMP_SELECT_PLAIN_TEXT:
|
||||
gtk_widget_set_tooltip_text (view->priv->link_search_entry,
|
||||
_("Select layers by text search"));
|
||||
gtk_entry_set_placeholder_text (GTK_ENTRY (view->priv->link_search_entry),
|
||||
_("Text search"));
|
||||
break;
|
||||
case GIMP_SELECT_GLOB_PATTERN:
|
||||
gtk_widget_set_tooltip_text (view->priv->link_search_entry,
|
||||
_("Select layers by glob patterns"));
|
||||
gtk_entry_set_placeholder_text (GTK_ENTRY (view->priv->link_search_entry),
|
||||
_("Glob pattern search"));
|
||||
break;
|
||||
case GIMP_SELECT_REGEX_PATTERN:
|
||||
gtk_widget_set_tooltip_text (view->priv->link_search_entry,
|
||||
_("Select layers by regular expressions"));
|
||||
gtk_entry_set_placeholder_text (GTK_ENTRY (view->priv->link_search_entry),
|
||||
_("Regular Expression search"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_layer_tree_view_search_key_release (GtkWidget *widget,
|
||||
GdkEventKey *event,
|
||||
GimpLayerTreeView *view)
|
||||
{
|
||||
GimpImage *image;
|
||||
const gchar *pattern;
|
||||
GimpSelectMethod pattern_syntax;
|
||||
|
||||
if (event->keyval == GDK_KEY_Escape ||
|
||||
event->keyval == GDK_KEY_Return ||
|
||||
event->keyval == GDK_KEY_KP_Enter ||
|
||||
event->keyval == GDK_KEY_ISO_Enter)
|
||||
{
|
||||
if (event->state & GDK_SHIFT_MASK)
|
||||
{
|
||||
if (gimp_layer_tree_view_new_link_clicked (view))
|
||||
gtk_widget_hide (view->priv->link_popover);
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_hide (view->priv->link_popover);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gtk_entry_set_attributes (GTK_ENTRY (view->priv->link_search_entry),
|
||||
NULL);
|
||||
|
||||
image = gimp_item_tree_view_get_image (GIMP_ITEM_TREE_VIEW (view));
|
||||
g_clear_object (&view->priv->link_pattern_set);
|
||||
|
||||
if (! image)
|
||||
return TRUE;
|
||||
|
||||
g_object_get (image->gimp->config,
|
||||
"items-select-method", &pattern_syntax,
|
||||
NULL);
|
||||
pattern = gtk_entry_get_text (GTK_ENTRY (view->priv->link_search_entry));
|
||||
if (pattern && strlen (pattern) > 0)
|
||||
{
|
||||
GList *items;
|
||||
GError *error = NULL;
|
||||
|
||||
gtk_entry_set_text (GTK_ENTRY (view->priv->link_entry), "");
|
||||
gtk_widget_set_sensitive (view->priv->link_entry, FALSE);
|
||||
|
||||
view->priv->link_pattern_set = gimp_item_list_pattern_new (image,
|
||||
GIMP_TYPE_LAYER,
|
||||
pattern_syntax,
|
||||
pattern);
|
||||
items = gimp_item_list_get_items (view->priv->link_pattern_set, &error);
|
||||
if (error)
|
||||
{
|
||||
/* Invalid regular expression. */
|
||||
PangoAttrList *attrs = pango_attr_list_new ();
|
||||
gchar *tooltip;
|
||||
|
||||
pango_attr_list_insert (attrs, pango_attr_strikethrough_new (TRUE));
|
||||
tooltip = g_strdup_printf (_("Invalid regular expression: %s\n"),
|
||||
error->message);
|
||||
gtk_widget_set_tooltip_text (view->priv->link_search_entry,
|
||||
tooltip);
|
||||
gimp_image_set_selected_layers (image, NULL);
|
||||
gtk_entry_set_attributes (GTK_ENTRY (view->priv->link_search_entry),
|
||||
attrs);
|
||||
g_free (tooltip);
|
||||
g_error_free (error);
|
||||
pango_attr_list_unref (attrs);
|
||||
|
||||
g_clear_object (&view->priv->link_pattern_set);
|
||||
}
|
||||
else if (items == NULL)
|
||||
{
|
||||
/* Pattern does not match any results. */
|
||||
gimp_image_set_selected_layers (image, NULL);
|
||||
gimp_widget_blink (view->priv->link_search_entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_image_set_selected_layers (image, items);
|
||||
g_list_free (items);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_widget_set_sensitive (view->priv->link_entry, TRUE);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_layer_tree_view_start_interactive_search (GtkTreeView *tree_view,
|
||||
GimpLayerTreeView *layer_view)
|
||||
{
|
||||
gtk_widget_show (layer_view->priv->link_popover);
|
||||
gtk_widget_grab_focus (layer_view->priv->link_search_entry);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gimp_layer_tree_view_new_link_exit (GimpLayerTreeView *view)
|
||||
{
|
||||
if (gimp_layer_tree_view_new_link_clicked (view))
|
||||
gtk_widget_hide (view->priv->link_popover);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_layer_tree_view_new_link_clicked (GimpLayerTreeView *view)
|
||||
{
|
||||
GimpImage *image;
|
||||
const gchar *name;
|
||||
|
||||
image = gimp_item_tree_view_get_image (GIMP_ITEM_TREE_VIEW (view));
|
||||
|
||||
if (! image)
|
||||
return TRUE;
|
||||
|
||||
name = gtk_entry_get_text (GTK_ENTRY (view->priv->link_entry));
|
||||
if (name && strlen (name) > 0)
|
||||
{
|
||||
GimpItemList *set;
|
||||
|
||||
set = gimp_item_list_named_new (image, GIMP_TYPE_LAYER, name, NULL);
|
||||
if (set)
|
||||
{
|
||||
gimp_image_store_item_set (image, set);
|
||||
gtk_entry_set_text (GTK_ENTRY (view->priv->link_entry), "");
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No existing selection. */
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else if (view->priv->link_pattern_set != NULL)
|
||||
{
|
||||
gimp_image_store_item_set (image, view->priv->link_pattern_set);
|
||||
view->priv->link_pattern_set = NULL;
|
||||
gtk_entry_set_text (GTK_ENTRY (view->priv->link_search_entry), "");
|
||||
}
|
||||
else
|
||||
{
|
||||
gimp_widget_blink (view->priv->link_entry);
|
||||
gimp_widget_blink (view->priv->link_search_entry);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gimp_layer_tree_view_unlink_clicked (GtkWidget *widget,
|
||||
GdkEvent *event,
|
||||
GimpLayerTreeView *view)
|
||||
{
|
||||
GimpImage *image;
|
||||
|
||||
image = gimp_item_tree_view_get_image (GIMP_ITEM_TREE_VIEW (view));
|
||||
|
||||
g_return_val_if_fail (GIMP_IS_IMAGE (image), FALSE);
|
||||
|
||||
gimp_image_unlink_item_set (image,
|
||||
g_object_get_data (G_OBJECT (widget),
|
||||
"link-set"));
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* Paint Mode, Opacity and Lock alpha callbacks */
|
||||
|
||||
|
|
Loading…
Reference in New Issue