2006-12-09 21:33:38 +00:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
2001-02-27 14:14:13 +00:00
|
|
|
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
|
|
|
|
*
|
2003-03-16 11:14:29 +00:00
|
|
|
* gimpitemtreeview.c
|
2011-10-12 11:13:41 +02:00
|
|
|
* Copyright (C) 2001-2011 Michael Natterer <mitch@gimp.org>
|
2001-04-22 00:38:56 +00:00
|
|
|
*
|
2009-01-17 22:28:01 +00:00
|
|
|
* This program is free software: you can redistribute it and/or modify
|
2001-02-27 14:14:13 +00:00
|
|
|
* it under the terms of the GNU General Public License as published by
|
2009-01-17 22:28:01 +00:00
|
|
|
* the Free Software Foundation; either version 3 of the License, or
|
2001-02-27 14:14:13 +00:00
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2018-07-11 23:27:07 +02:00
|
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
2001-02-27 14:14:13 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2004-12-10 22:11:29 +00:00
|
|
|
#include <string.h>
|
|
|
|
|
2008-10-09 20:24:04 +00:00
|
|
|
#include <gegl.h>
|
2001-02-27 14:14:13 +00:00
|
|
|
#include <gtk/gtk.h>
|
|
|
|
|
2025-01-26 03:15:09 +00:00
|
|
|
#include "libgimpbase/gimpbase.h"
|
2001-02-27 14:14:13 +00:00
|
|
|
#include "libgimpmath/gimpmath.h"
|
|
|
|
#include "libgimpwidgets/gimpwidgets.h"
|
2024-02-14 16:50:26 +01:00
|
|
|
#include "libgimpwidgets/gimpwidgets-private.h"
|
2001-02-27 14:14:13 +00:00
|
|
|
|
2024-06-19 13:42:41 -04:00
|
|
|
#include "gimphelp-ids.h"
|
2001-05-08 03:48:54 +00:00
|
|
|
#include "widgets-types.h"
|
2025-01-26 03:15:09 +00:00
|
|
|
#include "tools/tools-types.h"
|
2001-02-27 14:14:13 +00:00
|
|
|
|
2023-06-19 14:54:21 +00:00
|
|
|
#include "actions/gimpgeglprocedure.h"
|
|
|
|
#include "actions/filters-commands.h"
|
|
|
|
|
2024-01-03 18:57:08 +00:00
|
|
|
#include "config/gimpguiconfig.h"
|
|
|
|
|
2007-12-12 13:57:11 +00:00
|
|
|
#include "core/gimp.h"
|
2023-06-19 14:54:21 +00:00
|
|
|
#include "core/gimp-filter-history.h"
|
2001-05-09 02:32:03 +00:00
|
|
|
#include "core/gimpchannel.h"
|
|
|
|
#include "core/gimpcontainer.h"
|
2003-10-10 21:24:12 +00:00
|
|
|
#include "core/gimpcontext.h"
|
2023-06-19 14:54:21 +00:00
|
|
|
#include "core/gimpdrawable-filters.h"
|
|
|
|
#include "core/gimpdrawablefilter.h"
|
|
|
|
#include "core/gimpdrawablefilterundo.h"
|
2001-05-09 02:32:03 +00:00
|
|
|
#include "core/gimpimage.h"
|
2003-09-11 19:52:29 +00:00
|
|
|
#include "core/gimpimage-undo.h"
|
2004-03-18 19:39:19 +00:00
|
|
|
#include "core/gimpimage-undo-push.h"
|
2011-10-12 11:13:41 +02:00
|
|
|
#include "core/gimpitem-exclusive.h"
|
2024-02-06 21:05:43 +01:00
|
|
|
#include "core/gimpitemlist.h"
|
2004-03-18 17:01:46 +00:00
|
|
|
#include "core/gimpitemundo.h"
|
2023-06-19 14:54:21 +00:00
|
|
|
#include "core/gimplist.h"
|
2024-01-03 18:57:08 +00:00
|
|
|
#include "core/gimptoolinfo.h"
|
2009-08-04 20:20:09 +02:00
|
|
|
#include "core/gimptreehandler.h"
|
2004-03-18 17:01:46 +00:00
|
|
|
#include "core/gimpundostack.h"
|
2001-05-09 02:32:03 +00:00
|
|
|
|
2025-01-26 03:15:09 +00:00
|
|
|
#include "tools/tool_manager.h"
|
|
|
|
|
2024-07-12 06:16:25 +00:00
|
|
|
#include "vectors/gimppath.h"
|
2002-02-26 05:42:14 +00:00
|
|
|
|
2019-07-02 03:54:38 +02:00
|
|
|
#include "gimpaction.h"
|
2010-05-17 21:22:36 +02:00
|
|
|
#include "gimpcontainertreestore.h"
|
2004-05-10 23:22:39 +00:00
|
|
|
#include "gimpcontainerview.h"
|
2001-05-08 03:48:54 +00:00
|
|
|
#include "gimpdnd.h"
|
2003-10-10 21:24:12 +00:00
|
|
|
#include "gimpdocked.h"
|
2004-10-16 20:17:30 +00:00
|
|
|
#include "gimpitemtreeview.h"
|
2023-06-19 14:54:21 +00:00
|
|
|
#include "gimplayertreeview.h"
|
2003-01-10 17:55:53 +00:00
|
|
|
#include "gimpmenufactory.h"
|
2004-08-25 22:31:44 +00:00
|
|
|
#include "gimpviewrenderer.h"
|
2004-04-22 17:14:22 +00:00
|
|
|
#include "gimpuimanager.h"
|
2002-12-19 16:33:29 +00:00
|
|
|
#include "gimpwidgets-utils.h"
|
2001-05-03 12:26:05 +00:00
|
|
|
|
2003-03-25 16:38:19 +00:00
|
|
|
#include "gimp-intl.h"
|
2001-02-27 14:14:13 +00:00
|
|
|
|
|
|
|
|
2024-01-03 18:57:08 +00:00
|
|
|
#define COLUMN_EFFECTS_ACTIVE 3
|
|
|
|
|
|
|
|
|
2001-05-03 12:26:05 +00:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
SET_IMAGE,
|
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
|
|
|
|
app, libgimp*, modules: don't use g_type_class_add_private() ...
... and G_TYPE_INSTANCE_GET_PRIVATE()
g_type_class_add_private() and G_TYPE_INSTANCE_GET_PRIVATE() were
deprecated in GLib 2.58. Instead, use
G_DEFINE_[ABSTRACT_]TYPE_WITH_PRIVATE(), and
G_ADD_PRIVATE[_DYNAMIC](), and the implictly-defined
foo_get_instance_private() functions, all of which are available in
the GLib versions we depend on.
This commit only covers types registered using one of the
G_DEFINE_FOO() macros (i.e., most types), but not types with a
custom registration function, of which we still have a few -- GLib
currently only provides a (non-deprecated) public API for adding a
private struct using the G_DEFINE_FOO() macros.
Note that this commit was 99% auto-generated (because I'm not
*that* crazy :), so if there are any style mismatches... we'll have
to live with them for now.
2018-09-18 12:09:39 -04:00
|
|
|
struct _GimpItemTreeViewPrivate
|
2008-12-25 11:31:51 +00:00
|
|
|
{
|
|
|
|
GimpImage *image;
|
|
|
|
|
2009-08-19 10:44:38 +02:00
|
|
|
GtkWidget *options_box;
|
|
|
|
GtkSizeGroup *options_group;
|
2021-02-09 00:04:05 +01:00
|
|
|
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
GtkWidget *eye_header_image;
|
|
|
|
GtkWidget *lock_header_image;
|
2024-01-30 04:06:39 +00:00
|
|
|
GtkWidget *effect_header_image;
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
|
2021-02-09 00:04:05 +01:00
|
|
|
GimpItem *lock_box_item;
|
2021-02-11 10:33:57 +01:00
|
|
|
GtkTreePath *lock_box_path;
|
2021-02-09 00:04:05 +01:00
|
|
|
GtkWidget *lock_popover;
|
|
|
|
GtkWidget *lock_box;
|
2009-08-19 21:29:34 +02:00
|
|
|
|
2023-06-19 14:54:21 +00:00
|
|
|
GtkWidget *effects_popover;
|
|
|
|
GtkWidget *effects_box;
|
|
|
|
GtkWidget *effects_filters;
|
|
|
|
GtkWidget *effects_options;
|
|
|
|
|
|
|
|
GtkWidget *effects_visible_button;
|
|
|
|
GtkWidget *effects_edit_button;
|
|
|
|
GtkWidget *effects_raise_button;
|
|
|
|
GtkWidget *effects_lower_button;
|
|
|
|
GtkWidget *effects_merge_button;
|
|
|
|
GtkWidget *effects_remove_button;
|
|
|
|
GimpDrawable *effects_drawable;
|
|
|
|
GimpDrawableFilter
|
|
|
|
*effects_filter;
|
|
|
|
|
2021-02-09 13:12:35 +01:00
|
|
|
GList *locks;
|
2021-02-09 02:39:37 +01:00
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
GtkWidget *new_button;
|
|
|
|
GtkWidget *raise_button;
|
|
|
|
GtkWidget *lower_button;
|
|
|
|
GtkWidget *duplicate_button;
|
|
|
|
GtkWidget *delete_button;
|
|
|
|
|
|
|
|
gint model_column_visible;
|
2011-09-23 23:45:10 +02:00
|
|
|
gint model_column_viewable;
|
2021-02-09 00:04:05 +01:00
|
|
|
gint model_column_locked;
|
|
|
|
gint model_column_lock_icon;
|
2016-10-29 16:50:13 +02:00
|
|
|
gint model_column_color_tag;
|
2023-06-19 14:54:21 +00:00
|
|
|
gint model_column_effects;
|
2008-12-25 11:31:51 +00:00
|
|
|
GtkCellRenderer *eye_cell;
|
2021-02-09 00:04:05 +01:00
|
|
|
GtkCellRenderer *lock_cell;
|
2023-06-19 14:54:21 +00:00
|
|
|
GtkCellRenderer *effects_cell;
|
2008-12-25 11:31:51 +00:00
|
|
|
|
2009-08-04 20:20:09 +02:00
|
|
|
GimpTreeHandler *visible_changed_handler;
|
2016-10-29 16:50:13 +02:00
|
|
|
GimpTreeHandler *color_tag_changed_handler;
|
2023-06-19 14:54:21 +00:00
|
|
|
GimpTreeHandler *filters_changed_handler;
|
2024-01-03 18:57:08 +00:00
|
|
|
GimpTreeHandler *filters_active_changed_handler;
|
2024-02-06 21:05:43 +01:00
|
|
|
|
|
|
|
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;
|
2008-12-25 11:31:51 +00:00
|
|
|
};
|
|
|
|
|
2021-02-09 02:39:37 +01:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
GtkWidget *toggle;
|
|
|
|
const gchar *icon_name;
|
|
|
|
|
|
|
|
GimpIsLockedFunc is_locked;
|
|
|
|
GimpCanLockFunc can_lock;
|
|
|
|
GimpSetLockFunc lock;
|
2021-02-11 16:17:36 +01:00
|
|
|
GimpUndoLockPush undo_push;
|
2021-02-09 02:39:37 +01:00
|
|
|
|
|
|
|
const gchar *tooltip;
|
|
|
|
const gchar *help_id;
|
|
|
|
|
|
|
|
/* Signal handling when lock is changed from core. */
|
|
|
|
const gchar *signal_name;
|
|
|
|
GimpTreeHandler *changed_handler;
|
|
|
|
|
|
|
|
/* Undo types and labels. */
|
|
|
|
GimpUndoType undo_type;
|
|
|
|
GimpUndoType group_undo_type;
|
2021-02-11 16:17:36 +01:00
|
|
|
const gchar *undo_lock_desc;
|
|
|
|
const gchar *undo_unlock_desc;
|
|
|
|
const gchar *undo_exclusive_desc;
|
2021-02-09 02:39:37 +01:00
|
|
|
} LockToggle;
|
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
|
2004-05-10 23:22:39 +00:00
|
|
|
static void gimp_item_tree_view_view_iface_init (GimpContainerViewInterface *view_iface);
|
|
|
|
static void gimp_item_tree_view_docked_iface_init (GimpDockedInterface *docked_iface);
|
|
|
|
|
2011-01-14 09:38:11 +01:00
|
|
|
static void gimp_item_tree_view_constructed (GObject *object);
|
2010-10-15 14:08:36 +02:00
|
|
|
static void gimp_item_tree_view_dispose (GObject *object);
|
2002-02-25 17:58:50 +00:00
|
|
|
|
2011-01-09 20:38:01 +01:00
|
|
|
static void gimp_item_tree_view_style_updated (GtkWidget *widget);
|
2009-08-19 10:44:38 +02:00
|
|
|
|
2003-03-16 11:14:29 +00:00
|
|
|
static void gimp_item_tree_view_real_set_image (GimpItemTreeView *view,
|
2006-03-28 17:08:36 +00:00
|
|
|
GimpImage *image);
|
2024-08-14 23:34:27 +02:00
|
|
|
static gboolean gimp_item_tree_view_key_press_event (GtkTreeView *tree_view,
|
|
|
|
GdkEventKey *event,
|
|
|
|
GimpItemTreeView *view);
|
2002-02-25 17:58:50 +00:00
|
|
|
|
2006-03-28 17:08:36 +00:00
|
|
|
static void gimp_item_tree_view_image_flush (GimpImage *image,
|
2007-06-26 21:39:51 +00:00
|
|
|
gboolean invalidate_preview,
|
2004-10-15 12:27:07 +00:00
|
|
|
GimpItemTreeView *view);
|
2023-07-09 23:10:57 +02:00
|
|
|
static gboolean
|
|
|
|
gimp_item_tree_view_image_flush_idle (gpointer user_data);
|
2004-10-15 12:27:07 +00:00
|
|
|
|
2003-05-08 20:26:01 +00:00
|
|
|
static void gimp_item_tree_view_set_container (GimpContainerView *view,
|
|
|
|
GimpContainer *container);
|
2006-08-31 21:40:16 +00:00
|
|
|
static void gimp_item_tree_view_set_context (GimpContainerView *view,
|
|
|
|
GimpContext *context);
|
|
|
|
|
2003-05-08 20:26:01 +00:00
|
|
|
static gpointer gimp_item_tree_view_insert_item (GimpContainerView *view,
|
|
|
|
GimpViewable *viewable,
|
2009-08-01 19:13:35 +02:00
|
|
|
gpointer parent_insert_data,
|
2003-05-08 20:26:01 +00:00
|
|
|
gint index);
|
2020-03-31 16:10:29 +02:00
|
|
|
static void gimp_item_tree_view_insert_items_after (GimpContainerView *view);
|
2020-03-21 19:03:07 +01:00
|
|
|
static gboolean gimp_item_tree_view_select_items (GimpContainerView *view,
|
|
|
|
GList *items,
|
|
|
|
GList *paths);
|
2003-03-16 11:14:29 +00:00
|
|
|
static void gimp_item_tree_view_activate_item (GimpContainerView *view,
|
2002-02-25 17:58:50 +00:00
|
|
|
GimpViewable *item,
|
|
|
|
gpointer insert_data);
|
|
|
|
|
2003-03-19 15:17:13 +00:00
|
|
|
static gboolean gimp_item_tree_view_drop_possible (GimpContainerTreeView *view,
|
2004-06-28 22:07:12 +00:00
|
|
|
GimpDndType src_type,
|
2020-03-24 22:06:28 +01:00
|
|
|
GList *src_viewables,
|
2003-03-19 15:17:13 +00:00
|
|
|
GimpViewable *dest_viewable,
|
2009-12-28 21:10:04 +01:00
|
|
|
GtkTreePath *drop_path,
|
2003-03-19 15:17:13 +00:00
|
|
|
GtkTreeViewDropPosition drop_pos,
|
2004-06-28 22:07:12 +00:00
|
|
|
GtkTreeViewDropPosition *return_drop_pos,
|
|
|
|
GdkDragAction *return_drag_action);
|
2020-03-24 22:06:28 +01:00
|
|
|
static void gimp_item_tree_view_drop_viewables (GimpContainerTreeView *view,
|
|
|
|
GList *src_viewables,
|
|
|
|
GimpViewable *dest_viewable,
|
2003-03-19 15:17:13 +00:00
|
|
|
GtkTreeViewDropPosition drop_pos);
|
|
|
|
|
2003-03-16 11:14:29 +00:00
|
|
|
static void gimp_item_tree_view_new_dropped (GtkWidget *widget,
|
2004-12-31 14:36:30 +00:00
|
|
|
gint x,
|
|
|
|
gint y,
|
2002-02-25 17:58:50 +00:00
|
|
|
GimpViewable *viewable,
|
|
|
|
gpointer data);
|
2020-03-24 22:06:28 +01:00
|
|
|
static void gimp_item_tree_view_new_list_dropped (GtkWidget *widget,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
GList *viewables,
|
|
|
|
gpointer data);
|
2002-02-25 17:58:50 +00:00
|
|
|
|
2006-03-28 17:08:36 +00:00
|
|
|
static void gimp_item_tree_view_item_changed (GimpImage *image,
|
2003-03-16 11:14:29 +00:00
|
|
|
GimpItemTreeView *view);
|
2006-03-28 17:08:36 +00:00
|
|
|
static void gimp_item_tree_view_size_changed (GimpImage *image,
|
2003-03-16 11:14:29 +00:00
|
|
|
GimpItemTreeView *view);
|
|
|
|
|
|
|
|
static void gimp_item_tree_view_name_edited (GtkCellRendererText *cell,
|
|
|
|
const gchar *path,
|
2004-12-10 21:07:28 +00:00
|
|
|
const gchar *new_name,
|
2003-03-16 11:14:29 +00:00
|
|
|
GimpItemTreeView *view);
|
2001-02-27 14:14:13 +00:00
|
|
|
|
2021-02-09 00:04:05 +01:00
|
|
|
static void gimp_item_tree_view_visible_changed (GimpItem *item,
|
|
|
|
GimpItemTreeView *view);
|
|
|
|
static void gimp_item_tree_view_color_tag_changed (GimpItem *item,
|
|
|
|
GimpItemTreeView *view);
|
|
|
|
static void gimp_item_tree_view_lock_changed (GimpItem *item,
|
|
|
|
GimpItemTreeView *view);
|
2023-06-19 14:54:21 +00:00
|
|
|
static void gimp_item_tree_view_filters_changed (GimpItem *item,
|
|
|
|
GimpItemTreeView *view);
|
2003-09-11 19:52:29 +00:00
|
|
|
|
|
|
|
static void gimp_item_tree_view_eye_clicked (GtkCellRendererToggle *toggle,
|
|
|
|
gchar *path,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpItemTreeView *view);
|
2021-02-09 00:04:05 +01:00
|
|
|
static void gimp_item_tree_view_lock_clicked (GtkCellRendererToggle *toggle,
|
2003-05-08 20:26:01 +00:00
|
|
|
gchar *path,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpItemTreeView *view);
|
2023-06-19 14:54:21 +00:00
|
|
|
static void gimp_item_tree_view_effects_clicked (GtkCellRendererToggle *toggle,
|
|
|
|
gchar *path,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpItemTreeView *view);
|
|
|
|
static gboolean
|
|
|
|
gimp_item_tree_view_effects_filters_selected
|
|
|
|
(GimpContainerView *view,
|
|
|
|
GList *filters,
|
|
|
|
GList *paths,
|
|
|
|
GimpItemTreeView *item_view);
|
|
|
|
static void gimp_item_tree_view_effects_activate_filter
|
|
|
|
(GtkWidget *widget,
|
|
|
|
GimpViewable *viewable,
|
|
|
|
gpointer insert_data,
|
|
|
|
GimpItemTreeView *view);
|
2024-01-03 18:57:08 +00:00
|
|
|
static void gimp_item_tree_view_filter_active_changed
|
|
|
|
(GimpFilter *item,
|
|
|
|
GimpContainerTreeView
|
|
|
|
*view);
|
2023-06-19 14:54:21 +00:00
|
|
|
|
|
|
|
static void gimp_item_tree_view_effects_visible_toggled
|
2024-01-03 18:57:08 +00:00
|
|
|
(GtkCellRendererToggle *toggle,
|
|
|
|
gchar *path_str,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpContainerTreeView *view);
|
|
|
|
|
|
|
|
static void gimp_item_tree_view_effects_visible_all_toggled
|
2023-06-19 14:54:21 +00:00
|
|
|
(GtkWidget *widget,
|
|
|
|
GimpItemTreeView *view);
|
2025-05-28 22:15:41 +02:00
|
|
|
static void gimp_item_tree_view_effects_edit_clicked
|
2023-06-19 14:54:21 +00:00
|
|
|
(GtkWidget *widget,
|
|
|
|
GimpItemTreeView *view);
|
2025-05-28 22:15:41 +02:00
|
|
|
static void gimp_item_tree_view_effects_raise_clicked
|
2023-06-19 14:54:21 +00:00
|
|
|
(GtkWidget *widget,
|
|
|
|
GimpItemTreeView *view);
|
2025-05-28 22:15:41 +02:00
|
|
|
static void gimp_item_tree_view_effects_lower_clicked
|
2023-06-19 14:54:21 +00:00
|
|
|
(GtkWidget *widget,
|
|
|
|
GimpItemTreeView *view);
|
2025-05-28 22:15:41 +02:00
|
|
|
static void gimp_item_tree_view_effects_merge_clicked
|
2023-06-19 14:54:21 +00:00
|
|
|
(GtkWidget *widget,
|
|
|
|
GimpItemTreeView *view);
|
2025-05-28 22:15:41 +02:00
|
|
|
static void gimp_item_tree_view_effects_remove_clicked
|
2023-06-19 14:54:21 +00:00
|
|
|
(GtkWidget *widget,
|
|
|
|
GimpItemTreeView *view);
|
2021-02-11 16:17:36 +01:00
|
|
|
static gboolean gimp_item_tree_view_lock_button_release (GtkWidget *widget,
|
2023-06-19 14:54:21 +00:00
|
|
|
GdkEvent *event,
|
|
|
|
GimpItemTreeView *view);
|
2021-02-09 02:39:37 +01:00
|
|
|
static void gimp_item_tree_view_lock_toggled (GtkWidget *widget,
|
|
|
|
GimpItemTreeView *view);
|
2021-02-09 00:04:05 +01:00
|
|
|
static void gimp_item_tree_view_update_lock_box (GimpItemTreeView *view,
|
2021-02-11 10:33:57 +01:00
|
|
|
GimpItem *item,
|
|
|
|
GtkTreePath *path);
|
2021-02-10 19:03:28 +01:00
|
|
|
static gboolean gimp_item_tree_view_popover_button_press (GtkWidget *widget,
|
|
|
|
GdkEvent *event,
|
|
|
|
GimpItemTreeView *view);
|
2003-05-08 20:26:01 +00:00
|
|
|
|
2010-07-20 23:36:16 +02:00
|
|
|
static gboolean gimp_item_tree_view_item_pre_clicked(GimpCellRendererViewable *cell,
|
|
|
|
const gchar *path_str,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpItemTreeView *item_view);
|
|
|
|
|
2009-09-13 22:39:01 +02:00
|
|
|
static void gimp_item_tree_view_row_expanded (GtkTreeView *tree_view,
|
|
|
|
GtkTreeIter *iter,
|
|
|
|
GtkTreePath *path,
|
|
|
|
GimpItemTreeView *item_view);
|
|
|
|
|
2021-02-09 02:39:37 +01:00
|
|
|
static gint gimp_item_tree_view_get_n_locks (GimpItemTreeView *view,
|
|
|
|
GimpItem *item,
|
|
|
|
const gchar **icon_name);
|
|
|
|
|
2024-02-08 14:03:55 +00:00
|
|
|
static void gimp_item_tree_effects_set_sensitive (GimpItemTreeView *view,
|
|
|
|
gboolean is_sensitive);
|
|
|
|
|
2024-02-06 21:05:43 +01:00
|
|
|
/* 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);
|
|
|
|
|
2024-08-14 23:34:27 +02:00
|
|
|
static gboolean gimp_item_tree_view_move_cursor (GimpItemTreeView *tree_view,
|
|
|
|
guint keyval,
|
|
|
|
GdkModifierType modifiers);
|
|
|
|
|
2021-02-09 02:39:37 +01:00
|
|
|
|
2005-12-19 22:37:49 +00:00
|
|
|
G_DEFINE_TYPE_WITH_CODE (GimpItemTreeView, gimp_item_tree_view,
|
|
|
|
GIMP_TYPE_CONTAINER_TREE_VIEW,
|
app, libgimp*, modules: don't use g_type_class_add_private() ...
... and G_TYPE_INSTANCE_GET_PRIVATE()
g_type_class_add_private() and G_TYPE_INSTANCE_GET_PRIVATE() were
deprecated in GLib 2.58. Instead, use
G_DEFINE_[ABSTRACT_]TYPE_WITH_PRIVATE(), and
G_ADD_PRIVATE[_DYNAMIC](), and the implictly-defined
foo_get_instance_private() functions, all of which are available in
the GLib versions we depend on.
This commit only covers types registered using one of the
G_DEFINE_FOO() macros (i.e., most types), but not types with a
custom registration function, of which we still have a few -- GLib
currently only provides a (non-deprecated) public API for adding a
private struct using the G_DEFINE_FOO() macros.
Note that this commit was 99% auto-generated (because I'm not
*that* crazy :), so if there are any style mismatches... we'll have
to live with them for now.
2018-09-18 12:09:39 -04:00
|
|
|
G_ADD_PRIVATE (GimpItemTreeView)
|
2005-12-19 22:37:49 +00:00
|
|
|
G_IMPLEMENT_INTERFACE (GIMP_TYPE_CONTAINER_VIEW,
|
|
|
|
gimp_item_tree_view_view_iface_init)
|
|
|
|
G_IMPLEMENT_INTERFACE (GIMP_TYPE_DOCKED,
|
2006-05-15 09:46:31 +00:00
|
|
|
gimp_item_tree_view_docked_iface_init))
|
2005-12-19 22:37:49 +00:00
|
|
|
|
|
|
|
#define parent_class gimp_item_tree_view_parent_class
|
2001-05-03 12:26:05 +00:00
|
|
|
|
2004-05-10 23:22:39 +00:00
|
|
|
static GimpContainerViewInterface *parent_view_iface = NULL;
|
2001-02-27 14:14:13 +00:00
|
|
|
|
2005-12-19 22:37:49 +00:00
|
|
|
static guint view_signals[LAST_SIGNAL] = { 0 };
|
2001-02-27 14:14:13 +00:00
|
|
|
|
|
|
|
|
|
|
|
static void
|
2003-03-16 11:14:29 +00:00
|
|
|
gimp_item_tree_view_class_init (GimpItemTreeViewClass *klass)
|
2001-02-27 14:14:13 +00:00
|
|
|
{
|
2010-10-15 14:08:36 +02:00
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
|
2003-03-19 15:17:13 +00:00
|
|
|
GimpContainerTreeViewClass *tree_view_class;
|
2001-02-27 14:14:13 +00:00
|
|
|
|
2009-08-19 10:44:38 +02:00
|
|
|
tree_view_class = GIMP_CONTAINER_TREE_VIEW_CLASS (klass);
|
2001-02-27 14:14:13 +00:00
|
|
|
|
2001-05-03 12:26:05 +00:00
|
|
|
view_signals[SET_IMAGE] =
|
2005-05-27 13:05:26 +00:00
|
|
|
g_signal_new ("set-image",
|
2006-04-12 12:49:29 +00:00
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
G_STRUCT_OFFSET (GimpItemTreeViewClass, set_image),
|
2020-01-12 11:06:05 +01:00
|
|
|
NULL, NULL, NULL,
|
2006-04-12 12:49:29 +00:00
|
|
|
G_TYPE_NONE, 1,
|
|
|
|
GIMP_TYPE_OBJECT);
|
2001-05-03 12:26:05 +00:00
|
|
|
|
2011-01-14 09:38:11 +01:00
|
|
|
object_class->constructed = gimp_item_tree_view_constructed;
|
2010-10-15 14:08:36 +02:00
|
|
|
object_class->dispose = gimp_item_tree_view_dispose;
|
2004-05-10 23:22:39 +00:00
|
|
|
|
2011-01-09 20:38:01 +01:00
|
|
|
widget_class->style_updated = gimp_item_tree_view_style_updated;
|
2009-08-19 10:44:38 +02:00
|
|
|
|
2020-03-24 22:06:28 +01:00
|
|
|
tree_view_class->drop_possible = gimp_item_tree_view_drop_possible;
|
|
|
|
tree_view_class->drop_viewables = gimp_item_tree_view_drop_viewables;
|
2004-05-10 23:22:39 +00:00
|
|
|
|
|
|
|
klass->set_image = gimp_item_tree_view_real_set_image;
|
|
|
|
|
2004-10-16 20:17:30 +00:00
|
|
|
klass->item_type = G_TYPE_NONE;
|
|
|
|
klass->signal_name = NULL;
|
|
|
|
|
2004-05-10 23:22:39 +00:00
|
|
|
klass->get_container = NULL;
|
2020-03-26 00:33:11 +01:00
|
|
|
klass->get_selected_items = NULL;
|
2020-03-21 19:03:07 +01:00
|
|
|
klass->set_selected_items = NULL;
|
2004-05-10 23:22:39 +00:00
|
|
|
klass->add_item = NULL;
|
|
|
|
klass->remove_item = NULL;
|
2004-10-16 15:48:23 +00:00
|
|
|
klass->new_item = NULL;
|
|
|
|
|
|
|
|
klass->action_group = NULL;
|
|
|
|
klass->new_action = NULL;
|
|
|
|
klass->new_default_action = NULL;
|
|
|
|
klass->raise_action = NULL;
|
|
|
|
klass->raise_top_action = NULL;
|
|
|
|
klass->lower_action = NULL;
|
|
|
|
klass->lower_bottom_action = NULL;
|
|
|
|
klass->duplicate_action = NULL;
|
|
|
|
klass->delete_action = NULL;
|
2009-08-20 12:50:40 +02:00
|
|
|
|
2014-05-07 15:30:38 +02:00
|
|
|
klass->lock_content_icon_name = NULL;
|
2009-08-20 12:50:40 +02:00
|
|
|
klass->lock_content_tooltip = NULL;
|
|
|
|
klass->lock_content_help_id = NULL;
|
|
|
|
|
2014-05-07 15:30:38 +02:00
|
|
|
klass->lock_position_icon_name = NULL;
|
2012-11-09 11:17:25 +01:00
|
|
|
klass->lock_position_tooltip = NULL;
|
|
|
|
klass->lock_position_help_id = NULL;
|
2017-12-23 23:57:12 +01:00
|
|
|
|
|
|
|
klass->lock_visibility_icon_name = NULL;
|
|
|
|
klass->lock_visibility_tooltip = NULL;
|
|
|
|
klass->lock_visibility_help_id = NULL;
|
2024-08-14 23:34:27 +02:00
|
|
|
|
|
|
|
klass->move_cursor_up_action = NULL;
|
|
|
|
klass->move_cursor_down_action = NULL;
|
|
|
|
klass->move_cursor_up_flat_action = NULL;
|
|
|
|
klass->move_cursor_down_flat_action = NULL;
|
|
|
|
klass->move_cursor_start_action = NULL;
|
|
|
|
klass->move_cursor_end_action = NULL;
|
2001-02-27 14:14:13 +00:00
|
|
|
}
|
|
|
|
|
2006-08-29 21:44:51 +00:00
|
|
|
static void
|
|
|
|
gimp_item_tree_view_view_iface_init (GimpContainerViewInterface *iface)
|
|
|
|
{
|
|
|
|
parent_view_iface = g_type_interface_peek_parent (iface);
|
|
|
|
|
2020-03-31 16:10:29 +02:00
|
|
|
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;
|
2006-08-29 21:44:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_item_tree_view_docked_iface_init (GimpDockedInterface *iface)
|
|
|
|
{
|
|
|
|
iface->get_preview = NULL;
|
|
|
|
}
|
|
|
|
|
2001-02-27 14:14:13 +00:00
|
|
|
static void
|
2005-12-19 22:37:49 +00:00
|
|
|
gimp_item_tree_view_init (GimpItemTreeView *view)
|
2001-02-27 14:14:13 +00:00
|
|
|
{
|
2004-05-11 10:01:25 +00:00
|
|
|
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
|
2001-08-04 20:38:54 +00:00
|
|
|
|
app, libgimp*, modules: don't use g_type_class_add_private() ...
... and G_TYPE_INSTANCE_GET_PRIVATE()
g_type_class_add_private() and G_TYPE_INSTANCE_GET_PRIVATE() were
deprecated in GLib 2.58. Instead, use
G_DEFINE_[ABSTRACT_]TYPE_WITH_PRIVATE(), and
G_ADD_PRIVATE[_DYNAMIC](), and the implictly-defined
foo_get_instance_private() functions, all of which are available in
the GLib versions we depend on.
This commit only covers types registered using one of the
G_DEFINE_FOO() macros (i.e., most types), but not types with a
custom registration function, of which we still have a few -- GLib
currently only provides a (non-deprecated) public API for adding a
private struct using the G_DEFINE_FOO() macros.
Note that this commit was 99% auto-generated (because I'm not
*that* crazy :), so if there are any style mismatches... we'll have
to live with them for now.
2018-09-18 12:09:39 -04:00
|
|
|
view->priv = gimp_item_tree_view_get_instance_private (view);
|
2008-12-25 11:31:51 +00:00
|
|
|
|
2010-05-17 21:22:36 +02:00
|
|
|
view->priv->model_column_visible =
|
|
|
|
gimp_container_tree_store_columns_add (tree_view->model_columns,
|
|
|
|
&tree_view->n_model_columns,
|
|
|
|
G_TYPE_BOOLEAN);
|
|
|
|
|
2011-09-23 23:45:10 +02:00
|
|
|
view->priv->model_column_viewable =
|
|
|
|
gimp_container_tree_store_columns_add (tree_view->model_columns,
|
|
|
|
&tree_view->n_model_columns,
|
|
|
|
G_TYPE_BOOLEAN);
|
|
|
|
|
2021-02-09 00:04:05 +01:00
|
|
|
view->priv->model_column_locked =
|
2010-05-17 21:22:36 +02:00
|
|
|
gimp_container_tree_store_columns_add (tree_view->model_columns,
|
|
|
|
&tree_view->n_model_columns,
|
|
|
|
G_TYPE_BOOLEAN);
|
2001-02-27 14:14:13 +00:00
|
|
|
|
2021-02-09 00:04:05 +01:00
|
|
|
view->priv->model_column_lock_icon =
|
|
|
|
gimp_container_tree_store_columns_add (tree_view->model_columns,
|
|
|
|
&tree_view->n_model_columns,
|
|
|
|
G_TYPE_STRING);
|
|
|
|
|
2016-10-29 16:50:13 +02:00
|
|
|
view->priv->model_column_color_tag =
|
|
|
|
gimp_container_tree_store_columns_add (tree_view->model_columns,
|
|
|
|
&tree_view->n_model_columns,
|
2016-11-01 12:50:10 +01:00
|
|
|
GDK_TYPE_RGBA);
|
2016-10-29 16:50:13 +02:00
|
|
|
|
2023-06-19 14:54:21 +00:00
|
|
|
view->priv->model_column_effects =
|
|
|
|
gimp_container_tree_store_columns_add (tree_view->model_columns,
|
|
|
|
&tree_view->n_model_columns,
|
|
|
|
G_TYPE_BOOLEAN);
|
|
|
|
|
2008-11-16 19:48:54 +00:00
|
|
|
gimp_container_tree_view_set_dnd_drop_to_empty (tree_view, TRUE);
|
2005-01-17 15:28:08 +00:00
|
|
|
|
2023-06-19 14:54:21 +00:00
|
|
|
view->priv->image = NULL;
|
|
|
|
view->priv->effects_drawable = NULL;
|
|
|
|
view->priv->effects_filter = NULL;
|
2024-02-06 21:05:43 +01:00
|
|
|
|
|
|
|
view->priv->link_pattern_set = NULL;
|
2001-02-27 14:14:13 +00:00
|
|
|
}
|
|
|
|
|
2011-01-14 09:38:11 +01:00
|
|
|
static void
|
|
|
|
gimp_item_tree_view_constructed (GObject *object)
|
2003-03-16 11:14:29 +00:00
|
|
|
{
|
2011-01-14 09:38:11 +01:00
|
|
|
GimpItemTreeViewClass *item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (object);
|
|
|
|
GimpEditor *editor = GIMP_EDITOR (object);
|
|
|
|
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (object);
|
|
|
|
GimpItemTreeView *item_view = GIMP_ITEM_TREE_VIEW (object);
|
2004-05-10 23:22:39 +00:00
|
|
|
GtkTreeViewColumn *column;
|
2021-12-23 18:40:17 +01:00
|
|
|
GtkWidget *image;
|
2023-06-19 14:54:21 +00:00
|
|
|
GtkWidget *label;
|
2024-02-06 21:05:43 +01:00
|
|
|
GtkWidget *items_header;
|
2023-06-19 14:54:21 +00:00
|
|
|
gchar *text;
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
GtkIconSize button_icon_size = GTK_ICON_SIZE_SMALL_TOOLBAR;
|
|
|
|
gint pixel_icon_size = 16;
|
2021-02-09 02:39:37 +01:00
|
|
|
gint button_spacing;
|
2003-03-16 11:14:29 +00:00
|
|
|
|
2012-11-12 21:51:22 +01:00
|
|
|
G_OBJECT_CLASS (parent_class)->constructed (object);
|
2003-03-16 11:14:29 +00:00
|
|
|
|
2024-08-14 23:34:27 +02:00
|
|
|
g_signal_connect (tree_view->view, "key-press-event",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_key_press_event),
|
|
|
|
tree_view);
|
|
|
|
|
2021-02-25 18:40:42 +01:00
|
|
|
gtk_tree_view_set_headers_visible (tree_view->view, TRUE);
|
|
|
|
|
|
|
|
gtk_widget_style_get (GTK_WIDGET (item_view),
|
|
|
|
"button-icon-size", &button_icon_size,
|
|
|
|
"button-spacing", &button_spacing,
|
|
|
|
NULL);
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
gtk_icon_size_lookup (button_icon_size, &pixel_icon_size, NULL);
|
2021-02-25 18:40:42 +01:00
|
|
|
|
2008-06-28 16:05:05 +00:00
|
|
|
gimp_container_tree_view_connect_name_edited (tree_view,
|
|
|
|
G_CALLBACK (gimp_item_tree_view_name_edited),
|
|
|
|
item_view);
|
2003-03-16 11:14:29 +00:00
|
|
|
|
2009-09-13 22:39:01 +02:00
|
|
|
g_signal_connect (tree_view->view, "row-expanded",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_row_expanded),
|
|
|
|
tree_view);
|
|
|
|
|
2010-07-20 23:36:16 +02:00
|
|
|
g_signal_connect (tree_view->renderer_cell, "pre-clicked",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_item_pre_clicked),
|
|
|
|
item_view);
|
|
|
|
|
2003-05-08 20:26:01 +00:00
|
|
|
column = gtk_tree_view_column_new ();
|
2021-12-23 18:40:17 +01:00
|
|
|
image = gtk_image_new_from_icon_name (GIMP_ICON_VISIBLE, button_icon_size);
|
|
|
|
gtk_tree_view_column_set_widget (column, image);
|
|
|
|
gtk_widget_show (image);
|
2003-05-08 20:26:01 +00:00
|
|
|
gtk_tree_view_insert_column (tree_view->view, column, 0);
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
item_view->priv->eye_header_image = image;
|
2003-05-08 20:26:01 +00:00
|
|
|
|
2017-03-05 16:01:59 +01:00
|
|
|
item_view->priv->eye_cell = gimp_cell_renderer_toggle_new (GIMP_ICON_VISIBLE);
|
2009-08-28 11:11:19 +02:00
|
|
|
g_object_set (item_view->priv->eye_cell,
|
2016-10-29 16:50:13 +02:00
|
|
|
"xpad", 0,
|
|
|
|
"ypad", 0,
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
"icon-size", pixel_icon_size,
|
2016-10-29 16:50:13 +02:00
|
|
|
"override-background", TRUE,
|
2009-08-28 11:11:19 +02:00
|
|
|
NULL);
|
2008-12-25 11:31:51 +00:00
|
|
|
gtk_tree_view_column_pack_start (column, item_view->priv->eye_cell, FALSE);
|
|
|
|
gtk_tree_view_column_set_attributes (column, item_view->priv->eye_cell,
|
2003-09-11 19:52:29 +00:00
|
|
|
"active",
|
2008-12-25 11:31:51 +00:00
|
|
|
item_view->priv->model_column_visible,
|
2011-09-23 23:45:10 +02:00
|
|
|
"inconsistent",
|
|
|
|
item_view->priv->model_column_viewable,
|
2016-11-01 12:50:10 +01:00
|
|
|
"cell-background-rgba",
|
2016-10-29 16:50:13 +02:00
|
|
|
item_view->priv->model_column_color_tag,
|
2003-09-11 19:52:29 +00:00
|
|
|
NULL);
|
|
|
|
|
2009-08-28 10:59:27 +02:00
|
|
|
gimp_container_tree_view_add_toggle_cell (tree_view,
|
|
|
|
item_view->priv->eye_cell);
|
2003-09-11 19:52:29 +00:00
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
g_signal_connect (item_view->priv->eye_cell, "clicked",
|
2003-09-15 14:39:48 +00:00
|
|
|
G_CALLBACK (gimp_item_tree_view_eye_clicked),
|
2003-09-11 19:52:29 +00:00
|
|
|
item_view);
|
|
|
|
|
|
|
|
column = gtk_tree_view_column_new ();
|
2021-12-23 18:40:17 +01:00
|
|
|
image = gtk_image_new_from_icon_name (GIMP_ICON_LOCK, button_icon_size);
|
|
|
|
gtk_tree_view_column_set_widget (column, image);
|
|
|
|
gtk_widget_show (image);
|
2003-09-15 14:39:48 +00:00
|
|
|
gtk_tree_view_insert_column (tree_view->view, column, 1);
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
item_view->priv->lock_header_image = image;
|
2003-09-11 19:52:29 +00:00
|
|
|
|
2021-03-09 11:08:00 +01:00
|
|
|
item_view->priv->lock_cell = gimp_cell_renderer_toggle_new (GIMP_ICON_LOCK_MULTI);
|
2021-02-09 00:04:05 +01:00
|
|
|
g_object_set (item_view->priv->lock_cell,
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
"xpad", 0,
|
|
|
|
"ypad", 0,
|
|
|
|
"icon-size", pixel_icon_size,
|
2009-08-28 11:11:19 +02:00
|
|
|
NULL);
|
2021-02-09 00:04:05 +01:00
|
|
|
gtk_tree_view_column_pack_start (column, item_view->priv->lock_cell, FALSE);
|
|
|
|
gtk_tree_view_column_set_attributes (column, item_view->priv->lock_cell,
|
2003-05-08 20:26:01 +00:00
|
|
|
"active",
|
2021-02-09 00:04:05 +01:00
|
|
|
item_view->priv->model_column_locked,
|
|
|
|
"icon-name",
|
|
|
|
item_view->priv->model_column_lock_icon,
|
2003-05-08 20:26:01 +00:00
|
|
|
NULL);
|
|
|
|
|
2009-08-28 10:59:27 +02:00
|
|
|
gimp_container_tree_view_add_toggle_cell (tree_view,
|
2021-02-09 00:04:05 +01:00
|
|
|
item_view->priv->lock_cell);
|
2003-05-08 20:26:01 +00:00
|
|
|
|
2021-02-09 00:04:05 +01:00
|
|
|
g_signal_connect (item_view->priv->lock_cell, "clicked",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_lock_clicked),
|
2003-05-08 20:26:01 +00:00
|
|
|
item_view);
|
|
|
|
|
2023-06-19 14:54:21 +00:00
|
|
|
/* TODO: Expand layer effects to other drawable types */
|
|
|
|
if (GIMP_IS_LAYER_TREE_VIEW (object))
|
|
|
|
{
|
|
|
|
column = gtk_tree_view_column_new ();
|
2024-01-30 04:06:39 +00:00
|
|
|
image = gtk_image_new_from_icon_name (GIMP_ICON_EFFECT, button_icon_size);
|
2024-02-14 16:50:26 +01:00
|
|
|
gimp_widget_set_identifier (image, "item-effect-header-icon");
|
2024-01-30 04:06:39 +00:00
|
|
|
gtk_tree_view_column_set_widget (column, image);
|
|
|
|
gtk_widget_set_visible (image, TRUE);
|
2023-06-19 14:54:21 +00:00
|
|
|
gtk_tree_view_insert_column (tree_view->view, column, 2);
|
2024-01-30 04:06:39 +00:00
|
|
|
item_view->priv->effect_header_image = image;
|
2023-06-19 14:54:21 +00:00
|
|
|
|
2024-01-30 04:06:39 +00:00
|
|
|
item_view->priv->effects_cell = gimp_cell_renderer_toggle_new (GIMP_ICON_EFFECT);
|
2023-06-19 14:54:21 +00:00
|
|
|
g_object_set (item_view->priv->effects_cell,
|
|
|
|
"xpad", 0,
|
|
|
|
"ypad", 0,
|
|
|
|
"icon-size", pixel_icon_size,
|
|
|
|
NULL);
|
|
|
|
gtk_tree_view_column_pack_start (column, item_view->priv->effects_cell, FALSE);
|
|
|
|
gtk_tree_view_column_set_attributes (column, item_view->priv->effects_cell,
|
|
|
|
"active",
|
|
|
|
item_view->priv->model_column_effects,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
gimp_container_tree_view_add_toggle_cell (tree_view,
|
|
|
|
item_view->priv->effects_cell);
|
|
|
|
|
|
|
|
g_signal_connect (item_view->priv->effects_cell, "clicked",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_effects_clicked),
|
|
|
|
item_view);
|
|
|
|
}
|
|
|
|
|
2003-12-21 16:15:34 +00:00
|
|
|
/* disable the default GimpContainerView drop handler */
|
2004-05-10 23:22:39 +00:00
|
|
|
gimp_container_view_set_dnd_widget (GIMP_CONTAINER_VIEW (item_view), NULL);
|
2003-12-21 16:15:34 +00:00
|
|
|
|
2003-12-21 12:11:44 +00:00
|
|
|
gimp_dnd_drag_dest_set_by_type (GTK_WIDGET (tree_view->view),
|
2004-06-28 22:07:12 +00:00
|
|
|
GTK_DEST_DEFAULT_HIGHLIGHT,
|
2004-10-16 20:17:30 +00:00
|
|
|
item_view_class->item_type,
|
2020-03-24 22:06:28 +01:00
|
|
|
TRUE,
|
2003-12-21 12:11:44 +00:00
|
|
|
GDK_ACTION_MOVE | GDK_ACTION_COPY);
|
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
item_view->priv->new_button =
|
2004-10-16 15:48:23 +00:00
|
|
|
gimp_editor_add_action_button (editor, item_view_class->action_group,
|
2004-10-16 17:10:04 +00:00
|
|
|
item_view_class->new_action,
|
2004-10-23 00:53:48 +00:00
|
|
|
item_view_class->new_default_action,
|
2004-10-16 17:10:04 +00:00
|
|
|
GDK_SHIFT_MASK,
|
2004-10-16 15:48:23 +00:00
|
|
|
NULL);
|
2003-12-21 12:11:44 +00:00
|
|
|
/* connect "drop to new" manually as it makes a difference whether
|
|
|
|
* it was clicked or dropped
|
|
|
|
*/
|
2020-03-24 22:06:28 +01:00
|
|
|
gimp_dnd_viewable_list_dest_add (item_view->priv->new_button,
|
|
|
|
item_view_class->item_type,
|
|
|
|
gimp_item_tree_view_new_list_dropped,
|
|
|
|
item_view);
|
2008-12-25 11:31:51 +00:00
|
|
|
gimp_dnd_viewable_dest_add (item_view->priv->new_button,
|
2006-04-12 12:49:29 +00:00
|
|
|
item_view_class->item_type,
|
|
|
|
gimp_item_tree_view_new_dropped,
|
|
|
|
item_view);
|
2003-12-21 12:11:44 +00:00
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
item_view->priv->raise_button =
|
2004-10-16 15:48:23 +00:00
|
|
|
gimp_editor_add_action_button (editor, item_view_class->action_group,
|
|
|
|
item_view_class->raise_action,
|
|
|
|
item_view_class->raise_top_action,
|
|
|
|
GDK_SHIFT_MASK,
|
|
|
|
NULL);
|
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
item_view->priv->lower_button =
|
2004-10-16 15:48:23 +00:00
|
|
|
gimp_editor_add_action_button (editor, item_view_class->action_group,
|
|
|
|
item_view_class->lower_action,
|
|
|
|
item_view_class->lower_bottom_action,
|
|
|
|
GDK_SHIFT_MASK,
|
|
|
|
NULL);
|
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
item_view->priv->duplicate_button =
|
2004-10-16 15:48:23 +00:00
|
|
|
gimp_editor_add_action_button (editor, item_view_class->action_group,
|
|
|
|
item_view_class->duplicate_action, NULL);
|
2003-12-21 12:11:44 +00:00
|
|
|
gimp_container_view_enable_dnd (GIMP_CONTAINER_VIEW (item_view),
|
2008-12-25 11:31:51 +00:00
|
|
|
GTK_BUTTON (item_view->priv->duplicate_button),
|
2006-04-12 12:49:29 +00:00
|
|
|
item_view_class->item_type);
|
2004-10-16 15:48:23 +00:00
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
item_view->priv->delete_button =
|
2004-10-16 15:48:23 +00:00
|
|
|
gimp_editor_add_action_button (editor, item_view_class->action_group,
|
|
|
|
item_view_class->delete_action, NULL);
|
2003-12-21 12:11:44 +00:00
|
|
|
gimp_container_view_enable_dnd (GIMP_CONTAINER_VIEW (item_view),
|
2008-12-25 11:31:51 +00:00
|
|
|
GTK_BUTTON (item_view->priv->delete_button),
|
2006-04-12 12:49:29 +00:00
|
|
|
item_view_class->item_type);
|
2003-12-21 12:11:44 +00:00
|
|
|
|
2021-02-09 02:39:37 +01:00
|
|
|
/* Lock box. */
|
|
|
|
item_view->priv->lock_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, button_spacing);
|
2020-04-20 17:48:58 +02:00
|
|
|
|
2021-02-09 02:39:37 +01:00
|
|
|
/* Lock box: content toggle */
|
2021-02-09 13:12:35 +01:00
|
|
|
gimp_item_tree_view_add_lock (item_view,
|
|
|
|
item_view_class->lock_content_icon_name,
|
|
|
|
(GimpIsLockedFunc) gimp_item_get_lock_content,
|
2021-02-11 16:17:36 +01:00
|
|
|
(GimpCanLockFunc) gimp_item_can_lock_content,
|
|
|
|
(GimpSetLockFunc) gimp_item_set_lock_content,
|
|
|
|
(GimpUndoLockPush) gimp_image_undo_push_item_lock_content,
|
2021-02-09 13:12:35 +01:00
|
|
|
"lock-content-changed",
|
|
|
|
GIMP_UNDO_ITEM_LOCK_CONTENT,
|
|
|
|
GIMP_UNDO_GROUP_ITEM_LOCK_CONTENTS,
|
|
|
|
_("Lock content"),
|
|
|
|
_("Unlock content"),
|
2021-02-11 16:17:36 +01:00
|
|
|
_("Set Item Exclusive Content Lock"),
|
2021-02-09 13:12:35 +01:00
|
|
|
item_view_class->lock_content_tooltip,
|
|
|
|
item_view_class->lock_content_help_id);
|
2012-11-09 11:17:25 +01:00
|
|
|
|
2021-02-09 02:39:37 +01:00
|
|
|
/* Lock box: position toggle */
|
2021-02-09 13:12:35 +01:00
|
|
|
gimp_item_tree_view_add_lock (item_view,
|
|
|
|
item_view_class->lock_position_icon_name,
|
|
|
|
(GimpIsLockedFunc) gimp_item_get_lock_position,
|
2021-02-11 16:17:36 +01:00
|
|
|
(GimpCanLockFunc) gimp_item_can_lock_position,
|
|
|
|
(GimpSetLockFunc) gimp_item_set_lock_position,
|
|
|
|
(GimpUndoLockPush) gimp_image_undo_push_item_lock_position,
|
2021-02-09 13:12:35 +01:00
|
|
|
"lock-position-changed",
|
|
|
|
GIMP_UNDO_ITEM_LOCK_POSITION,
|
|
|
|
GIMP_UNDO_GROUP_ITEM_LOCK_POSITION,
|
|
|
|
_("Lock position"),
|
|
|
|
_("Unlock position"),
|
2021-02-11 16:17:36 +01:00
|
|
|
_("Set Item Exclusive Position Lock"),
|
2021-02-09 13:12:35 +01:00
|
|
|
item_view_class->lock_position_tooltip,
|
|
|
|
item_view_class->lock_position_help_id);
|
2017-12-23 23:57:12 +01:00
|
|
|
|
2021-02-09 02:39:37 +01:00
|
|
|
/* Lock box: visibility toggle */
|
2021-02-09 13:12:35 +01:00
|
|
|
gimp_item_tree_view_add_lock (item_view,
|
|
|
|
item_view_class->lock_visibility_icon_name,
|
|
|
|
(GimpIsLockedFunc) gimp_item_get_lock_visibility,
|
2021-02-11 16:17:36 +01:00
|
|
|
(GimpCanLockFunc) gimp_item_can_lock_visibility,
|
|
|
|
(GimpSetLockFunc) gimp_item_set_lock_visibility,
|
|
|
|
(GimpUndoLockPush) gimp_image_undo_push_item_lock_visibility,
|
2021-02-09 13:12:35 +01:00
|
|
|
"lock-visibility-changed",
|
|
|
|
GIMP_UNDO_ITEM_LOCK_VISIBILITY,
|
|
|
|
GIMP_UNDO_GROUP_ITEM_LOCK_VISIBILITY,
|
|
|
|
_("Lock visibility"),
|
|
|
|
_("Unlock visibility"),
|
2021-02-11 16:17:36 +01:00
|
|
|
_("Set Item Exclusive Visibility Lock"),
|
2021-02-09 13:12:35 +01:00
|
|
|
item_view_class->lock_visibility_tooltip,
|
|
|
|
item_view_class->lock_visibility_help_id);
|
2021-02-09 00:04:05 +01:00
|
|
|
|
|
|
|
/* Lock popover. */
|
|
|
|
item_view->priv->lock_popover = gtk_popover_new (GTK_WIDGET (tree_view->view));
|
|
|
|
gtk_popover_set_modal (GTK_POPOVER (item_view->priv->lock_popover), TRUE);
|
2021-02-10 19:03:28 +01:00
|
|
|
g_signal_connect (item_view->priv->lock_popover,
|
|
|
|
"button-press-event",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_popover_button_press),
|
|
|
|
item_view);
|
2021-02-09 02:39:37 +01:00
|
|
|
gtk_container_add (GTK_CONTAINER (item_view->priv->lock_popover), item_view->priv->lock_box);
|
|
|
|
gtk_widget_show (item_view->priv->lock_box);
|
2023-06-19 14:54:21 +00:00
|
|
|
|
|
|
|
/* Effects box. */
|
|
|
|
if (GIMP_IS_LAYER_TREE_VIEW (object))
|
|
|
|
{
|
|
|
|
item_view->priv->effects_filters = gtk_box_new (GTK_ORIENTATION_VERTICAL, button_spacing);
|
|
|
|
item_view->priv->effects_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, button_spacing);
|
|
|
|
item_view->priv->effects_options = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, button_spacing);
|
|
|
|
|
|
|
|
/* Effects Buttons */
|
|
|
|
item_view->priv->effects_visible_button = gtk_toggle_button_new ();
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (item_view->priv->effects_visible_button),
|
|
|
|
TRUE);
|
|
|
|
image = gtk_image_new_from_icon_name (GIMP_ICON_VISIBLE,
|
|
|
|
GTK_ICON_SIZE_SMALL_TOOLBAR);
|
|
|
|
gtk_container_add (GTK_CONTAINER (item_view->priv->effects_visible_button), image);
|
|
|
|
gimp_help_set_help_data (item_view->priv->effects_visible_button,
|
|
|
|
_("Toggle the visibility of all filters."),
|
2024-06-19 13:42:41 -04:00
|
|
|
GIMP_HELP_LAYER_EFFECTS);
|
2023-06-19 14:54:21 +00:00
|
|
|
g_signal_connect (item_view->priv->effects_visible_button, "toggled",
|
2024-01-03 18:57:08 +00:00
|
|
|
G_CALLBACK (gimp_item_tree_view_effects_visible_all_toggled),
|
2023-06-19 14:54:21 +00:00
|
|
|
item_view);
|
|
|
|
gtk_box_pack_start (GTK_BOX (item_view->priv->effects_options),
|
|
|
|
item_view->priv->effects_visible_button, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_set_visible (image, TRUE);
|
|
|
|
gtk_widget_set_visible (item_view->priv->effects_visible_button, TRUE);
|
|
|
|
|
|
|
|
item_view->priv->effects_edit_button =
|
|
|
|
gtk_button_new_from_icon_name (GIMP_ICON_EDIT,
|
|
|
|
GTK_ICON_SIZE_SMALL_TOOLBAR);
|
|
|
|
gimp_help_set_help_data (item_view->priv->effects_edit_button,
|
|
|
|
_("Edit the selected filter."),
|
2024-06-19 13:42:41 -04:00
|
|
|
GIMP_HELP_LAYER_EFFECTS);
|
2023-06-19 14:54:21 +00:00
|
|
|
g_signal_connect (item_view->priv->effects_edit_button, "clicked",
|
2025-05-28 22:15:41 +02:00
|
|
|
G_CALLBACK (gimp_item_tree_view_effects_edit_clicked),
|
2023-06-19 14:54:21 +00:00
|
|
|
item_view);
|
|
|
|
gtk_box_pack_start (GTK_BOX (item_view->priv->effects_options),
|
|
|
|
item_view->priv->effects_edit_button, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_set_visible (item_view->priv->effects_edit_button, TRUE);
|
|
|
|
|
|
|
|
item_view->priv->effects_raise_button =
|
|
|
|
gtk_button_new_from_icon_name (GIMP_ICON_GO_UP,
|
|
|
|
GTK_ICON_SIZE_SMALL_TOOLBAR);
|
|
|
|
gimp_help_set_help_data (item_view->priv->effects_raise_button,
|
|
|
|
_("Raise filter one step up in the stack."),
|
2024-06-19 13:42:41 -04:00
|
|
|
GIMP_HELP_LAYER_EFFECTS);
|
2023-06-19 14:54:21 +00:00
|
|
|
g_signal_connect (item_view->priv->effects_raise_button, "clicked",
|
2025-05-28 22:15:41 +02:00
|
|
|
G_CALLBACK (gimp_item_tree_view_effects_raise_clicked),
|
2023-06-19 14:54:21 +00:00
|
|
|
item_view);
|
|
|
|
gtk_box_pack_start (GTK_BOX (item_view->priv->effects_options),
|
|
|
|
item_view->priv->effects_raise_button, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_set_visible (item_view->priv->effects_raise_button, TRUE);
|
|
|
|
|
|
|
|
item_view->priv->effects_lower_button =
|
|
|
|
gtk_button_new_from_icon_name (GIMP_ICON_GO_DOWN,
|
|
|
|
GTK_ICON_SIZE_SMALL_TOOLBAR);
|
|
|
|
gimp_help_set_help_data (item_view->priv->effects_lower_button,
|
|
|
|
_("Lower filter one step down in the stack."),
|
2024-06-19 13:42:41 -04:00
|
|
|
GIMP_HELP_LAYER_EFFECTS);
|
2023-06-19 14:54:21 +00:00
|
|
|
g_signal_connect (item_view->priv->effects_lower_button, "clicked",
|
2025-05-28 22:15:41 +02:00
|
|
|
G_CALLBACK (gimp_item_tree_view_effects_lower_clicked),
|
2023-06-19 14:54:21 +00:00
|
|
|
item_view);
|
|
|
|
gtk_box_pack_start (GTK_BOX (item_view->priv->effects_options),
|
|
|
|
item_view->priv->effects_lower_button, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_set_visible (item_view->priv->effects_lower_button, TRUE);
|
|
|
|
|
|
|
|
item_view->priv->effects_merge_button =
|
|
|
|
gtk_button_new_from_icon_name (GIMP_ICON_LAYER_MERGE_DOWN,
|
|
|
|
GTK_ICON_SIZE_SMALL_TOOLBAR);
|
|
|
|
gimp_help_set_help_data (item_view->priv->effects_merge_button,
|
|
|
|
_("Merge all active filters down."),
|
2024-06-19 13:42:41 -04:00
|
|
|
GIMP_HELP_LAYER_EFFECTS);
|
2023-06-19 14:54:21 +00:00
|
|
|
g_signal_connect (item_view->priv->effects_merge_button, "clicked",
|
2025-05-28 22:15:41 +02:00
|
|
|
G_CALLBACK (gimp_item_tree_view_effects_merge_clicked),
|
2023-06-19 14:54:21 +00:00
|
|
|
item_view);
|
|
|
|
gtk_box_pack_start (GTK_BOX (item_view->priv->effects_options),
|
|
|
|
item_view->priv->effects_merge_button, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_set_visible (item_view->priv->effects_merge_button, TRUE);
|
|
|
|
|
|
|
|
item_view->priv->effects_remove_button =
|
|
|
|
gtk_button_new_from_icon_name (GIMP_ICON_EDIT_DELETE,
|
|
|
|
GTK_ICON_SIZE_SMALL_TOOLBAR);
|
|
|
|
gimp_help_set_help_data (item_view->priv->effects_remove_button,
|
|
|
|
_("Remove the selected filter."),
|
2024-06-19 13:42:41 -04:00
|
|
|
GIMP_HELP_LAYER_EFFECTS);
|
2023-06-19 14:54:21 +00:00
|
|
|
g_signal_connect (item_view->priv->effects_remove_button, "clicked",
|
2025-05-28 22:15:41 +02:00
|
|
|
G_CALLBACK (gimp_item_tree_view_effects_remove_clicked),
|
2023-06-19 14:54:21 +00:00
|
|
|
item_view);
|
|
|
|
gtk_box_pack_start (GTK_BOX (item_view->priv->effects_options),
|
|
|
|
item_view->priv->effects_remove_button, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_set_visible (item_view->priv->effects_remove_button, TRUE);
|
|
|
|
|
|
|
|
label = gtk_label_new (NULL);
|
|
|
|
text = g_strdup_printf ("<b>%s</b>",
|
|
|
|
_("Layer Effects"));
|
|
|
|
gtk_label_set_markup (GTK_LABEL (label), text);
|
|
|
|
gtk_widget_set_visible (label, TRUE);
|
|
|
|
g_free (text);
|
|
|
|
|
|
|
|
/* Effects popover. */
|
|
|
|
item_view->priv->effects_popover = gtk_popover_new (GTK_WIDGET (tree_view->view));
|
|
|
|
gtk_popover_set_modal (GTK_POPOVER (item_view->priv->effects_popover), TRUE);
|
|
|
|
gtk_container_add (GTK_CONTAINER (item_view->priv->effects_popover),
|
|
|
|
item_view->priv->effects_filters);
|
2024-08-24 23:03:04 +02:00
|
|
|
gimp_help_connect (item_view->priv->effects_filters, NULL,
|
|
|
|
gimp_standard_help_func, GIMP_HELP_LAYER_EFFECTS, NULL, NULL);
|
2023-06-19 14:54:21 +00:00
|
|
|
gtk_box_pack_start (GTK_BOX (item_view->priv->effects_filters), label,
|
|
|
|
FALSE, FALSE, 0);
|
|
|
|
gtk_box_pack_start (GTK_BOX (item_view->priv->effects_filters),
|
|
|
|
item_view->priv->effects_box, FALSE, FALSE, 0);
|
|
|
|
gtk_box_pack_start (GTK_BOX (item_view->priv->effects_filters),
|
|
|
|
item_view->priv->effects_options, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_set_visible (item_view->priv->effects_box, TRUE);
|
|
|
|
gtk_widget_set_visible (item_view->priv->effects_options, TRUE);
|
|
|
|
gtk_widget_set_visible (item_view->priv->effects_filters, TRUE);
|
|
|
|
}
|
2024-02-06 21:05:43 +01:00
|
|
|
|
|
|
|
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);
|
2024-10-29 01:45:43 +00:00
|
|
|
/* TODO: Currently the search feature only works on layers.
|
|
|
|
* In the future, we should expand this to channels and paths
|
|
|
|
* dockables as well */
|
|
|
|
if (GIMP_IS_LAYER_TREE_VIEW (object))
|
|
|
|
gtk_widget_show (item_view->priv->search_button);
|
2024-02-06 21:05:43 +01:00
|
|
|
|
|
|
|
/* 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.
|
|
|
|
*/
|
2024-10-29 01:45:43 +00:00
|
|
|
if (GIMP_IS_LAYER_TREE_VIEW (object))
|
|
|
|
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);
|
2024-02-06 21:05:43 +01:00
|
|
|
gtk_widget_show (items_header);
|
2003-03-16 11:14:29 +00:00
|
|
|
}
|
|
|
|
|
2003-12-21 12:11:44 +00:00
|
|
|
static void
|
2010-10-15 14:08:36 +02:00
|
|
|
gimp_item_tree_view_dispose (GObject *object)
|
2003-12-21 12:11:44 +00:00
|
|
|
{
|
|
|
|
GimpItemTreeView *view = GIMP_ITEM_TREE_VIEW (object);
|
2001-02-27 14:14:13 +00:00
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
if (view->priv->image)
|
2003-03-16 11:14:29 +00:00
|
|
|
gimp_item_tree_view_set_image (view, NULL);
|
2001-05-01 14:58:13 +00:00
|
|
|
|
2021-02-09 00:04:05 +01:00
|
|
|
if (view->priv->lock_popover)
|
|
|
|
{
|
|
|
|
gtk_widget_destroy (view->priv->lock_popover);
|
|
|
|
view->priv->lock_popover = NULL;
|
|
|
|
}
|
|
|
|
|
2021-02-11 10:33:57 +01:00
|
|
|
if (view->priv->lock_box_path)
|
|
|
|
{
|
|
|
|
gtk_tree_path_free (view->priv->lock_box_path);
|
|
|
|
view->priv->lock_box_path = NULL;
|
|
|
|
}
|
|
|
|
|
2021-02-09 13:12:35 +01:00
|
|
|
if (view->priv->locks)
|
2021-02-09 02:39:37 +01:00
|
|
|
{
|
2021-02-09 13:12:35 +01:00
|
|
|
g_list_free_full (view->priv->locks,
|
2021-02-09 02:39:37 +01:00
|
|
|
(GDestroyNotify) g_free);
|
2021-02-09 13:12:35 +01:00
|
|
|
view->priv->locks = NULL;
|
2021-02-09 02:39:37 +01:00
|
|
|
}
|
|
|
|
|
2023-06-19 14:54:21 +00:00
|
|
|
if (view->priv->effects_popover)
|
|
|
|
{
|
|
|
|
gtk_widget_destroy (view->priv->effects_popover);
|
|
|
|
view->priv->effects_popover = NULL;
|
|
|
|
}
|
|
|
|
view->priv->effects_drawable = NULL;
|
|
|
|
view->priv->effects_filter = NULL;
|
|
|
|
|
2010-10-15 14:08:36 +02:00
|
|
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
2001-02-27 14:14:13 +00:00
|
|
|
}
|
|
|
|
|
2009-08-19 10:44:38 +02:00
|
|
|
static void
|
2011-01-09 20:38:01 +01:00
|
|
|
gimp_item_tree_view_style_updated (GtkWidget *widget)
|
2009-08-19 10:44:38 +02:00
|
|
|
{
|
|
|
|
GimpItemTreeView *view = GIMP_ITEM_TREE_VIEW (widget);
|
2009-09-03 13:22:17 +02:00
|
|
|
GList *children;
|
|
|
|
GList *list;
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
const gchar *old_icon_name;
|
|
|
|
gchar *icon_name;
|
2009-09-03 13:22:17 +02:00
|
|
|
GtkReliefStyle button_relief;
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
GtkIconSize old_size;
|
|
|
|
GtkIconSize button_icon_size = GTK_ICON_SIZE_SMALL_TOOLBAR;
|
|
|
|
gint pixel_icon_size = 16;
|
2009-09-03 13:22:17 +02:00
|
|
|
gint content_spacing;
|
|
|
|
gint button_spacing;
|
|
|
|
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
|
2009-09-03 13:22:17 +02:00
|
|
|
gtk_widget_style_get (widget,
|
|
|
|
"button-relief", &button_relief,
|
|
|
|
"button-icon-size", &button_icon_size,
|
|
|
|
"content-spacing", &content_spacing,
|
|
|
|
"button-spacing", &button_spacing,
|
|
|
|
NULL);
|
2009-08-19 10:44:38 +02:00
|
|
|
|
|
|
|
if (view->priv->options_box)
|
|
|
|
{
|
2009-09-03 13:22:17 +02:00
|
|
|
gtk_box_set_spacing (GTK_BOX (view->priv->options_box), content_spacing);
|
2009-08-19 10:44:38 +02:00
|
|
|
|
2009-09-03 13:22:17 +02:00
|
|
|
children =
|
|
|
|
gtk_container_get_children (GTK_CONTAINER (view->priv->options_box));
|
2009-08-19 10:44:38 +02:00
|
|
|
|
2009-09-03 13:22:17 +02:00
|
|
|
for (list = children; list; list = g_list_next (list))
|
|
|
|
{
|
|
|
|
GtkWidget *child = list->data;
|
|
|
|
|
2011-04-18 20:40:10 +02:00
|
|
|
if (GTK_IS_BOX (child))
|
|
|
|
gtk_box_set_spacing (GTK_BOX (child), button_spacing);
|
2009-09-03 13:22:17 +02:00
|
|
|
}
|
|
|
|
|
2010-06-22 23:05:28 +02:00
|
|
|
g_list_free (children);
|
2009-09-03 13:22:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (view->priv->lock_box)
|
|
|
|
{
|
2009-08-19 10:44:38 +02:00
|
|
|
gtk_box_set_spacing (GTK_BOX (view->priv->lock_box), button_spacing);
|
|
|
|
|
2009-09-03 13:22:17 +02:00
|
|
|
children =
|
|
|
|
gtk_container_get_children (GTK_CONTAINER (view->priv->lock_box));
|
2009-08-19 10:44:38 +02:00
|
|
|
|
|
|
|
for (list = children; list; list = g_list_next (list))
|
|
|
|
{
|
|
|
|
GtkWidget *child = list->data;
|
|
|
|
|
2009-09-03 13:22:17 +02:00
|
|
|
if (GTK_IS_BUTTON (child))
|
|
|
|
{
|
|
|
|
GtkWidget *image;
|
|
|
|
|
|
|
|
gtk_button_set_relief (GTK_BUTTON (child), button_relief);
|
|
|
|
|
|
|
|
image = gtk_bin_get_child (GTK_BIN (child));
|
|
|
|
|
|
|
|
if (GTK_IS_IMAGE (image))
|
|
|
|
{
|
|
|
|
GtkIconSize old_size;
|
|
|
|
|
2014-05-07 15:30:38 +02:00
|
|
|
gtk_image_get_icon_name (GTK_IMAGE (image),
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
&old_icon_name, &old_size);
|
2009-09-03 13:22:17 +02:00
|
|
|
|
|
|
|
if (button_icon_size != old_size)
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
2009-09-03 13:22:17 +02:00
|
|
|
}
|
|
|
|
}
|
2009-08-19 10:44:38 +02:00
|
|
|
}
|
|
|
|
|
2010-06-23 00:19:44 +02:00
|
|
|
g_list_free (children);
|
2009-08-19 10:44:38 +02:00
|
|
|
}
|
|
|
|
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
gtk_image_get_icon_name (GTK_IMAGE (view->priv->lock_header_image),
|
|
|
|
&old_icon_name, &old_size);
|
|
|
|
|
|
|
|
if (button_icon_size != old_size)
|
|
|
|
{
|
|
|
|
icon_name = g_strdup (old_icon_name);
|
|
|
|
gtk_image_set_from_icon_name (GTK_IMAGE (view->priv->lock_header_image),
|
|
|
|
icon_name, button_icon_size);
|
|
|
|
g_free (icon_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_image_get_icon_name (GTK_IMAGE (view->priv->eye_header_image),
|
|
|
|
&old_icon_name, &old_size);
|
|
|
|
if (button_icon_size != old_size)
|
|
|
|
{
|
|
|
|
icon_name = g_strdup (old_icon_name);
|
|
|
|
gtk_image_set_from_icon_name (GTK_IMAGE (view->priv->eye_header_image),
|
|
|
|
icon_name, button_icon_size);
|
|
|
|
g_free (icon_name);
|
|
|
|
}
|
|
|
|
|
2024-02-06 21:05:43 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2024-01-30 04:06:39 +00:00
|
|
|
if (GIMP_IS_LAYER_TREE_VIEW (view))
|
|
|
|
{
|
|
|
|
gtk_image_get_icon_name (GTK_IMAGE (view->priv->effect_header_image),
|
|
|
|
&old_icon_name, &old_size);
|
|
|
|
if (button_icon_size != old_size)
|
|
|
|
{
|
|
|
|
icon_name = g_strdup (old_icon_name);
|
|
|
|
gtk_image_set_from_icon_name (GTK_IMAGE (view->priv->effect_header_image),
|
|
|
|
icon_name, button_icon_size);
|
|
|
|
g_free (icon_name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
/* force the eye and toggle cells to recreate their icon */
|
|
|
|
gtk_icon_size_lookup (button_icon_size, &pixel_icon_size, NULL);
|
2015-12-11 22:55:01 +01:00
|
|
|
g_object_set (view->priv->eye_cell,
|
2017-03-05 16:01:59 +01:00
|
|
|
"icon-name", GIMP_ICON_VISIBLE,
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
"icon-size", pixel_icon_size,
|
2015-12-11 22:55:01 +01:00
|
|
|
NULL);
|
2021-02-09 00:04:05 +01:00
|
|
|
g_object_set (view->priv->lock_cell,
|
2021-03-09 11:08:00 +01:00
|
|
|
"icon-name", GIMP_ICON_LOCK_MULTI,
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
"icon-size", pixel_icon_size,
|
2015-12-11 22:55:01 +01:00
|
|
|
NULL);
|
|
|
|
|
2023-06-19 14:54:21 +00:00
|
|
|
if (GIMP_IS_LAYER_TREE_VIEW (view))
|
|
|
|
g_object_set (view->priv->effects_cell,
|
2024-01-30 04:06:39 +00:00
|
|
|
"icon-name", GIMP_ICON_EFFECT,
|
2023-06-19 14:54:21 +00:00
|
|
|
"icon-size", pixel_icon_size,
|
|
|
|
NULL);
|
|
|
|
|
2011-01-09 20:38:01 +01:00
|
|
|
GTK_WIDGET_CLASS (parent_class)->style_updated (widget);
|
2009-08-19 10:44:38 +02:00
|
|
|
}
|
|
|
|
|
2001-02-27 14:14:13 +00:00
|
|
|
GtkWidget *
|
2004-10-16 20:17:30 +00:00
|
|
|
gimp_item_tree_view_new (GType view_type,
|
2006-01-17 10:08:50 +00:00
|
|
|
gint view_size,
|
|
|
|
gint view_border_width,
|
2020-03-22 15:18:28 +01:00
|
|
|
gboolean multiple_selection,
|
2006-03-28 17:08:36 +00:00
|
|
|
GimpImage *image,
|
2004-10-16 15:48:23 +00:00
|
|
|
GimpMenuFactory *menu_factory,
|
|
|
|
const gchar *menu_identifier,
|
|
|
|
const gchar *ui_path)
|
2001-02-27 14:14:13 +00:00
|
|
|
{
|
2004-05-10 23:22:39 +00:00
|
|
|
GimpItemTreeView *item_view;
|
2001-02-27 14:14:13 +00:00
|
|
|
|
2004-10-16 20:17:30 +00:00
|
|
|
g_return_val_if_fail (g_type_is_a (view_type, GIMP_TYPE_ITEM_TREE_VIEW), NULL);
|
2006-01-17 10:08:50 +00:00
|
|
|
g_return_val_if_fail (view_size > 0 &&
|
2006-04-12 12:49:29 +00:00
|
|
|
view_size <= GIMP_VIEWABLE_MAX_PREVIEW_SIZE, NULL);
|
2006-01-17 10:08:50 +00:00
|
|
|
g_return_val_if_fail (view_border_width >= 0 &&
|
|
|
|
view_border_width <= GIMP_VIEW_MAX_BORDER_WIDTH,
|
2003-04-08 12:39:02 +00:00
|
|
|
NULL);
|
2006-03-28 17:08:36 +00:00
|
|
|
g_return_val_if_fail (image == NULL || GIMP_IS_IMAGE (image), NULL);
|
2003-01-10 17:55:53 +00:00
|
|
|
g_return_val_if_fail (GIMP_IS_MENU_FACTORY (menu_factory), NULL);
|
|
|
|
g_return_val_if_fail (menu_identifier != NULL, NULL);
|
2004-05-12 18:36:33 +00:00
|
|
|
g_return_val_if_fail (ui_path != NULL, NULL);
|
2001-02-27 14:14:13 +00:00
|
|
|
|
2003-12-21 12:11:44 +00:00
|
|
|
item_view = g_object_new (view_type,
|
2004-05-12 18:36:33 +00:00
|
|
|
"reorderable", TRUE,
|
|
|
|
"menu-factory", menu_factory,
|
|
|
|
"menu-identifier", menu_identifier,
|
|
|
|
"ui-path", ui_path,
|
2020-03-22 15:18:28 +01:00
|
|
|
"selection-mode", multiple_selection ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE,
|
2003-12-21 12:11:44 +00:00
|
|
|
NULL);
|
|
|
|
|
2006-01-17 10:08:50 +00:00
|
|
|
gimp_container_view_set_view_size (GIMP_CONTAINER_VIEW (item_view),
|
|
|
|
view_size, view_border_width);
|
2003-03-26 17:49:42 +00:00
|
|
|
|
2006-03-28 17:08:36 +00:00
|
|
|
gimp_item_tree_view_set_image (item_view, image);
|
2001-02-27 14:14:13 +00:00
|
|
|
|
2003-03-19 15:17:13 +00:00
|
|
|
return GTK_WIDGET (item_view);
|
2001-02-27 14:14:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2003-03-16 11:14:29 +00:00
|
|
|
gimp_item_tree_view_set_image (GimpItemTreeView *view,
|
2006-03-28 17:08:36 +00:00
|
|
|
GimpImage *image)
|
2001-05-03 12:26:05 +00:00
|
|
|
{
|
2003-03-16 11:14:29 +00:00
|
|
|
g_return_if_fail (GIMP_IS_ITEM_TREE_VIEW (view));
|
2006-03-28 17:08:36 +00:00
|
|
|
g_return_if_fail (image == NULL || GIMP_IS_IMAGE (image));
|
2001-05-03 12:26:05 +00:00
|
|
|
|
2006-03-28 17:08:36 +00:00
|
|
|
g_signal_emit (view, view_signals[SET_IMAGE], 0, image);
|
2004-10-15 12:27:07 +00:00
|
|
|
|
2011-04-09 19:51:51 +02:00
|
|
|
gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (view)), view);
|
2001-05-03 12:26:05 +00:00
|
|
|
}
|
|
|
|
|
2006-06-16 17:02:14 +00:00
|
|
|
GimpImage *
|
|
|
|
gimp_item_tree_view_get_image (GimpItemTreeView *view)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_ITEM_TREE_VIEW (view), NULL);
|
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
return view->priv->image;
|
|
|
|
}
|
|
|
|
|
2009-08-19 10:44:38 +02:00
|
|
|
void
|
|
|
|
gimp_item_tree_view_add_options (GimpItemTreeView *view,
|
|
|
|
const gchar *label,
|
|
|
|
GtkWidget *options)
|
|
|
|
{
|
2011-05-01 23:23:19 +02:00
|
|
|
gint content_spacing;
|
|
|
|
gint button_spacing;
|
2009-08-19 10:44:38 +02:00
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_ITEM_TREE_VIEW (view));
|
|
|
|
g_return_if_fail (GTK_IS_WIDGET (options));
|
|
|
|
|
|
|
|
gtk_widget_style_get (GTK_WIDGET (view),
|
|
|
|
"content-spacing", &content_spacing,
|
|
|
|
"button-spacing", &button_spacing,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (! view->priv->options_box)
|
|
|
|
{
|
|
|
|
GimpItemTreeViewClass *item_view_class;
|
|
|
|
|
|
|
|
item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (view);
|
|
|
|
|
2011-09-30 11:29:11 +02:00
|
|
|
view->priv->options_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, content_spacing);
|
2009-08-19 10:44:38 +02:00
|
|
|
gtk_box_pack_start (GTK_BOX (view), view->priv->options_box,
|
|
|
|
FALSE, FALSE, 0);
|
|
|
|
gtk_box_reorder_child (GTK_BOX (view), view->priv->options_box, 0);
|
|
|
|
gtk_widget_show (view->priv->options_box);
|
|
|
|
|
|
|
|
if (! view->priv->image ||
|
2022-10-12 22:47:22 +02:00
|
|
|
! item_view_class->get_selected_items (view->priv->image))
|
2009-08-19 10:44:38 +02:00
|
|
|
{
|
|
|
|
gtk_widget_set_sensitive (view->priv->options_box, FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-18 20:40:10 +02:00
|
|
|
if (label)
|
|
|
|
{
|
|
|
|
GtkWidget *hbox;
|
|
|
|
GtkWidget *label_widget;
|
|
|
|
gboolean group_created = FALSE;
|
|
|
|
|
2011-09-30 11:29:11 +02:00
|
|
|
hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, button_spacing);
|
2011-04-18 20:40:10 +02:00
|
|
|
gtk_box_pack_start (GTK_BOX (view->priv->options_box), hbox,
|
|
|
|
FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (hbox);
|
2009-08-19 10:44:38 +02:00
|
|
|
|
2011-04-18 20:40:10 +02:00
|
|
|
if (! view->priv->options_group)
|
|
|
|
{
|
|
|
|
view->priv->options_group = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
|
|
|
|
group_created = TRUE;
|
|
|
|
}
|
2009-08-19 10:44:38 +02:00
|
|
|
|
2011-04-18 20:40:10 +02:00
|
|
|
label_widget = gtk_label_new (label);
|
2016-09-08 19:11:20 +02:00
|
|
|
gtk_label_set_xalign (GTK_LABEL (label_widget), 0.0);
|
2011-04-18 20:40:10 +02:00
|
|
|
gtk_size_group_add_widget (view->priv->options_group, label_widget);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), label_widget, FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (label_widget);
|
2009-08-19 10:44:38 +02:00
|
|
|
|
2011-04-18 20:40:10 +02:00
|
|
|
if (group_created)
|
|
|
|
g_object_unref (view->priv->options_group);
|
|
|
|
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox), options, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_show (options);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gtk_box_pack_start (GTK_BOX (view->priv->options_box), options,
|
|
|
|
FALSE, FALSE, 0);
|
|
|
|
gtk_widget_show (options);
|
|
|
|
}
|
2009-08-19 10:44:38 +02:00
|
|
|
}
|
|
|
|
|
2021-02-09 02:39:37 +01:00
|
|
|
void
|
|
|
|
gimp_item_tree_view_add_lock (GimpItemTreeView *view,
|
|
|
|
const gchar *icon_name,
|
|
|
|
GimpIsLockedFunc is_locked,
|
|
|
|
GimpCanLockFunc can_lock,
|
|
|
|
GimpSetLockFunc lock,
|
2021-02-11 16:17:36 +01:00
|
|
|
GimpUndoLockPush undo_push,
|
2021-02-09 02:39:37 +01:00
|
|
|
const gchar *signal_name,
|
|
|
|
GimpUndoType undo_type,
|
|
|
|
GimpUndoType group_undo_type,
|
2021-02-11 16:17:36 +01:00
|
|
|
const gchar *undo_lock_desc,
|
|
|
|
const gchar *undo_unlock_desc,
|
|
|
|
const gchar *undo_exclusive_desc,
|
2021-02-09 02:39:37 +01:00
|
|
|
const gchar *tooltip,
|
|
|
|
const gchar *help_id)
|
2009-08-19 10:44:38 +02:00
|
|
|
{
|
2021-02-09 02:39:37 +01:00
|
|
|
LockToggle *data;
|
|
|
|
GtkWidget *toggle = gtk_toggle_button_new ();
|
|
|
|
GtkWidget *image;
|
|
|
|
GtkIconSize icon_size;
|
|
|
|
|
|
|
|
data = g_new0 (LockToggle, 1);
|
|
|
|
data->toggle = toggle;
|
|
|
|
data->icon_name = icon_name;
|
|
|
|
data->is_locked = is_locked;
|
|
|
|
data->can_lock = can_lock;
|
|
|
|
data->lock = lock;
|
2021-02-11 16:17:36 +01:00
|
|
|
data->undo_push = undo_push;
|
2021-02-09 02:39:37 +01:00
|
|
|
data->signal_name = signal_name;
|
|
|
|
data->tooltip = tooltip;
|
|
|
|
data->help_id = help_id;
|
|
|
|
|
2021-02-11 16:17:36 +01:00
|
|
|
data->undo_type = undo_type;
|
|
|
|
data->group_undo_type = group_undo_type;
|
|
|
|
data->undo_lock_desc = undo_lock_desc;
|
|
|
|
data->undo_unlock_desc = undo_unlock_desc;
|
|
|
|
data->undo_exclusive_desc = undo_exclusive_desc;
|
2021-02-09 02:39:37 +01:00
|
|
|
|
2021-02-09 13:12:35 +01:00
|
|
|
view->priv->locks = g_list_prepend (view->priv->locks, data);
|
2021-02-09 02:39:37 +01:00
|
|
|
|
|
|
|
gtk_box_pack_end (GTK_BOX (view->priv->lock_box), toggle, FALSE, FALSE, 0);
|
|
|
|
gtk_box_reorder_child (GTK_BOX (view->priv->lock_box), toggle, 0);
|
|
|
|
gtk_widget_show (toggle);
|
|
|
|
|
|
|
|
g_object_set_data (G_OBJECT (toggle), "lock-data", data);
|
|
|
|
g_signal_connect (toggle, "toggled",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_lock_toggled),
|
|
|
|
view);
|
2021-02-11 16:17:36 +01:00
|
|
|
g_signal_connect (toggle, "button-release-event",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_lock_button_release),
|
|
|
|
view);
|
2021-02-09 02:39:37 +01:00
|
|
|
|
2024-08-24 23:03:04 +02:00
|
|
|
gimp_help_connect (toggle, tooltip, gimp_standard_help_func, help_id, NULL, NULL);
|
2009-08-19 10:44:38 +02:00
|
|
|
|
2021-02-09 02:39:37 +01:00
|
|
|
gtk_widget_style_get (GTK_WIDGET (view),
|
|
|
|
"button-icon-size", &icon_size,
|
|
|
|
NULL);
|
2009-08-19 10:44:38 +02:00
|
|
|
|
2021-02-09 02:39:37 +01:00
|
|
|
image = gtk_image_new_from_icon_name (icon_name, icon_size);
|
|
|
|
gtk_container_add (GTK_CONTAINER (toggle), image);
|
|
|
|
gtk_widget_show (image);
|
2009-08-19 10:44:38 +02:00
|
|
|
}
|
|
|
|
|
2021-02-09 16:49:04 +01:00
|
|
|
void
|
|
|
|
gimp_item_tree_view_blink_lock (GimpItemTreeView *view,
|
|
|
|
GimpItem *item)
|
|
|
|
{
|
|
|
|
GtkTreeIter *iter;
|
|
|
|
GtkTreePath *path;
|
|
|
|
GdkRectangle rect;
|
|
|
|
|
|
|
|
g_return_if_fail (GIMP_IS_ITEM_TREE_VIEW (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);
|
|
|
|
path = gtk_tree_model_get_path (GIMP_CONTAINER_TREE_VIEW (view)->model, iter);
|
|
|
|
|
|
|
|
/* Scroll dockable to make sure the cell is showing. */
|
|
|
|
gtk_tree_view_scroll_to_cell (GIMP_CONTAINER_TREE_VIEW (view)->view, path,
|
|
|
|
gtk_tree_view_get_column (GIMP_CONTAINER_TREE_VIEW (view)->view, 1),
|
|
|
|
FALSE, 0.0, 0.0);
|
|
|
|
|
|
|
|
/* Now blink the lock cell of the specified item. */
|
|
|
|
gtk_tree_view_get_cell_area (GIMP_CONTAINER_TREE_VIEW (view)->view, path,
|
|
|
|
gtk_tree_view_get_column (GIMP_CONTAINER_TREE_VIEW (view)->view, 1),
|
|
|
|
&rect);
|
2021-02-25 18:48:23 +01:00
|
|
|
gtk_tree_view_convert_bin_window_to_widget_coords (GIMP_CONTAINER_TREE_VIEW (view)->view,
|
|
|
|
rect.x, rect.y, &rect.x, &rect.y);
|
2021-02-09 16:49:04 +01:00
|
|
|
gimp_widget_blink_rect (GTK_WIDGET (GIMP_CONTAINER_TREE_VIEW (view)->view), &rect);
|
|
|
|
|
|
|
|
gtk_tree_path_free (path);
|
|
|
|
}
|
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
GtkWidget *
|
|
|
|
gimp_item_tree_view_get_new_button (GimpItemTreeView *view)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_ITEM_TREE_VIEW (view), NULL);
|
|
|
|
|
|
|
|
return view->priv->new_button;
|
|
|
|
}
|
|
|
|
|
2018-03-07 05:40:38 -05:00
|
|
|
GtkWidget *
|
|
|
|
gimp_item_tree_view_get_delete_button (GimpItemTreeView *view)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (GIMP_IS_ITEM_TREE_VIEW (view), NULL);
|
|
|
|
|
|
|
|
return view->priv->delete_button;
|
|
|
|
}
|
|
|
|
|
2009-08-03 19:21:51 +02:00
|
|
|
gint
|
|
|
|
gimp_item_tree_view_get_drop_index (GimpItemTreeView *view,
|
|
|
|
GimpViewable *dest_viewable,
|
|
|
|
GtkTreeViewDropPosition drop_pos,
|
|
|
|
GimpViewable **parent)
|
|
|
|
{
|
|
|
|
gint index = -1;
|
|
|
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_ITEM_TREE_VIEW (view), -1);
|
|
|
|
g_return_val_if_fail (dest_viewable == NULL ||
|
|
|
|
GIMP_IS_VIEWABLE (dest_viewable), -1);
|
|
|
|
g_return_val_if_fail (parent != NULL, -1);
|
|
|
|
|
|
|
|
*parent = NULL;
|
|
|
|
|
|
|
|
if (dest_viewable)
|
|
|
|
{
|
|
|
|
*parent = gimp_viewable_get_parent (dest_viewable);
|
|
|
|
index = gimp_item_get_index (GIMP_ITEM (dest_viewable));
|
|
|
|
|
2011-02-08 09:35:38 +01:00
|
|
|
if (drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER)
|
2009-08-03 19:21:51 +02:00
|
|
|
{
|
|
|
|
GimpContainer *children = gimp_viewable_get_children (dest_viewable);
|
|
|
|
|
|
|
|
if (children)
|
|
|
|
{
|
|
|
|
*parent = dest_viewable;
|
|
|
|
index = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
index++;
|
|
|
|
}
|
|
|
|
}
|
2011-02-08 09:35:38 +01:00
|
|
|
else if (drop_pos == GTK_TREE_VIEW_DROP_AFTER)
|
|
|
|
{
|
|
|
|
index++;
|
|
|
|
}
|
2009-08-03 19:21:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
2001-05-03 12:26:05 +00:00
|
|
|
static void
|
2003-03-16 11:14:29 +00:00
|
|
|
gimp_item_tree_view_real_set_image (GimpItemTreeView *view,
|
2006-03-28 17:08:36 +00:00
|
|
|
GimpImage *image)
|
2001-02-27 14:14:13 +00:00
|
|
|
{
|
2024-02-06 21:05:43 +01:00
|
|
|
GimpItemTreeViewClass *item_view_class;
|
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
if (view->priv->image == image)
|
2001-02-27 14:14:13 +00:00
|
|
|
return;
|
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
if (view->priv->image)
|
2001-02-27 14:14:13 +00:00
|
|
|
{
|
2008-12-25 11:31:51 +00:00
|
|
|
g_signal_handlers_disconnect_by_func (view->priv->image,
|
2006-04-12 12:49:29 +00:00
|
|
|
gimp_item_tree_view_item_changed,
|
|
|
|
view);
|
2008-12-25 11:31:51 +00:00
|
|
|
g_signal_handlers_disconnect_by_func (view->priv->image,
|
2006-04-12 12:49:29 +00:00
|
|
|
gimp_item_tree_view_size_changed,
|
|
|
|
view);
|
2001-02-27 14:14:13 +00:00
|
|
|
|
|
|
|
gimp_container_view_set_container (GIMP_CONTAINER_VIEW (view), NULL);
|
2004-10-15 12:27:07 +00:00
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
g_signal_handlers_disconnect_by_func (view->priv->image,
|
2004-10-15 12:27:07 +00:00
|
|
|
gimp_item_tree_view_image_flush,
|
|
|
|
view);
|
2024-02-06 21:05:43 +01:00
|
|
|
|
|
|
|
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);
|
2001-02-27 14:14:13 +00:00
|
|
|
}
|
|
|
|
|
2024-01-03 18:57:08 +00:00
|
|
|
view->priv->image = image;
|
|
|
|
view->priv->effects_drawable = NULL;
|
|
|
|
view->priv->effects_filter = NULL;
|
|
|
|
view->priv->filters_active_changed_handler = NULL;
|
2024-04-19 01:58:56 +00:00
|
|
|
if (view->priv->effects_popover)
|
|
|
|
gtk_widget_set_visible (view->priv->effects_popover, FALSE);
|
2001-02-27 14:14:13 +00:00
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
if (view->priv->image)
|
2001-02-27 14:14:13 +00:00
|
|
|
{
|
|
|
|
GimpContainer *container;
|
|
|
|
|
2003-02-17 13:33:29 +00:00
|
|
|
container =
|
2008-12-25 11:31:51 +00:00
|
|
|
GIMP_ITEM_TREE_VIEW_GET_CLASS (view)->get_container (view->priv->image);
|
2001-02-27 14:14:13 +00:00
|
|
|
|
|
|
|
gimp_container_view_set_container (GIMP_CONTAINER_VIEW (view), container);
|
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
g_signal_connect (view->priv->image,
|
2004-10-16 20:17:30 +00:00
|
|
|
GIMP_ITEM_TREE_VIEW_GET_CLASS (view)->signal_name,
|
2006-04-12 12:49:29 +00:00
|
|
|
G_CALLBACK (gimp_item_tree_view_item_changed),
|
|
|
|
view);
|
2008-12-25 11:31:51 +00:00
|
|
|
g_signal_connect (view->priv->image, "size-changed",
|
2006-04-12 12:49:29 +00:00
|
|
|
G_CALLBACK (gimp_item_tree_view_size_changed),
|
|
|
|
view);
|
2001-03-11 17:24:47 +00:00
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
g_signal_connect (view->priv->image, "flush",
|
2004-10-15 12:27:07 +00:00
|
|
|
G_CALLBACK (gimp_item_tree_view_image_flush),
|
|
|
|
view);
|
|
|
|
|
2024-02-06 21:05:43 +01:00
|
|
|
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);
|
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
gimp_item_tree_view_item_changed (view->priv->image, view);
|
2001-02-27 14:14:13 +00:00
|
|
|
}
|
2024-02-06 21:05:43 +01:00
|
|
|
|
|
|
|
/* 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);
|
2001-02-27 14:14:13 +00:00
|
|
|
}
|
|
|
|
|
2024-08-14 23:34:27 +02:00
|
|
|
static gboolean
|
|
|
|
gimp_item_tree_view_key_press_event (GtkTreeView *tree_view,
|
|
|
|
GdkEventKey *event,
|
|
|
|
GimpItemTreeView *view)
|
|
|
|
{
|
|
|
|
if (event->keyval == GDK_KEY_Up ||
|
|
|
|
event->keyval == GDK_KEY_KP_Up ||
|
|
|
|
event->keyval == GDK_KEY_Down ||
|
|
|
|
event->keyval == GDK_KEY_KP_Down ||
|
|
|
|
event->keyval == GDK_KEY_Page_Up ||
|
|
|
|
event->keyval == GDK_KEY_KP_Page_Up ||
|
|
|
|
event->keyval == GDK_KEY_Down ||
|
|
|
|
event->keyval == GDK_KEY_KP_Down ||
|
|
|
|
event->keyval == GDK_KEY_Page_Down ||
|
|
|
|
event->keyval == GDK_KEY_KP_Page_Down ||
|
|
|
|
event->keyval == GDK_KEY_Home ||
|
|
|
|
event->keyval == GDK_KEY_KP_Home ||
|
|
|
|
event->keyval == GDK_KEY_End ||
|
|
|
|
event->keyval == GDK_KEY_KP_End)
|
|
|
|
{
|
|
|
|
if (event->state & gimp_get_all_modifiers_mask ())
|
|
|
|
/* Let the event propagate, though to be fair, it would be nice
|
|
|
|
* to specify what happens with a Shift-arrow, or Ctrl-arrow,
|
|
|
|
* with a multi-item aware logic. It may also require a concept
|
|
|
|
* of "active" item among the selected one (very likely the last
|
|
|
|
* clicked item).
|
|
|
|
* TODO for a proper gimp-ux spec.
|
|
|
|
*/
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
gimp_item_tree_view_move_cursor (view, event->keyval, event->state);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2004-10-15 12:27:07 +00:00
|
|
|
static void
|
2006-03-28 17:08:36 +00:00
|
|
|
gimp_item_tree_view_image_flush (GimpImage *image,
|
2007-06-26 21:39:51 +00:00
|
|
|
gboolean invalidate_preview,
|
2004-10-15 12:27:07 +00:00
|
|
|
GimpItemTreeView *view)
|
|
|
|
{
|
2023-07-09 23:10:57 +02:00
|
|
|
g_idle_add_full (G_PRIORITY_LOW,
|
|
|
|
(GSourceFunc) gimp_item_tree_view_image_flush_idle,
|
|
|
|
g_object_ref (view), g_object_unref);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gimp_item_tree_view_image_flush_idle (gpointer user_data)
|
|
|
|
{
|
|
|
|
GimpItemTreeView *view = user_data;
|
|
|
|
|
|
|
|
/* This needs to be run as idle because we want this to be run in the main
|
|
|
|
* thread even when the flush happened in a thread (e.g. from the paint
|
|
|
|
* thread).
|
|
|
|
*/
|
2023-07-10 16:55:57 +02:00
|
|
|
if (gimp_editor_get_ui_manager (GIMP_EDITOR (view)))
|
|
|
|
gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (view)), view);
|
2023-07-09 23:10:57 +02:00
|
|
|
|
|
|
|
return G_SOURCE_REMOVE;
|
2004-10-15 12:27:07 +00:00
|
|
|
}
|
|
|
|
|
2001-03-11 17:24:47 +00:00
|
|
|
|
|
|
|
/* GimpContainerView methods */
|
|
|
|
|
2003-05-08 20:26:01 +00:00
|
|
|
static void
|
|
|
|
gimp_item_tree_view_set_container (GimpContainerView *view,
|
|
|
|
GimpContainer *container)
|
|
|
|
{
|
2004-05-10 17:16:50 +00:00
|
|
|
GimpItemTreeView *item_view = GIMP_ITEM_TREE_VIEW (view);
|
|
|
|
GimpContainer *old_container;
|
2021-02-09 02:39:37 +01:00
|
|
|
GList *list;
|
2003-05-08 20:26:01 +00:00
|
|
|
|
2004-05-10 17:16:50 +00:00
|
|
|
old_container = gimp_container_view_get_container (view);
|
2003-05-08 20:26:01 +00:00
|
|
|
|
2004-05-10 17:16:50 +00:00
|
|
|
if (old_container)
|
2003-05-08 20:26:01 +00:00
|
|
|
{
|
2009-08-04 20:20:09 +02:00
|
|
|
gimp_tree_handler_disconnect (item_view->priv->visible_changed_handler);
|
|
|
|
item_view->priv->visible_changed_handler = NULL;
|
2003-09-15 14:39:48 +00:00
|
|
|
|
2016-10-29 16:50:13 +02:00
|
|
|
gimp_tree_handler_disconnect (item_view->priv->color_tag_changed_handler);
|
|
|
|
item_view->priv->color_tag_changed_handler = NULL;
|
|
|
|
|
2023-06-19 14:54:21 +00:00
|
|
|
if (GIMP_IS_LAYER_TREE_VIEW (item_view))
|
|
|
|
{
|
|
|
|
gimp_tree_handler_disconnect (item_view->priv->filters_changed_handler);
|
|
|
|
item_view->priv->filters_changed_handler = NULL;
|
2024-01-03 18:57:08 +00:00
|
|
|
|
|
|
|
if (item_view->priv->filters_active_changed_handler)
|
|
|
|
gimp_tree_handler_disconnect (item_view->priv->filters_active_changed_handler);
|
|
|
|
|
|
|
|
item_view->priv->filters_active_changed_handler = NULL;
|
2023-06-19 14:54:21 +00:00
|
|
|
}
|
|
|
|
|
2021-02-09 13:12:35 +01:00
|
|
|
for (list = item_view->priv->locks; list; list = list->next)
|
2021-02-09 02:39:37 +01:00
|
|
|
{
|
|
|
|
LockToggle *data = list->data;
|
|
|
|
|
|
|
|
gimp_tree_handler_disconnect (data->changed_handler);
|
|
|
|
data->changed_handler = NULL;
|
|
|
|
}
|
2003-05-08 20:26:01 +00:00
|
|
|
}
|
|
|
|
|
2004-05-10 23:22:39 +00:00
|
|
|
parent_view_iface->set_container (view, container);
|
2003-05-08 20:26:01 +00:00
|
|
|
|
2004-05-10 17:16:50 +00:00
|
|
|
if (container)
|
2003-05-08 20:26:01 +00:00
|
|
|
{
|
2009-08-04 20:20:09 +02:00
|
|
|
item_view->priv->visible_changed_handler =
|
|
|
|
gimp_tree_handler_connect (container, "visibility-changed",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_visible_changed),
|
|
|
|
view);
|
|
|
|
|
2016-10-29 16:50:13 +02:00
|
|
|
item_view->priv->color_tag_changed_handler =
|
|
|
|
gimp_tree_handler_connect (container, "color-tag-changed",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_color_tag_changed),
|
|
|
|
view);
|
|
|
|
|
2021-02-09 13:12:35 +01:00
|
|
|
for (list = item_view->priv->locks; list; list = list->next)
|
2021-02-09 02:39:37 +01:00
|
|
|
{
|
|
|
|
LockToggle *data = list->data;
|
|
|
|
|
|
|
|
data->changed_handler = gimp_tree_handler_connect (container,
|
|
|
|
data->signal_name,
|
|
|
|
G_CALLBACK (gimp_item_tree_view_lock_changed),
|
|
|
|
view);
|
|
|
|
}
|
2023-06-19 14:54:21 +00:00
|
|
|
|
|
|
|
if (GIMP_IS_LAYER_TREE_VIEW (item_view))
|
|
|
|
item_view->priv->filters_changed_handler =
|
|
|
|
gimp_tree_handler_connect (container, "filters-changed",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_filters_changed),
|
|
|
|
view);
|
2003-05-08 20:26:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-08-31 21:40:16 +00:00
|
|
|
static void
|
|
|
|
gimp_item_tree_view_set_context (GimpContainerView *view,
|
|
|
|
GimpContext *context)
|
|
|
|
{
|
|
|
|
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
|
|
|
|
GimpItemTreeView *item_view = GIMP_ITEM_TREE_VIEW (view);
|
|
|
|
GimpImage *image = NULL;
|
|
|
|
GimpContext *old_context;
|
|
|
|
|
|
|
|
old_context = gimp_container_view_get_context (view);
|
|
|
|
|
|
|
|
if (old_context)
|
|
|
|
{
|
|
|
|
g_signal_handlers_disconnect_by_func (old_context,
|
|
|
|
gimp_item_tree_view_set_image,
|
|
|
|
item_view);
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
g_signal_handlers_disconnect_by_func (old_context->gimp->config,
|
|
|
|
G_CALLBACK (gimp_item_tree_view_style_updated),
|
|
|
|
item_view);
|
2006-08-31 21:40:16 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
parent_view_iface->set_context (view, context);
|
|
|
|
|
|
|
|
if (context)
|
|
|
|
{
|
|
|
|
if (! tree_view->dnd_gimp)
|
|
|
|
tree_view->dnd_gimp = context->gimp;
|
|
|
|
|
|
|
|
g_signal_connect_swapped (context, "image-changed",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_set_image),
|
|
|
|
item_view);
|
|
|
|
|
Issue #7023: icon size selection on GIMP 2.99.
This kinda reverts commit 6aebd30de142286c41e6cd90abedc4082a13fcea ("app: remove
icon sizing preferences"), except that the code base is different enough since
this old commit was mainly for GIMP 2.10.x.
In any case, after initially thinking that GTK+3 handling for high density
display would be enough, we finally decide that adding back a Preferences-wide
setting for overriding the theme-set icon size is a good idea (additionally to
GTK+3 automatic support).
The base idea for removing the feature was that GTK+3 has high density display
support, through the "scale factor". Typically a high density display will
normally be set as using a ×2 scale factor so all icons will be double size.
Unfortunately it turns out it's not enough.
For instance, on very small screen estate, even with a scale factor of 1, if the
theme sets 24px toolbox icons, it may still take too much space.
Oppositely on huge screens, even with ×2 factor scale detected by the OS, the
icons may still feel too small (this is possibly what happens with #7023).
Furthermore there is also a matter of taste. Some people like small icons even
when they have the space. Others may want bigger icons, easy to click on.
Finally you can like a theme for its color scheme for instance, but it may not
have the icon size you want. Right now, we'd need to duplicate every theme in
small or bigger size. Instead of doing so, let's just have this global setting
overriding the theme rules.
Comparison with the 2.10 implementation:
- We still provide 4 sizes: small, medium, large and huge.
- We don't have the "Guess ideal size" setting anymore. Instead this is now a
mix of the GTK+3 scale factor logic and the theme-set or custom size. I.e.
that on a high density display with ×2 scale factor, we could have toolbox
icons up to 96 pixels (48×2)!
- We now try to have less custom code in widgets as we append the CSS rules to
the theme (similar to what we were already doing for dark theme or icon
variants). What happens in widget code is mostly to connect to changes in
themes and redraw the widgets which need to be.
- The custom size will now affect: toolbox icons, the FG/BG editor widget (in
both the toolbox and the color dockable), dockable tab icons, the main
dockable buttons, eye and lock header icons in item tree views, eye and lock
cell icons in the item lists.
There are still a bunch of areas where it is not taken into account, such as
plug-ins, and various dialogs, but even in custom-made interface in dockables.
Ultimately it might be interesting to have a way to sync more buttons and
widgets to a global size settings.
Lastly, I fixed a bunch of existing bugs where we were updating icon sizes with
gtk_image_set_from_icon_name() using the const icon name taken from
gtk_image_get_icon_name(). As this was reusing the same string pointer, we were
ending with freeing the icon name.
2022-09-26 22:56:08 +02:00
|
|
|
g_signal_connect_object (context->gimp->config,
|
|
|
|
"notify::theme",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_style_updated),
|
|
|
|
item_view, G_CONNECT_AFTER | G_CONNECT_SWAPPED);
|
|
|
|
g_signal_connect_object (context->gimp->config,
|
|
|
|
"notify::override-theme-icon-size",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_style_updated),
|
|
|
|
item_view, G_CONNECT_AFTER | G_CONNECT_SWAPPED);
|
|
|
|
g_signal_connect_object (context->gimp->config,
|
|
|
|
"notify::custom-icon-size",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_style_updated),
|
|
|
|
item_view, G_CONNECT_AFTER | G_CONNECT_SWAPPED);
|
|
|
|
|
2006-08-31 21:40:16 +00:00
|
|
|
image = gimp_context_get_image (context);
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_item_tree_view_set_image (item_view, image);
|
|
|
|
}
|
|
|
|
|
2003-05-08 20:26:01 +00:00
|
|
|
static gpointer
|
|
|
|
gimp_item_tree_view_insert_item (GimpContainerView *view,
|
|
|
|
GimpViewable *viewable,
|
2009-08-01 19:13:35 +02:00
|
|
|
gpointer parent_insert_data,
|
2003-05-08 20:26:01 +00:00
|
|
|
gint index)
|
|
|
|
{
|
2004-05-11 10:01:25 +00:00
|
|
|
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
|
|
|
|
GimpItemTreeView *item_view = GIMP_ITEM_TREE_VIEW (view);
|
|
|
|
GimpItem *item = GIMP_ITEM (viewable);
|
2003-05-08 20:26:01 +00:00
|
|
|
GtkTreeIter *iter;
|
2024-04-02 04:00:50 +00:00
|
|
|
GeglColor *color = gegl_color_new ("none");
|
|
|
|
GdkRGBA rgba;
|
2016-10-29 16:50:13 +02:00
|
|
|
gboolean has_color;
|
2021-02-25 18:40:42 +01:00
|
|
|
const gchar *icon_name;
|
2021-02-09 02:39:37 +01:00
|
|
|
gint n_locks;
|
2003-05-08 20:26:01 +00:00
|
|
|
|
2009-08-01 19:13:35 +02:00
|
|
|
iter = parent_view_iface->insert_item (view, viewable,
|
|
|
|
parent_insert_data, index);
|
2003-05-08 20:26:01 +00:00
|
|
|
|
2017-12-07 16:42:54 -05:00
|
|
|
has_color = gimp_get_color_tag_color (gimp_item_get_merged_color_tag (item),
|
2024-04-02 04:00:50 +00:00
|
|
|
color,
|
2017-12-07 16:42:54 -05:00
|
|
|
gimp_item_get_color_tag (item) ==
|
|
|
|
GIMP_COLOR_TAG_NONE);
|
2024-04-02 04:00:50 +00:00
|
|
|
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), &rgba);
|
|
|
|
g_object_unref (color);
|
2016-10-29 16:50:13 +02:00
|
|
|
|
2021-02-09 02:39:37 +01:00
|
|
|
n_locks = gimp_item_tree_view_get_n_locks (item_view, item, &icon_name);
|
2021-02-09 00:04:05 +01:00
|
|
|
|
2009-07-25 17:38:03 +02:00
|
|
|
gtk_tree_store_set (GTK_TREE_STORE (tree_view->model), iter,
|
2021-02-09 00:04:05 +01:00
|
|
|
|
2008-12-25 11:31:51 +00:00
|
|
|
item_view->priv->model_column_visible,
|
2003-09-11 19:52:29 +00:00
|
|
|
gimp_item_get_visible (item),
|
2021-02-09 00:04:05 +01:00
|
|
|
|
2011-09-23 23:45:10 +02:00
|
|
|
item_view->priv->model_column_viewable,
|
|
|
|
gimp_item_get_visible (item) &&
|
|
|
|
! gimp_item_is_visible (item),
|
2021-02-09 00:04:05 +01:00
|
|
|
|
|
|
|
item_view->priv->model_column_locked,
|
2021-02-09 02:39:37 +01:00
|
|
|
n_locks > 0,
|
2021-02-09 00:04:05 +01:00
|
|
|
|
|
|
|
item_view->priv->model_column_lock_icon,
|
|
|
|
icon_name,
|
|
|
|
|
2016-10-29 16:50:13 +02:00
|
|
|
item_view->priv->model_column_color_tag,
|
2024-04-02 04:00:50 +00:00
|
|
|
has_color ? &rgba : NULL,
|
2003-05-08 20:26:01 +00:00
|
|
|
-1);
|
|
|
|
|
2023-06-19 14:54:21 +00:00
|
|
|
if (GIMP_IS_LAYER_TREE_VIEW (item_view))
|
|
|
|
{
|
|
|
|
GimpContainer *filters;
|
|
|
|
gint n_filters;
|
|
|
|
|
|
|
|
filters = gimp_drawable_get_filters (GIMP_DRAWABLE (item));
|
|
|
|
n_filters = gimp_container_get_n_children (filters);
|
|
|
|
|
|
|
|
gtk_tree_store_set (GTK_TREE_STORE (tree_view->model), iter,
|
|
|
|
item_view->priv->model_column_effects,
|
|
|
|
n_filters > 0,
|
|
|
|
-1);
|
|
|
|
}
|
|
|
|
|
2003-05-08 20:26:01 +00:00
|
|
|
return iter;
|
|
|
|
}
|
|
|
|
|
2009-09-16 20:00:48 +02:00
|
|
|
static void
|
2020-03-31 16:10:29 +02:00
|
|
|
gimp_item_tree_view_insert_items_after (GimpContainerView *view)
|
2009-09-16 20:00:48 +02:00
|
|
|
{
|
|
|
|
GimpItemTreeView *item_view = GIMP_ITEM_TREE_VIEW (view);
|
|
|
|
GimpItemTreeViewClass *item_view_class;
|
2020-03-26 00:33:11 +01:00
|
|
|
GList *selected_items;
|
2009-09-16 20:00:48 +02:00
|
|
|
|
|
|
|
item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (item_view);
|
|
|
|
|
2020-03-26 00:33:11 +01:00
|
|
|
selected_items = item_view_class->get_selected_items (item_view->priv->image);
|
|
|
|
gimp_container_view_select_items (view, selected_items);
|
2009-09-16 20:00:48 +02:00
|
|
|
}
|
|
|
|
|
2020-03-21 19:03:07 +01:00
|
|
|
static gboolean
|
|
|
|
gimp_item_tree_view_select_items (GimpContainerView *view,
|
2020-05-04 17:31:46 +02:00
|
|
|
GList *items,
|
2020-03-21 19:03:07 +01:00
|
|
|
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. */
|
|
|
|
{
|
2020-05-04 17:31:46 +02:00
|
|
|
item_view_class->set_selected_items (tree_view->priv->image, items);
|
|
|
|
|
|
|
|
items = item_view_class->get_selected_items (tree_view->priv->image);
|
2020-03-21 19:03:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
options_sensitive = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_ui_manager_update (gimp_editor_get_ui_manager (GIMP_EDITOR (tree_view)), tree_view);
|
|
|
|
|
2009-08-19 10:44:38 +02:00
|
|
|
if (tree_view->priv->options_box)
|
|
|
|
gtk_widget_set_sensitive (tree_view->priv->options_box, options_sensitive);
|
|
|
|
|
2024-02-06 21:05:43 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2003-05-18 13:28:27 +00:00
|
|
|
return success;
|
2001-02-27 14:14:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2003-03-16 11:14:29 +00:00
|
|
|
gimp_item_tree_view_activate_item (GimpContainerView *view,
|
2002-02-25 17:58:50 +00:00
|
|
|
GimpViewable *item,
|
|
|
|
gpointer insert_data)
|
2001-02-27 14:14:13 +00:00
|
|
|
{
|
2004-10-16 15:48:23 +00:00
|
|
|
GimpItemTreeViewClass *item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (view);
|
2002-02-26 14:40:30 +00:00
|
|
|
|
2004-05-10 23:22:39 +00:00
|
|
|
if (parent_view_iface->activate_item)
|
|
|
|
parent_view_iface->activate_item (view, item, insert_data);
|
2001-02-27 14:14:13 +00:00
|
|
|
|
2004-10-16 15:48:23 +00:00
|
|
|
if (item_view_class->activate_action)
|
|
|
|
{
|
2011-04-09 19:51:51 +02:00
|
|
|
gimp_ui_manager_activate_action (gimp_editor_get_ui_manager (GIMP_EDITOR (view)),
|
2006-12-15 12:03:47 +00:00
|
|
|
item_view_class->action_group,
|
|
|
|
item_view_class->activate_action);
|
2004-10-16 15:48:23 +00:00
|
|
|
}
|
2001-03-06 13:28:39 +00:00
|
|
|
}
|
|
|
|
|
2003-03-19 15:17:13 +00:00
|
|
|
static gboolean
|
|
|
|
gimp_item_tree_view_drop_possible (GimpContainerTreeView *tree_view,
|
2004-06-28 22:07:12 +00:00
|
|
|
GimpDndType src_type,
|
2020-03-24 22:06:28 +01:00
|
|
|
GList *src_viewables,
|
2003-03-19 15:17:13 +00:00
|
|
|
GimpViewable *dest_viewable,
|
2009-12-28 21:10:04 +01:00
|
|
|
GtkTreePath *drop_path,
|
2003-03-19 15:17:13 +00:00
|
|
|
GtkTreeViewDropPosition drop_pos,
|
2004-06-28 22:07:12 +00:00
|
|
|
GtkTreeViewDropPosition *return_drop_pos,
|
|
|
|
GdkDragAction *return_drag_action)
|
2003-03-19 15:17:13 +00:00
|
|
|
{
|
2020-03-24 22:06:28 +01:00
|
|
|
GList *iter;
|
|
|
|
gboolean other_image_items;
|
|
|
|
|
|
|
|
if (src_viewables)
|
|
|
|
other_image_items = TRUE;
|
|
|
|
else
|
|
|
|
other_image_items = FALSE;
|
|
|
|
|
|
|
|
for (iter = src_viewables; iter; iter = iter->next)
|
|
|
|
{
|
|
|
|
GimpViewable *src_viewable = iter->data;
|
|
|
|
|
|
|
|
if (! GIMP_IS_ITEM (src_viewable) ||
|
|
|
|
(dest_viewable != NULL &&
|
|
|
|
gimp_item_get_image (GIMP_ITEM (src_viewable)) ==
|
|
|
|
gimp_item_get_image (GIMP_ITEM (dest_viewable))))
|
|
|
|
{
|
|
|
|
/* Not an item or from the same image. */
|
|
|
|
other_image_items = FALSE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (other_image_items)
|
2003-03-19 15:17:13 +00:00
|
|
|
{
|
2004-06-28 22:07:12 +00:00
|
|
|
if (return_drop_pos)
|
|
|
|
*return_drop_pos = drop_pos;
|
|
|
|
|
|
|
|
if (return_drag_action)
|
|
|
|
*return_drag_action = GDK_ACTION_COPY;
|
2003-03-19 15:17:13 +00:00
|
|
|
|
2003-08-27 17:21:49 +00:00
|
|
|
return TRUE;
|
2003-03-19 15:17:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return GIMP_CONTAINER_TREE_VIEW_CLASS (parent_class)->drop_possible (tree_view,
|
2004-06-28 22:07:12 +00:00
|
|
|
src_type,
|
2020-03-24 22:06:28 +01:00
|
|
|
src_viewables,
|
2003-03-19 15:17:13 +00:00
|
|
|
dest_viewable,
|
2009-12-28 21:10:04 +01:00
|
|
|
drop_path,
|
2003-03-19 15:17:13 +00:00
|
|
|
drop_pos,
|
2004-06-28 22:07:12 +00:00
|
|
|
return_drop_pos,
|
|
|
|
return_drag_action);
|
2003-03-19 15:17:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2020-03-24 22:06:28 +01:00
|
|
|
gimp_item_tree_view_drop_viewables (GimpContainerTreeView *tree_view,
|
|
|
|
GList *src_viewables,
|
|
|
|
GimpViewable *dest_viewable,
|
|
|
|
GtkTreeViewDropPosition drop_pos)
|
2003-03-19 15:17:13 +00:00
|
|
|
{
|
|
|
|
GimpItemTreeViewClass *item_view_class;
|
2021-08-15 01:44:46 +02:00
|
|
|
GimpItemTreeView *item_view = GIMP_ITEM_TREE_VIEW (tree_view);
|
2025-02-27 20:19:27 +01:00
|
|
|
GList *dropped_viewables;
|
|
|
|
GList *dup_children = NULL;
|
2020-03-24 22:06:28 +01:00
|
|
|
GList *iter;
|
2021-08-15 01:44:46 +02:00
|
|
|
GimpImage *src_image = NULL;
|
|
|
|
GType src_viewable_type = G_TYPE_NONE;
|
|
|
|
gint dest_index = -1;
|
2020-03-27 17:18:17 +01:00
|
|
|
|
|
|
|
g_return_if_fail (g_list_length (src_viewables) > 0);
|
2003-03-19 15:17:13 +00:00
|
|
|
|
2025-02-27 20:19:27 +01:00
|
|
|
dropped_viewables = g_list_copy (src_viewables);
|
|
|
|
|
2003-03-19 15:17:13 +00:00
|
|
|
item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (item_view);
|
|
|
|
|
2025-02-27 20:19:27 +01:00
|
|
|
for (iter = dropped_viewables; iter; iter = iter->next)
|
2003-03-19 15:17:13 +00:00
|
|
|
{
|
2020-03-24 22:06:28 +01:00
|
|
|
GimpViewable *src_viewable = iter->data;
|
2003-03-19 15:17:13 +00:00
|
|
|
|
2020-03-27 17:18:17 +01:00
|
|
|
/* All dropped viewables must be of the same finale type and come
|
|
|
|
* from the same source image.
|
|
|
|
*/
|
2020-03-24 22:06:28 +01:00
|
|
|
if (src_viewable_type == G_TYPE_NONE)
|
2025-02-27 20:19:27 +01:00
|
|
|
{
|
|
|
|
src_viewable_type = G_TYPE_FROM_INSTANCE (src_viewable);
|
|
|
|
}
|
2020-03-24 22:06:28 +01:00
|
|
|
else
|
2020-03-27 17:18:17 +01:00
|
|
|
{
|
|
|
|
if (g_type_is_a (src_viewable_type,
|
|
|
|
G_TYPE_FROM_INSTANCE (src_viewable)))
|
|
|
|
/* It is possible to move different types of a same
|
|
|
|
* parenting hierarchy, for instance GimpLayer and
|
|
|
|
* GimpGroupLayer.
|
|
|
|
*/
|
|
|
|
src_viewable_type = G_TYPE_FROM_INSTANCE (src_viewable);
|
|
|
|
|
|
|
|
g_return_if_fail (g_type_is_a (G_TYPE_FROM_INSTANCE (src_viewable),
|
|
|
|
src_viewable_type));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (src_image == NULL)
|
|
|
|
src_image = gimp_item_get_image (GIMP_ITEM (iter->data));
|
|
|
|
else
|
|
|
|
g_return_if_fail (src_image == gimp_item_get_image (GIMP_ITEM (iter->data)));
|
2020-03-24 22:06:28 +01:00
|
|
|
}
|
2005-01-15 03:24:42 +00:00
|
|
|
|
2025-02-27 20:19:27 +01:00
|
|
|
/* What does it mean when an item and a children of this item are
|
|
|
|
* dropped together? Does it mean we want to copy the tree structure
|
|
|
|
* but only this child? What when it's not a copy but a move?
|
|
|
|
* These are complicated questions for UX discussions. For the time
|
|
|
|
* being, we just do the simple answer: all children of a group item
|
|
|
|
* are implied, so we can just remove any descendant from the list of
|
|
|
|
* viewables.
|
|
|
|
*/
|
|
|
|
for (iter = dropped_viewables; iter; iter = iter->next)
|
|
|
|
{
|
|
|
|
GList *iter2;
|
|
|
|
|
|
|
|
for (iter2 = dropped_viewables; iter2; iter2 = iter2->next)
|
|
|
|
{
|
|
|
|
if (iter->data != iter2->data &&
|
|
|
|
gimp_viewable_is_ancestor (iter2->data, iter->data))
|
|
|
|
{
|
|
|
|
dup_children = g_list_prepend (dup_children, iter->data);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (iter = dup_children; iter; iter = iter->next)
|
|
|
|
dropped_viewables = g_list_remove (dropped_viewables, iter->data);
|
|
|
|
g_list_free (dup_children);
|
|
|
|
|
2020-03-24 22:06:28 +01:00
|
|
|
if (drop_pos == GTK_TREE_VIEW_DROP_AFTER ||
|
|
|
|
(drop_pos == GTK_TREE_VIEW_DROP_INTO_OR_AFTER &&
|
|
|
|
dest_viewable &&
|
|
|
|
gimp_viewable_get_children (dest_viewable)))
|
2021-08-15 01:44:46 +02:00
|
|
|
{
|
2025-02-27 20:19:27 +01:00
|
|
|
dropped_viewables = g_list_reverse (dropped_viewables);
|
2021-08-15 01:44:46 +02:00
|
|
|
}
|
2003-03-19 15:17:13 +00:00
|
|
|
|
2020-03-27 17:18:17 +01:00
|
|
|
if (item_view->priv->image != src_image ||
|
|
|
|
! g_type_is_a (src_viewable_type, item_view_class->item_type))
|
2020-03-24 22:06:28 +01:00
|
|
|
{
|
2020-03-27 17:18:17 +01:00
|
|
|
gimp_image_undo_group_start (item_view->priv->image,
|
|
|
|
GIMP_UNDO_GROUP_LAYER_ADD,
|
|
|
|
_("Drop layers"));
|
2003-03-19 15:17:13 +00:00
|
|
|
|
2025-02-27 20:19:27 +01:00
|
|
|
for (iter = dropped_viewables; iter; iter = iter->next)
|
2020-03-24 22:06:28 +01:00
|
|
|
{
|
2020-03-27 17:18:17 +01:00
|
|
|
GimpViewable *src_viewable = iter->data;
|
|
|
|
GimpItem *new_item;
|
|
|
|
GimpItem *parent;
|
2025-02-28 13:03:58 +01:00
|
|
|
GType item_type = item_view_class->item_type;
|
2007-06-02 11:45:54 +00:00
|
|
|
|
2020-03-24 22:06:28 +01:00
|
|
|
if (g_type_is_a (src_viewable_type, item_type))
|
|
|
|
item_type = G_TYPE_FROM_INSTANCE (src_viewable);
|
2009-08-05 18:57:08 +02:00
|
|
|
|
2020-03-24 22:06:28 +01:00
|
|
|
dest_index = gimp_item_tree_view_get_drop_index (item_view, dest_viewable,
|
|
|
|
drop_pos,
|
|
|
|
(GimpViewable **) &parent);
|
2005-01-15 03:24:42 +00:00
|
|
|
|
2020-03-24 22:06:28 +01:00
|
|
|
new_item = gimp_item_convert (GIMP_ITEM (src_viewable),
|
|
|
|
item_view->priv->image, item_type);
|
2009-08-05 18:57:08 +02:00
|
|
|
|
2020-03-24 22:06:28 +01:00
|
|
|
item_view_class->add_item (item_view->priv->image, new_item,
|
|
|
|
parent, dest_index, TRUE);
|
2003-03-19 15:17:13 +00:00
|
|
|
}
|
2020-03-27 17:18:17 +01:00
|
|
|
}
|
|
|
|
else if (dest_viewable)
|
|
|
|
{
|
|
|
|
gimp_image_undo_group_start (item_view->priv->image,
|
|
|
|
GIMP_UNDO_GROUP_IMAGE_ITEM_REORDER,
|
2025-02-27 20:19:27 +01:00
|
|
|
GIMP_ITEM_GET_CLASS (dropped_viewables->data)->reorder_desc);
|
2020-03-27 17:18:17 +01:00
|
|
|
|
2025-02-27 20:19:27 +01:00
|
|
|
for (iter = dropped_viewables; iter; iter = iter->next)
|
2020-03-24 22:06:28 +01:00
|
|
|
{
|
2020-03-27 17:18:17 +01:00
|
|
|
GimpViewable *src_viewable = iter->data;
|
|
|
|
GimpItem *src_parent;
|
|
|
|
GimpItem *dest_parent;
|
|
|
|
gint src_index;
|
|
|
|
gint dest_index;
|
2009-08-06 18:43:57 +02:00
|
|
|
|
2020-03-24 22:06:28 +01:00
|
|
|
src_parent = GIMP_ITEM (gimp_viewable_get_parent (src_viewable));
|
|
|
|
src_index = gimp_item_get_index (GIMP_ITEM (src_viewable));
|
|
|
|
|
|
|
|
dest_index = gimp_item_tree_view_get_drop_index (item_view, dest_viewable,
|
|
|
|
drop_pos,
|
|
|
|
(GimpViewable **) &dest_parent);
|
|
|
|
|
|
|
|
if (src_parent == dest_parent)
|
|
|
|
{
|
|
|
|
if (src_index < dest_index)
|
|
|
|
dest_index--;
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_image_reorder_item (item_view->priv->image,
|
|
|
|
GIMP_ITEM (src_viewable),
|
|
|
|
dest_parent,
|
|
|
|
dest_index,
|
|
|
|
TRUE, NULL);
|
|
|
|
}
|
2003-03-19 15:17:13 +00:00
|
|
|
}
|
|
|
|
|
2020-03-27 17:18:17 +01:00
|
|
|
gimp_image_undo_group_end (item_view->priv->image);
|
2008-12-25 11:31:51 +00:00
|
|
|
gimp_image_flush (item_view->priv->image);
|
2025-02-27 20:19:27 +01:00
|
|
|
|
|
|
|
g_list_free (dropped_viewables);
|
2003-03-19 15:17:13 +00:00
|
|
|
}
|
|
|
|
|
2001-03-11 17:24:47 +00:00
|
|
|
|
|
|
|
/* "New" functions */
|
|
|
|
|
2001-02-27 14:14:13 +00:00
|
|
|
static void
|
2003-03-16 11:14:29 +00:00
|
|
|
gimp_item_tree_view_new_dropped (GtkWidget *widget,
|
2004-12-31 14:36:30 +00:00
|
|
|
gint x,
|
|
|
|
gint y,
|
2002-02-25 17:58:50 +00:00
|
|
|
GimpViewable *viewable,
|
|
|
|
gpointer data)
|
2001-02-27 14:14:13 +00:00
|
|
|
{
|
2004-10-16 15:48:23 +00:00
|
|
|
GimpItemTreeViewClass *item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (data);
|
2010-03-02 17:54:29 +01:00
|
|
|
GimpContainerView *view = GIMP_CONTAINER_VIEW (data);
|
2001-02-27 14:14:13 +00:00
|
|
|
|
2010-03-02 17:54:29 +01:00
|
|
|
if (item_view_class->new_default_action &&
|
|
|
|
viewable && gimp_container_view_lookup (view, viewable))
|
2001-03-06 13:28:39 +00:00
|
|
|
{
|
2019-07-02 03:54:38 +02:00
|
|
|
GimpAction *action;
|
2001-03-06 13:28:39 +00:00
|
|
|
|
2011-04-09 19:51:51 +02:00
|
|
|
action = gimp_ui_manager_find_action (gimp_editor_get_ui_manager (GIMP_EDITOR (view)),
|
2004-12-08 13:52:28 +00:00
|
|
|
item_view_class->action_group,
|
|
|
|
item_view_class->new_default_action);
|
2003-02-17 13:33:29 +00:00
|
|
|
|
2004-10-16 17:29:42 +00:00
|
|
|
if (action)
|
2003-02-17 13:33:29 +00:00
|
|
|
{
|
2004-10-16 17:29:42 +00:00
|
|
|
g_object_set (action, "viewable", viewable, NULL);
|
2019-07-02 03:54:38 +02:00
|
|
|
gimp_action_activate (action);
|
2004-10-16 17:29:42 +00:00
|
|
|
g_object_set (action, "viewable", NULL, NULL);
|
2003-02-17 13:33:29 +00:00
|
|
|
}
|
2001-05-06 20:31:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-03-24 22:06:28 +01:00
|
|
|
static void
|
|
|
|
gimp_item_tree_view_new_list_dropped (GtkWidget *widget,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
GList *viewables,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
GimpItemTreeViewClass *item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (data);
|
|
|
|
GimpContainerView *view = GIMP_CONTAINER_VIEW (data);
|
|
|
|
GimpAction *action;
|
|
|
|
|
|
|
|
action = gimp_ui_manager_find_action (gimp_editor_get_ui_manager (GIMP_EDITOR (view)),
|
|
|
|
item_view_class->action_group,
|
|
|
|
item_view_class->new_default_action);
|
|
|
|
|
2020-04-20 01:56:23 +02:00
|
|
|
if (item_view_class->new_default_action && viewables && action &&
|
|
|
|
gimp_container_view_contains (view, viewables))
|
|
|
|
gimp_action_activate (action);
|
2020-03-24 22:06:28 +01:00
|
|
|
}
|
2001-03-11 17:24:47 +00:00
|
|
|
|
|
|
|
/* GimpImage callbacks */
|
|
|
|
|
2001-02-27 14:14:13 +00:00
|
|
|
static void
|
2006-03-28 17:08:36 +00:00
|
|
|
gimp_item_tree_view_item_changed (GimpImage *image,
|
2003-03-16 11:14:29 +00:00
|
|
|
GimpItemTreeView *view)
|
2001-02-27 14:14:13 +00:00
|
|
|
{
|
2020-03-26 00:33:11 +01:00
|
|
|
GList *items;
|
2001-02-27 14:14:13 +00:00
|
|
|
|
2020-03-26 00:33:11 +01:00
|
|
|
items = GIMP_ITEM_TREE_VIEW_GET_CLASS (view)->get_selected_items (view->priv->image);
|
2001-02-27 14:14:13 +00:00
|
|
|
|
2020-03-26 00:33:11 +01:00
|
|
|
gimp_container_view_select_items (GIMP_CONTAINER_VIEW (view), items);
|
2001-02-27 14:14:13 +00:00
|
|
|
}
|
2001-05-06 17:56:10 +00:00
|
|
|
|
|
|
|
static void
|
2006-03-28 17:08:36 +00:00
|
|
|
gimp_item_tree_view_size_changed (GimpImage *image,
|
2004-05-10 17:16:50 +00:00
|
|
|
GimpItemTreeView *tree_view)
|
2001-05-06 17:56:10 +00:00
|
|
|
{
|
2004-07-04 21:27:09 +00:00
|
|
|
GimpContainerView *view = GIMP_CONTAINER_VIEW (tree_view);
|
2006-01-17 10:08:50 +00:00
|
|
|
gint view_size;
|
2004-05-10 17:16:50 +00:00
|
|
|
gint border_width;
|
2001-05-06 17:56:10 +00:00
|
|
|
|
2006-01-17 10:08:50 +00:00
|
|
|
view_size = gimp_container_view_get_view_size (view, &border_width);
|
2001-05-06 17:56:10 +00:00
|
|
|
|
2006-01-17 10:08:50 +00:00
|
|
|
gimp_container_view_set_view_size (view, view_size, border_width);
|
2001-05-06 17:56:10 +00:00
|
|
|
}
|
2003-03-16 11:14:29 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_item_tree_view_name_edited (GtkCellRendererText *cell,
|
|
|
|
const gchar *path_str,
|
2004-12-10 21:07:28 +00:00
|
|
|
const gchar *new_name,
|
2003-03-16 11:14:29 +00:00
|
|
|
GimpItemTreeView *view)
|
|
|
|
{
|
2006-08-29 21:44:51 +00:00
|
|
|
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
|
2003-03-16 11:14:29 +00:00
|
|
|
GtkTreePath *path;
|
|
|
|
GtkTreeIter iter;
|
|
|
|
|
|
|
|
path = gtk_tree_path_new_from_string (path_str);
|
|
|
|
|
|
|
|
if (gtk_tree_model_get_iter (tree_view->model, &iter, path))
|
|
|
|
{
|
2004-08-25 22:31:44 +00:00
|
|
|
GimpViewRenderer *renderer;
|
|
|
|
GimpItem *item;
|
2004-12-10 21:07:28 +00:00
|
|
|
const gchar *old_name;
|
2007-12-12 13:57:11 +00:00
|
|
|
GError *error = NULL;
|
2003-03-16 11:14:29 +00:00
|
|
|
|
2022-11-02 01:25:43 +01:00
|
|
|
renderer = gimp_container_tree_store_get_renderer (GIMP_CONTAINER_TREE_STORE (tree_view->model),
|
|
|
|
&iter);
|
2003-03-16 11:14:29 +00:00
|
|
|
|
|
|
|
item = GIMP_ITEM (renderer->viewable);
|
|
|
|
|
2009-08-31 22:47:18 +02:00
|
|
|
old_name = gimp_object_get_name (item);
|
2004-12-10 21:07:28 +00:00
|
|
|
|
|
|
|
if (! old_name) old_name = "";
|
|
|
|
if (! new_name) new_name = "";
|
|
|
|
|
|
|
|
if (strcmp (old_name, new_name) &&
|
2007-12-12 13:57:11 +00:00
|
|
|
gimp_item_rename (item, new_name, &error))
|
2004-02-01 20:38:26 +00:00
|
|
|
{
|
|
|
|
gimp_image_flush (gimp_item_get_image (item));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gchar *name = gimp_viewable_get_description (renderer->viewable, NULL);
|
|
|
|
|
2009-07-25 17:38:03 +02:00
|
|
|
gtk_tree_store_set (GTK_TREE_STORE (tree_view->model), &iter,
|
2010-05-17 21:28:17 +02:00
|
|
|
GIMP_CONTAINER_TREE_STORE_COLUMN_NAME, name,
|
2004-02-01 20:38:26 +00:00
|
|
|
-1);
|
|
|
|
g_free (name);
|
2007-12-12 13:57:11 +00:00
|
|
|
|
2008-06-24 21:23:20 +00:00
|
|
|
if (error)
|
|
|
|
{
|
2008-12-25 11:31:51 +00:00
|
|
|
gimp_message_literal (view->priv->image->gimp, G_OBJECT (view),
|
2013-09-15 04:59:20 +12:00
|
|
|
GIMP_MESSAGE_WARNING,
|
|
|
|
error->message);
|
2008-06-24 21:23:20 +00:00
|
|
|
g_clear_error (&error);
|
|
|
|
}
|
2004-02-01 20:38:26 +00:00
|
|
|
}
|
2003-03-16 11:14:29 +00:00
|
|
|
|
|
|
|
g_object_unref (renderer);
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_tree_path_free (path);
|
|
|
|
}
|
2003-05-08 20:26:01 +00:00
|
|
|
|
|
|
|
|
2003-09-11 19:52:29 +00:00
|
|
|
/* "Visible" callbacks */
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_item_tree_view_visible_changed (GimpItem *item,
|
|
|
|
GimpItemTreeView *view)
|
|
|
|
{
|
2004-05-10 23:22:39 +00:00
|
|
|
GimpContainerView *container_view = GIMP_CONTAINER_VIEW (view);
|
|
|
|
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
|
|
|
|
GtkTreeIter *iter;
|
2004-05-10 17:16:50 +00:00
|
|
|
|
2004-05-10 23:22:39 +00:00
|
|
|
iter = gimp_container_view_lookup (container_view,
|
|
|
|
(GimpViewable *) item);
|
2003-09-11 19:52:29 +00:00
|
|
|
|
|
|
|
if (iter)
|
2011-09-23 23:45:10 +02:00
|
|
|
{
|
|
|
|
GimpContainer *children;
|
|
|
|
|
|
|
|
gtk_tree_store_set (GTK_TREE_STORE (tree_view->model), iter,
|
|
|
|
view->priv->model_column_visible,
|
|
|
|
gimp_item_get_visible (item),
|
|
|
|
view->priv->model_column_viewable,
|
|
|
|
gimp_item_get_visible (item) &&
|
|
|
|
! gimp_item_is_visible (item),
|
|
|
|
-1);
|
|
|
|
|
|
|
|
children = gimp_viewable_get_children (GIMP_VIEWABLE (item));
|
|
|
|
|
|
|
|
if (children)
|
|
|
|
gimp_container_foreach (children,
|
|
|
|
(GFunc) gimp_item_tree_view_visible_changed,
|
|
|
|
view);
|
|
|
|
}
|
2003-09-11 19:52:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_item_tree_view_eye_clicked (GtkCellRendererToggle *toggle,
|
|
|
|
gchar *path_str,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpItemTreeView *view)
|
|
|
|
{
|
2021-02-09 00:04:05 +01:00
|
|
|
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
|
|
|
|
GtkTreePath *path;
|
|
|
|
GtkTreeIter iter;
|
2003-11-14 17:35:51 +00:00
|
|
|
|
2021-02-09 00:04:05 +01:00
|
|
|
path = gtk_tree_path_new_from_string (path_str);
|
2011-10-12 11:13:41 +02:00
|
|
|
|
2021-02-09 00:04:05 +01:00
|
|
|
if (gtk_tree_model_get_iter (tree_view->model, &iter, path))
|
|
|
|
{
|
|
|
|
GimpContext *context;
|
|
|
|
GimpViewRenderer *renderer;
|
|
|
|
GimpItem *item;
|
|
|
|
GimpImage *image;
|
|
|
|
gboolean active;
|
2003-11-14 17:35:51 +00:00
|
|
|
|
2021-02-09 00:04:05 +01:00
|
|
|
context = gimp_container_view_get_context (GIMP_CONTAINER_VIEW (view));
|
2004-05-10 17:16:50 +00:00
|
|
|
|
2022-11-02 01:25:43 +01:00
|
|
|
renderer = gimp_container_tree_store_get_renderer (GIMP_CONTAINER_TREE_STORE (tree_view->model),
|
|
|
|
&iter);
|
2021-02-09 00:04:05 +01:00
|
|
|
g_object_get (toggle,
|
|
|
|
"active", &active,
|
|
|
|
NULL);
|
2003-11-14 17:35:51 +00:00
|
|
|
|
2021-02-09 00:04:05 +01:00
|
|
|
item = GIMP_ITEM (renderer->viewable);
|
|
|
|
g_object_unref (renderer);
|
|
|
|
|
|
|
|
image = gimp_item_get_image (item);
|
|
|
|
|
2021-02-11 18:08:19 +01:00
|
|
|
if ((state & GDK_SHIFT_MASK) ||
|
|
|
|
(state & GDK_MOD1_MASK))
|
2021-02-09 00:04:05 +01:00
|
|
|
{
|
2021-02-11 18:08:19 +01:00
|
|
|
gimp_item_toggle_exclusive_visible (item, (state & GDK_MOD1_MASK), context);
|
2021-02-09 00:04:05 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GimpUndo *undo;
|
|
|
|
gboolean push_undo = TRUE;
|
|
|
|
|
|
|
|
undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
|
|
|
|
GIMP_UNDO_ITEM_VISIBILITY);
|
|
|
|
|
|
|
|
if (undo && GIMP_ITEM_UNDO (undo)->item == item)
|
|
|
|
push_undo = FALSE;
|
|
|
|
|
2021-02-09 16:49:04 +01:00
|
|
|
if (! gimp_item_set_visible (item, ! active, push_undo))
|
|
|
|
gimp_item_tree_view_blink_lock (view, item);
|
2021-02-09 00:04:05 +01:00
|
|
|
|
|
|
|
if (!push_undo)
|
|
|
|
gimp_undo_refresh_preview (undo, context);
|
|
|
|
}
|
|
|
|
|
|
|
|
gimp_image_flush (image);
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_tree_path_free (path);
|
2003-11-14 17:35:51 +00:00
|
|
|
}
|
|
|
|
|
2021-02-09 00:04:05 +01:00
|
|
|
|
|
|
|
/* "Locked" callbacks */
|
|
|
|
|
2003-11-14 17:35:51 +00:00
|
|
|
static void
|
2021-02-09 00:04:05 +01:00
|
|
|
gimp_item_tree_view_lock_clicked (GtkCellRendererToggle *toggle,
|
|
|
|
gchar *path_str,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpItemTreeView *view)
|
2003-11-14 17:35:51 +00:00
|
|
|
{
|
2021-02-09 00:04:05 +01:00
|
|
|
GtkTreePath *path;
|
|
|
|
GtkTreeIter iter;
|
|
|
|
|
|
|
|
path = gtk_tree_path_new_from_string (path_str);
|
|
|
|
|
|
|
|
if (gtk_tree_model_get_iter (GIMP_CONTAINER_TREE_VIEW (view)->model,
|
|
|
|
&iter, path))
|
|
|
|
{
|
2022-11-02 01:25:43 +01:00
|
|
|
GimpViewRenderer *renderer;
|
|
|
|
GimpContainerTreeStore *store;
|
|
|
|
GimpItem *item;
|
|
|
|
GdkRectangle rect;
|
2021-02-09 00:04:05 +01:00
|
|
|
|
|
|
|
/* Update the lock state. */
|
2022-11-02 01:25:43 +01:00
|
|
|
store = GIMP_CONTAINER_TREE_STORE (GIMP_CONTAINER_TREE_VIEW (view)->model);
|
|
|
|
renderer = gimp_container_tree_store_get_renderer (store, &iter);
|
2021-02-09 00:04:05 +01:00
|
|
|
item = GIMP_ITEM (renderer->viewable);
|
|
|
|
g_object_unref (renderer);
|
2021-02-11 10:33:57 +01:00
|
|
|
gimp_item_tree_view_update_lock_box (view, item, path);
|
2021-02-09 00:04:05 +01:00
|
|
|
|
|
|
|
/* Change popover position. */
|
|
|
|
gtk_tree_view_get_cell_area (GIMP_CONTAINER_TREE_VIEW (view)->view, path,
|
|
|
|
gtk_tree_view_get_column (GIMP_CONTAINER_TREE_VIEW (view)->view, 1),
|
|
|
|
&rect);
|
2021-02-25 18:48:23 +01:00
|
|
|
gtk_tree_view_convert_bin_window_to_widget_coords (GIMP_CONTAINER_TREE_VIEW (view)->view,
|
|
|
|
rect.x, rect.y, &rect.x, &rect.y);
|
2021-02-09 00:04:05 +01:00
|
|
|
gtk_popover_set_pointing_to (GTK_POPOVER (view->priv->lock_popover), &rect);
|
|
|
|
|
2021-02-10 19:03:28 +01:00
|
|
|
gtk_widget_show (view->priv->lock_popover);
|
2021-02-09 00:04:05 +01:00
|
|
|
}
|
2003-11-14 17:35:51 +00:00
|
|
|
}
|
|
|
|
|
2023-06-19 14:54:21 +00:00
|
|
|
/* "Effects" callbacks */
|
|
|
|
static void
|
|
|
|
gimp_item_tree_view_effects_clicked (GtkCellRendererToggle *toggle,
|
|
|
|
gchar *path_str,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpItemTreeView *view)
|
|
|
|
{
|
|
|
|
GtkTreePath *path;
|
|
|
|
GtkTreeIter iter;
|
|
|
|
|
|
|
|
path = gtk_tree_path_new_from_string (path_str);
|
|
|
|
|
|
|
|
if (gtk_tree_model_get_iter (GIMP_CONTAINER_TREE_VIEW (view)->model,
|
|
|
|
&iter, path))
|
|
|
|
{
|
|
|
|
GimpViewRenderer *renderer;
|
|
|
|
GimpContainerTreeStore *store;
|
|
|
|
GimpItem *item;
|
|
|
|
GimpContainer *filters;
|
|
|
|
GdkRectangle rect;
|
|
|
|
GtkWidget *filter_view;
|
|
|
|
GList *filter_list;
|
|
|
|
GList *children;
|
|
|
|
gint n_children = 0;
|
|
|
|
gboolean visible = TRUE;
|
|
|
|
|
|
|
|
children = gtk_container_get_children (GTK_CONTAINER (view->priv->effects_box));
|
|
|
|
|
|
|
|
/* Update the filter state. */
|
|
|
|
store = GIMP_CONTAINER_TREE_STORE (GIMP_CONTAINER_TREE_VIEW (view)->model);
|
|
|
|
renderer = gimp_container_tree_store_get_renderer (store, &iter);
|
|
|
|
item = GIMP_ITEM (renderer->viewable);
|
|
|
|
g_object_unref (renderer);
|
|
|
|
|
|
|
|
/* Get filters */
|
|
|
|
if (children)
|
|
|
|
{
|
|
|
|
g_signal_handlers_disconnect_by_func (children->data,
|
|
|
|
gimp_item_tree_view_effects_filters_selected,
|
|
|
|
view);
|
|
|
|
g_signal_handlers_disconnect_by_func (children->data,
|
|
|
|
gimp_item_tree_view_effects_activate_filter,
|
|
|
|
view);
|
|
|
|
gtk_widget_destroy (children->data);
|
|
|
|
g_list_free (children);
|
|
|
|
}
|
|
|
|
|
|
|
|
view->priv->effects_drawable = GIMP_DRAWABLE (item);
|
|
|
|
filters = gimp_drawable_get_filters (GIMP_DRAWABLE (item));
|
|
|
|
for (filter_list = GIMP_LIST (filters)->queue->tail; filter_list;
|
|
|
|
filter_list = g_list_previous (filter_list))
|
|
|
|
{
|
|
|
|
if (GIMP_IS_DRAWABLE_FILTER (filter_list->data))
|
|
|
|
{
|
|
|
|
if (! gimp_filter_get_active (GIMP_FILTER (filter_list->data)))
|
|
|
|
visible = FALSE;
|
|
|
|
|
|
|
|
n_children++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-03 18:57:08 +00:00
|
|
|
/* Set the initial value for the effect visibility toggle */
|
2023-06-19 14:54:21 +00:00
|
|
|
g_signal_handlers_block_by_func (view->priv->effects_visible_button,
|
2024-02-08 14:03:55 +00:00
|
|
|
gimp_item_tree_view_effects_visible_all_toggled,
|
2023-06-19 14:54:21 +00:00
|
|
|
view);
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (view->priv->effects_visible_button),
|
|
|
|
visible);
|
|
|
|
g_signal_handlers_unblock_by_func (view->priv->effects_visible_button,
|
2024-02-08 14:03:55 +00:00
|
|
|
gimp_item_tree_view_effects_visible_all_toggled,
|
2023-06-19 14:54:21 +00:00
|
|
|
view);
|
|
|
|
|
|
|
|
/* Only show if we have at least one active filter */
|
|
|
|
if (n_children > 0)
|
|
|
|
{
|
2024-01-03 18:57:08 +00:00
|
|
|
GtkCellRenderer *renderer;
|
|
|
|
GtkTreeViewColumn *column;
|
|
|
|
GimpContainerTreeView *filter_tree_view = NULL;
|
2024-02-08 14:03:55 +00:00
|
|
|
GtkWidget *scrolled_window = NULL;
|
2025-01-23 12:36:58 +00:00
|
|
|
gboolean is_editing = FALSE;
|
2024-01-03 18:57:08 +00:00
|
|
|
|
2023-06-19 14:54:21 +00:00
|
|
|
filter_view = gimp_container_tree_view_new (filters,
|
|
|
|
gimp_container_view_get_context (GIMP_CONTAINER_VIEW (view)),
|
|
|
|
GIMP_VIEW_SIZE_SMALL, 0);
|
2024-01-03 18:57:08 +00:00
|
|
|
filter_tree_view = GIMP_CONTAINER_TREE_VIEW (filter_view);
|
|
|
|
|
|
|
|
/* Connect filter active signal */
|
|
|
|
if (view->priv->filters_active_changed_handler)
|
|
|
|
gimp_tree_handler_disconnect (view->priv->filters_active_changed_handler);
|
|
|
|
|
|
|
|
view->priv->filters_active_changed_handler =
|
|
|
|
gimp_tree_handler_connect (filters, "active-changed",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_filter_active_changed),
|
|
|
|
filter_view);
|
|
|
|
|
|
|
|
gimp_container_tree_store_columns_add (filter_tree_view->model_columns,
|
|
|
|
&filter_tree_view->n_model_columns,
|
|
|
|
G_TYPE_BOOLEAN);
|
|
|
|
|
|
|
|
/* Set up individual visibility toggles */
|
|
|
|
column = gtk_tree_view_column_new ();
|
|
|
|
renderer = gimp_cell_renderer_toggle_new (GIMP_ICON_VISIBLE);
|
|
|
|
gtk_cell_renderer_toggle_set_active (GTK_CELL_RENDERER_TOGGLE (renderer), TRUE);
|
|
|
|
gtk_tree_view_column_pack_end (column, renderer, FALSE);
|
|
|
|
gtk_tree_view_column_set_attributes (column, renderer,
|
|
|
|
"active",
|
|
|
|
COLUMN_EFFECTS_ACTIVE,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
gtk_tree_view_append_column (filter_tree_view->view,
|
|
|
|
column);
|
|
|
|
gtk_tree_view_move_column_after (filter_tree_view->view,
|
|
|
|
column, NULL);
|
|
|
|
gimp_container_tree_view_add_toggle_cell (filter_tree_view,
|
|
|
|
renderer);
|
|
|
|
|
|
|
|
g_signal_connect_object (renderer, "clicked",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_effects_visible_toggled),
|
|
|
|
filter_tree_view, 0);
|
|
|
|
|
|
|
|
/* Update filter visible icon */
|
|
|
|
for (filter_list = GIMP_LIST (filters)->queue->tail; filter_list;
|
|
|
|
filter_list = g_list_previous (filter_list))
|
|
|
|
{
|
|
|
|
if (GIMP_IS_DRAWABLE_FILTER (filter_list->data))
|
2025-01-23 12:36:58 +00:00
|
|
|
{
|
|
|
|
gboolean is_temporary;
|
|
|
|
|
|
|
|
gimp_item_tree_view_filter_active_changed (GIMP_FILTER (filter_list->data),
|
|
|
|
filter_tree_view);
|
|
|
|
|
|
|
|
g_object_get (filter_list->data,
|
|
|
|
"temporary", &is_temporary,
|
|
|
|
NULL);
|
|
|
|
if (is_temporary)
|
|
|
|
is_editing = TRUE;
|
|
|
|
}
|
2024-01-03 18:57:08 +00:00
|
|
|
}
|
|
|
|
|
2024-02-08 14:03:55 +00:00
|
|
|
g_signal_connect (filter_tree_view, "select-items",
|
2023-06-19 14:54:21 +00:00
|
|
|
G_CALLBACK (gimp_item_tree_view_effects_filters_selected),
|
|
|
|
view);
|
2024-01-03 18:57:08 +00:00
|
|
|
g_signal_connect_object (filter_tree_view,
|
2023-06-19 14:54:21 +00:00
|
|
|
"activate-item",
|
|
|
|
G_CALLBACK (gimp_item_tree_view_effects_activate_filter),
|
|
|
|
view, 0);
|
|
|
|
|
|
|
|
gtk_box_pack_start (GTK_BOX (view->priv->effects_box), filter_view, TRUE, TRUE, 0);
|
|
|
|
gtk_widget_set_visible (filter_view, TRUE);
|
|
|
|
|
2024-02-08 14:03:55 +00:00
|
|
|
scrolled_window = gtk_widget_get_parent (GTK_WIDGET (filter_tree_view->view));
|
|
|
|
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
|
|
|
|
GTK_POLICY_NEVER,
|
|
|
|
GTK_POLICY_NEVER);
|
|
|
|
gtk_widget_set_size_request (view->priv->effects_box, -1, 24 * (n_children + 1));
|
2023-06-19 14:54:21 +00:00
|
|
|
|
|
|
|
/* Change popover position. */
|
|
|
|
gtk_tree_view_get_cell_area (GIMP_CONTAINER_TREE_VIEW (view)->view, path,
|
|
|
|
gtk_tree_view_get_column (GIMP_CONTAINER_TREE_VIEW (view)->view, 2),
|
|
|
|
&rect);
|
|
|
|
gtk_tree_view_convert_bin_window_to_widget_coords (GIMP_CONTAINER_TREE_VIEW (view)->view,
|
|
|
|
rect.x, rect.y, &rect.x, &rect.y);
|
|
|
|
gtk_popover_set_pointing_to (GTK_POPOVER (view->priv->effects_popover), &rect);
|
|
|
|
|
|
|
|
gimp_item_tree_view_filters_changed (item, view);
|
|
|
|
gtk_widget_show (view->priv->effects_popover);
|
2025-01-23 12:36:58 +00:00
|
|
|
|
|
|
|
/* Lock filter options if we're actively editing a filter */
|
|
|
|
gimp_item_tree_effects_set_sensitive (view, ! is_editing);
|
2023-06-19 14:54:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gimp_item_tree_view_effects_filters_selected (GimpContainerView *view,
|
|
|
|
GList *filters,
|
|
|
|
GList *paths,
|
|
|
|
GimpItemTreeView *item_view)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (g_list_length (filters) <= 1, FALSE);
|
|
|
|
|
|
|
|
if (filters &&
|
|
|
|
item_view->priv->effects_drawable &&
|
|
|
|
GIMP_IS_DRAWABLE (item_view->priv->effects_drawable))
|
|
|
|
{
|
2025-02-12 05:18:53 +00:00
|
|
|
GimpDrawableFilter *filter;
|
2023-06-19 14:54:21 +00:00
|
|
|
GimpContainer *container;
|
2025-02-27 19:52:51 +01:00
|
|
|
gint index = -1;
|
|
|
|
gint n_children = 0;
|
2025-02-12 05:18:53 +00:00
|
|
|
gboolean is_blocked_op = FALSE;
|
2025-02-27 19:52:51 +01:00
|
|
|
GeglNode *op_node = NULL;
|
2023-06-19 14:54:21 +00:00
|
|
|
|
2025-02-12 05:18:53 +00:00
|
|
|
/* Don't set floating selection as active filter */
|
|
|
|
if (GIMP_IS_DRAWABLE_FILTER (filters->data))
|
|
|
|
{
|
|
|
|
filter = filters->data;
|
2023-06-19 14:54:21 +00:00
|
|
|
|
2025-02-12 05:18:53 +00:00
|
|
|
item_view->priv->effects_filter = filter;
|
2023-06-19 14:54:21 +00:00
|
|
|
|
2025-02-12 05:18:53 +00:00
|
|
|
container =
|
|
|
|
gimp_drawable_get_filters (GIMP_DRAWABLE (item_view->priv->effects_drawable));
|
2023-06-19 14:54:21 +00:00
|
|
|
|
2025-02-12 05:18:53 +00:00
|
|
|
index = gimp_container_get_child_index (container,
|
|
|
|
GIMP_OBJECT (filter));
|
2023-06-19 14:54:21 +00:00
|
|
|
|
2025-02-12 05:18:53 +00:00
|
|
|
n_children = gimp_container_get_n_children (container);
|
|
|
|
|
|
|
|
/* TODO: For now, prevent raising/lowering tool operations like Warp. */
|
|
|
|
op_node = gimp_drawable_filter_get_operation (filter);
|
|
|
|
if (op_node &&
|
|
|
|
! strcmp (gegl_node_get_operation (op_node), "GraphNode"))
|
|
|
|
is_blocked_op = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
is_blocked_op = TRUE;
|
|
|
|
}
|
2024-02-14 17:49:51 +00:00
|
|
|
|
2024-05-22 19:59:40 +00:00
|
|
|
gtk_widget_set_sensitive (item_view->priv->effects_remove_button,
|
2025-02-12 05:18:53 +00:00
|
|
|
! is_blocked_op);
|
2023-06-19 14:54:21 +00:00
|
|
|
gtk_widget_set_sensitive (item_view->priv->effects_raise_button,
|
2025-02-12 05:18:53 +00:00
|
|
|
(index != 0) && ! is_blocked_op);
|
2023-06-19 14:54:21 +00:00
|
|
|
gtk_widget_set_sensitive (item_view->priv->effects_lower_button,
|
2025-02-12 05:18:53 +00:00
|
|
|
(index != n_children - 1) && ! is_blocked_op);
|
2023-06-19 14:54:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_item_tree_view_effects_activate_filter (GtkWidget *widget,
|
|
|
|
GimpViewable *viewable,
|
|
|
|
gpointer insert_data,
|
|
|
|
GimpItemTreeView *view)
|
|
|
|
{
|
|
|
|
if (gtk_widget_get_sensitive (view->priv->effects_edit_button))
|
2025-05-28 22:15:41 +02:00
|
|
|
gimp_item_tree_view_effects_edit_clicked (widget, view);
|
2023-06-19 14:54:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2024-01-03 18:57:08 +00:00
|
|
|
gimp_item_tree_view_filter_active_changed (GimpFilter *filter,
|
|
|
|
GimpContainerTreeView *view)
|
|
|
|
{
|
|
|
|
GtkTreeIter *iter;
|
|
|
|
|
|
|
|
iter = gimp_container_view_lookup (GIMP_CONTAINER_VIEW (view),
|
|
|
|
(GimpViewable *) filter);
|
|
|
|
|
|
|
|
if (iter)
|
|
|
|
gtk_tree_store_set (GTK_TREE_STORE (view->model), iter,
|
|
|
|
COLUMN_EFFECTS_ACTIVE,
|
|
|
|
gimp_filter_get_active (filter),
|
|
|
|
-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_item_tree_view_effects_visible_toggled (GtkCellRendererToggle *toggle,
|
|
|
|
gchar *path_str,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpContainerTreeView *view)
|
|
|
|
{
|
|
|
|
GtkTreePath *path;
|
|
|
|
GtkTreeIter iter;
|
|
|
|
|
|
|
|
path = gtk_tree_path_new_from_string (path_str);
|
|
|
|
|
|
|
|
if (gtk_tree_model_get_iter (view->model, &iter, path))
|
|
|
|
{
|
|
|
|
GimpViewRenderer *renderer;
|
|
|
|
GimpContainerTreeStore *store;
|
|
|
|
GimpDrawableFilter *filter;
|
|
|
|
gboolean visible;
|
|
|
|
|
|
|
|
/* Update the filter state. */
|
|
|
|
store = GIMP_CONTAINER_TREE_STORE (view->model);
|
|
|
|
renderer = gimp_container_tree_store_get_renderer (store, &iter);
|
|
|
|
filter = GIMP_DRAWABLE_FILTER (renderer->viewable);
|
|
|
|
g_object_unref (renderer);
|
|
|
|
|
|
|
|
if (GIMP_IS_DRAWABLE_FILTER (filter))
|
|
|
|
{
|
2025-05-28 22:15:41 +02:00
|
|
|
GimpDrawable *drawable;
|
2024-01-03 18:57:08 +00:00
|
|
|
|
|
|
|
drawable = gimp_drawable_filter_get_drawable (filter);
|
|
|
|
|
|
|
|
if (drawable)
|
|
|
|
{
|
|
|
|
visible = gimp_filter_get_active (GIMP_FILTER (filter));
|
|
|
|
|
|
|
|
gimp_filter_set_active (GIMP_FILTER (filter), ! visible);
|
|
|
|
|
2025-05-28 15:36:59 +02:00
|
|
|
gimp_item_refresh_filters (GIMP_ITEM (drawable));
|
2024-01-03 18:57:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_item_tree_view_effects_visible_all_toggled (GtkWidget *widget,
|
|
|
|
GimpItemTreeView *view)
|
2023-06-19 14:54:21 +00:00
|
|
|
{
|
|
|
|
if (view->priv->effects_drawable)
|
|
|
|
{
|
|
|
|
gboolean visible;
|
|
|
|
GimpContainer *filter_stack;
|
|
|
|
GList *list;
|
|
|
|
|
|
|
|
visible = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
|
|
|
|
filter_stack = gimp_drawable_get_filters (GIMP_DRAWABLE (view->priv->effects_drawable));
|
|
|
|
|
|
|
|
for (list = GIMP_LIST (filter_stack)->queue->head; list;
|
|
|
|
list = g_list_next (list))
|
|
|
|
{
|
|
|
|
if (GIMP_IS_DRAWABLE_FILTER (list->data))
|
|
|
|
{
|
|
|
|
GimpFilter *filter = list->data;
|
|
|
|
|
|
|
|
gimp_filter_set_active (filter, visible);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-05-28 15:36:59 +02:00
|
|
|
gimp_item_refresh_filters (GIMP_ITEM (view->priv->effects_drawable));
|
2023-06-19 14:54:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2025-05-28 22:15:41 +02:00
|
|
|
gimp_item_tree_view_effects_edit_clicked (GtkWidget *widget,
|
|
|
|
GimpItemTreeView *view)
|
2023-06-19 14:54:21 +00:00
|
|
|
{
|
2024-12-19 17:42:43 +00:00
|
|
|
GimpImage *image = view->priv->image;
|
|
|
|
GimpDrawable *drawable;
|
|
|
|
GeglNode *op;
|
2024-01-03 18:57:08 +00:00
|
|
|
|
2024-12-19 17:42:43 +00:00
|
|
|
if (! view->priv->effects_filter ||
|
|
|
|
! GIMP_IS_DRAWABLE_FILTER (view->priv->effects_filter))
|
|
|
|
return;
|
2024-01-03 18:57:08 +00:00
|
|
|
|
2024-12-19 17:42:43 +00:00
|
|
|
drawable = gimp_drawable_filter_get_drawable (view->priv->effects_filter);
|
|
|
|
|
|
|
|
if (drawable && GIMP_IS_DRAWABLE (drawable))
|
2024-01-03 18:57:08 +00:00
|
|
|
{
|
2024-12-19 17:42:43 +00:00
|
|
|
if (! gimp_item_is_visible (GIMP_ITEM (drawable)) &&
|
2024-01-03 18:57:08 +00:00
|
|
|
! GIMP_GUI_CONFIG (image->gimp->config)->edit_non_visible)
|
|
|
|
{
|
|
|
|
gimp_message_literal (image->gimp, G_OBJECT (view),
|
|
|
|
GIMP_MESSAGE_ERROR,
|
|
|
|
_("A selected layer is not visible."));
|
2024-02-07 04:47:49 +00:00
|
|
|
return;
|
|
|
|
}
|
2024-12-19 17:42:43 +00:00
|
|
|
else if (gimp_item_get_lock_content (GIMP_ITEM (drawable)))
|
2024-02-07 04:47:49 +00:00
|
|
|
{
|
|
|
|
gimp_message_literal (view->priv->image->gimp, G_OBJECT (view),
|
|
|
|
GIMP_MESSAGE_WARNING,
|
|
|
|
_("A selected layer's pixels are locked."));
|
2024-01-03 18:57:08 +00:00
|
|
|
return;
|
|
|
|
}
|
2023-06-19 14:54:21 +00:00
|
|
|
|
2024-12-19 17:42:43 +00:00
|
|
|
op = gimp_drawable_filter_get_operation (view->priv->effects_filter);
|
2023-06-19 14:54:21 +00:00
|
|
|
if (op)
|
|
|
|
{
|
|
|
|
GimpProcedure *procedure;
|
|
|
|
GVariant *variant;
|
|
|
|
gchar *operation;
|
|
|
|
gchar *name;
|
|
|
|
|
|
|
|
g_object_get (view->priv->effects_filter,
|
|
|
|
"name", &name,
|
|
|
|
NULL);
|
|
|
|
g_object_get (op,
|
|
|
|
"operation", &operation,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (operation)
|
|
|
|
{
|
|
|
|
procedure = gimp_gegl_procedure_new (image->gimp,
|
|
|
|
view->priv->effects_filter,
|
|
|
|
GIMP_RUN_INTERACTIVE, NULL,
|
|
|
|
operation,
|
|
|
|
name,
|
|
|
|
name,
|
|
|
|
NULL, NULL, NULL);
|
|
|
|
|
|
|
|
variant = g_variant_new_uint64 (GPOINTER_TO_SIZE (procedure));
|
|
|
|
g_variant_take_ref (variant);
|
|
|
|
filters_run_procedure (image->gimp,
|
|
|
|
gimp_context_get_display (gimp_get_user_context (image->gimp)),
|
|
|
|
procedure, GIMP_RUN_INTERACTIVE);
|
|
|
|
|
|
|
|
g_variant_unref (variant);
|
|
|
|
g_object_unref (procedure);
|
|
|
|
|
|
|
|
/* Disable buttons until we're done editing */
|
2024-02-08 14:03:55 +00:00
|
|
|
gimp_item_tree_effects_set_sensitive (view, FALSE);
|
2023-06-19 14:54:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
g_free (name);
|
|
|
|
g_free (operation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2025-05-28 22:15:41 +02:00
|
|
|
gimp_item_tree_view_effects_raise_clicked (GtkWidget *widget,
|
|
|
|
GimpItemTreeView *view)
|
2023-06-19 14:54:21 +00:00
|
|
|
{
|
2025-05-29 13:18:40 +02:00
|
|
|
GimpImage *image = view->priv->image;
|
2024-03-26 16:58:34 +00:00
|
|
|
|
2025-05-29 13:18:40 +02:00
|
|
|
if (! GIMP_IS_DRAWABLE_FILTER (view->priv->effects_filter))
|
2023-06-19 14:54:21 +00:00
|
|
|
return;
|
|
|
|
|
2024-03-26 16:58:34 +00:00
|
|
|
if (gimp_drawable_filter_get_mask (view->priv->effects_filter) == NULL)
|
|
|
|
{
|
|
|
|
gimp_message_literal (image->gimp, G_OBJECT (view), GIMP_MESSAGE_ERROR,
|
|
|
|
_("Cannot reorder a filter that is being edited."));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2025-05-29 13:18:40 +02:00
|
|
|
if (gimp_drawable_raise_filter (view->priv->effects_drawable,
|
|
|
|
GIMP_FILTER (view->priv->effects_filter)))
|
2023-06-19 14:54:21 +00:00
|
|
|
{
|
2025-05-29 13:18:40 +02:00
|
|
|
if (gtk_widget_get_sensitive (view->priv->effects_edit_button))
|
2023-06-19 14:54:21 +00:00
|
|
|
{
|
2025-05-29 13:18:40 +02:00
|
|
|
GimpContainer *container;
|
|
|
|
gint index;
|
2023-06-19 14:54:21 +00:00
|
|
|
|
2025-05-29 13:18:40 +02:00
|
|
|
container =
|
|
|
|
gimp_drawable_get_filters (GIMP_DRAWABLE (view->priv->effects_drawable));
|
2023-06-19 14:54:21 +00:00
|
|
|
|
2025-05-29 13:18:40 +02:00
|
|
|
index = gimp_container_get_child_index (container,
|
|
|
|
GIMP_OBJECT (view->priv->effects_filter));
|
2023-06-19 14:54:21 +00:00
|
|
|
|
2025-05-29 13:18:40 +02:00
|
|
|
gtk_widget_set_sensitive (view->priv->effects_lower_button, TRUE);
|
|
|
|
if (index == 0)
|
|
|
|
gtk_widget_set_sensitive (view->priv->effects_raise_button, FALSE);
|
2023-06-19 14:54:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2025-05-28 22:15:41 +02:00
|
|
|
gimp_item_tree_view_effects_lower_clicked (GtkWidget *widget,
|
|
|
|
GimpItemTreeView *view)
|
2023-06-19 14:54:21 +00:00
|
|
|
{
|
2025-05-29 13:18:40 +02:00
|
|
|
GimpImage *image = view->priv->image;
|
2024-03-26 16:58:34 +00:00
|
|
|
|
2025-05-29 13:18:40 +02:00
|
|
|
if (! GIMP_IS_DRAWABLE_FILTER (view->priv->effects_filter))
|
2023-06-19 14:54:21 +00:00
|
|
|
return;
|
|
|
|
|
2024-03-26 16:58:34 +00:00
|
|
|
if (gimp_drawable_filter_get_mask (view->priv->effects_filter) == NULL)
|
|
|
|
{
|
|
|
|
gimp_message_literal (image->gimp, G_OBJECT (view), GIMP_MESSAGE_ERROR,
|
|
|
|
_("Cannot reorder a filter that is being edited."));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2025-05-29 13:18:40 +02:00
|
|
|
if (gimp_drawable_lower_filter (view->priv->effects_drawable,
|
|
|
|
GIMP_FILTER (view->priv->effects_filter)))
|
2023-06-19 14:54:21 +00:00
|
|
|
{
|
2025-05-29 13:18:40 +02:00
|
|
|
if (gtk_widget_get_sensitive (view->priv->effects_edit_button))
|
2023-06-19 14:54:21 +00:00
|
|
|
{
|
2025-05-29 13:18:40 +02:00
|
|
|
GimpContainer *container;
|
|
|
|
gint index;
|
2025-02-12 05:18:53 +00:00
|
|
|
|
2025-05-29 13:18:40 +02:00
|
|
|
container =
|
|
|
|
gimp_drawable_get_filters (GIMP_DRAWABLE (view->priv->effects_drawable));
|
2023-06-19 14:54:21 +00:00
|
|
|
|
2025-05-29 13:18:40 +02:00
|
|
|
index = gimp_container_get_child_index (container,
|
|
|
|
GIMP_OBJECT (view->priv->effects_filter));
|
2023-06-19 14:54:21 +00:00
|
|
|
|
2025-05-29 13:18:40 +02:00
|
|
|
gtk_widget_set_sensitive (view->priv->effects_raise_button, TRUE);
|
|
|
|
if (index == gimp_container_get_n_children (container) - 1)
|
|
|
|
gtk_widget_set_sensitive (view->priv->effects_lower_button, FALSE);
|
2023-06-19 14:54:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2025-05-28 22:15:41 +02:00
|
|
|
gimp_item_tree_view_effects_merge_clicked (GtkWidget *widget,
|
|
|
|
GimpItemTreeView *view)
|
2023-06-19 14:54:21 +00:00
|
|
|
{
|
2024-01-03 18:57:08 +00:00
|
|
|
GimpContext *context = NULL;
|
|
|
|
GimpToolInfo *active_tool = NULL;
|
|
|
|
|
2023-06-19 14:54:21 +00:00
|
|
|
if (! view->priv->effects_filter ||
|
|
|
|
! GIMP_IS_DRAWABLE_FILTER (view->priv->effects_filter))
|
|
|
|
return;
|
|
|
|
|
2025-01-26 03:15:09 +00:00
|
|
|
/* Commit GEGL-based tools before trying to merge filters */
|
2024-01-03 18:57:08 +00:00
|
|
|
context = gimp_container_view_get_context (GIMP_CONTAINER_VIEW (view));
|
|
|
|
active_tool = gimp_context_get_tool (context);
|
|
|
|
|
|
|
|
if (! strcmp (gimp_object_get_name (active_tool), "gimp-cage-tool") ||
|
|
|
|
! strcmp (gimp_object_get_name (active_tool), "gimp-gradient-tool") ||
|
|
|
|
! strcmp (gimp_object_get_name (active_tool), "gimp-warp-tool"))
|
|
|
|
{
|
2025-01-26 03:15:09 +00:00
|
|
|
tool_manager_control_active (context->gimp, GIMP_TOOL_ACTION_COMMIT,
|
|
|
|
gimp_context_get_display (context));
|
2024-01-03 18:57:08 +00:00
|
|
|
}
|
|
|
|
|
2024-02-27 20:10:50 +00:00
|
|
|
if (view->priv->effects_drawable &&
|
|
|
|
! gimp_viewable_get_children (GIMP_VIEWABLE (view->priv->effects_drawable)))
|
2023-06-19 14:54:21 +00:00
|
|
|
{
|
|
|
|
GimpImage *image = view->priv->image;
|
|
|
|
|
2024-02-06 18:20:36 +00:00
|
|
|
/* Don't merge if the layer is currently locked */
|
|
|
|
if (gimp_item_get_lock_content (GIMP_ITEM (view->priv->effects_drawable)))
|
|
|
|
{
|
2025-02-05 12:58:43 +00:00
|
|
|
gimp_message_literal (image->gimp, G_OBJECT (view),
|
2024-02-06 18:20:36 +00:00
|
|
|
GIMP_MESSAGE_WARNING,
|
|
|
|
_("The layer to merge down to is locked."));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2025-02-05 12:58:43 +00:00
|
|
|
gimp_drawable_merge_filters (GIMP_DRAWABLE (view->priv->effects_drawable));
|
|
|
|
gimp_drawable_clear_filters (GIMP_DRAWABLE (view->priv->effects_drawable));
|
2023-06-19 14:54:21 +00:00
|
|
|
|
2025-02-05 12:58:43 +00:00
|
|
|
view->priv->effects_filter = NULL;
|
2024-01-03 18:57:08 +00:00
|
|
|
|
2025-02-05 12:58:43 +00:00
|
|
|
/* Close NDE pop-over on successful merge */
|
|
|
|
gtk_widget_set_visible (view->priv->effects_popover, FALSE);
|
2024-02-15 18:30:12 +00:00
|
|
|
|
2025-05-28 15:36:59 +02:00
|
|
|
gimp_item_refresh_filters (GIMP_ITEM (view->priv->effects_drawable));
|
2023-06-19 14:54:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2025-05-28 22:15:41 +02:00
|
|
|
gimp_item_tree_view_effects_remove_clicked (GtkWidget *widget,
|
|
|
|
GimpItemTreeView *view)
|
2023-06-19 14:54:21 +00:00
|
|
|
{
|
|
|
|
if (view->priv->effects_drawable)
|
|
|
|
{
|
2024-06-12 13:44:21 +00:00
|
|
|
GimpImage *image = view->priv->image;
|
|
|
|
GimpContainer *filters = NULL;
|
2024-04-29 11:34:59 +00:00
|
|
|
|
2024-06-12 13:44:21 +00:00
|
|
|
filters = gimp_drawable_get_filters (view->priv->effects_drawable);
|
|
|
|
|
|
|
|
if (filters != NULL &&
|
|
|
|
gimp_container_have (filters, GIMP_OBJECT (view->priv->effects_filter)))
|
|
|
|
{
|
2023-06-19 14:54:21 +00:00
|
|
|
gimp_image_undo_push_filter_remove (image, _("Remove filter"),
|
|
|
|
view->priv->effects_drawable,
|
|
|
|
view->priv->effects_filter);
|
|
|
|
|
|
|
|
gimp_drawable_filter_abort (view->priv->effects_filter);
|
|
|
|
|
2024-04-29 11:34:59 +00:00
|
|
|
/* Toggle the popover off if all effects are deleted */
|
|
|
|
if (gimp_container_get_n_children (filters) == 0)
|
|
|
|
gtk_widget_set_visible (view->priv->effects_popover, FALSE);
|
2023-06-19 14:54:21 +00:00
|
|
|
}
|
|
|
|
|
2025-05-28 15:36:59 +02:00
|
|
|
gimp_item_refresh_filters (GIMP_ITEM (view->priv->effects_drawable));
|
2023-06-19 14:54:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-11-14 17:35:51 +00:00
|
|
|
|
2016-10-29 16:50:13 +02:00
|
|
|
/* "Color Tag" callbacks */
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_item_tree_view_color_tag_changed (GimpItem *item,
|
|
|
|
GimpItemTreeView *view)
|
|
|
|
{
|
|
|
|
GimpContainerView *container_view = GIMP_CONTAINER_VIEW (view);
|
|
|
|
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
|
|
|
|
GtkTreeIter *iter;
|
|
|
|
|
|
|
|
iter = gimp_container_view_lookup (container_view,
|
|
|
|
(GimpViewable *) item);
|
|
|
|
|
|
|
|
if (iter)
|
|
|
|
{
|
2017-12-07 16:42:54 -05:00
|
|
|
GimpContainer *children;
|
2024-04-02 04:00:50 +00:00
|
|
|
GeglColor *color = gegl_color_new ("none");
|
|
|
|
GdkRGBA rgba;
|
2017-12-07 16:42:54 -05:00
|
|
|
gboolean has_color;
|
|
|
|
|
|
|
|
has_color = gimp_get_color_tag_color (gimp_item_get_merged_color_tag (item),
|
2024-04-02 04:00:50 +00:00
|
|
|
color,
|
2017-12-07 16:42:54 -05:00
|
|
|
gimp_item_get_color_tag (item) ==
|
|
|
|
GIMP_COLOR_TAG_NONE);
|
2024-04-02 04:00:50 +00:00
|
|
|
gegl_color_get_pixel (color, babl_format ("R'G'B'A double"), &rgba);
|
|
|
|
g_object_unref (color);
|
2016-10-29 16:50:13 +02:00
|
|
|
|
|
|
|
gtk_tree_store_set (GTK_TREE_STORE (tree_view->model), iter,
|
|
|
|
view->priv->model_column_color_tag,
|
2024-04-02 04:00:50 +00:00
|
|
|
has_color ? &rgba : NULL,
|
2016-10-29 16:50:13 +02:00
|
|
|
-1);
|
2017-12-07 16:42:54 -05:00
|
|
|
|
|
|
|
children = gimp_viewable_get_children (GIMP_VIEWABLE (item));
|
|
|
|
|
|
|
|
if (children)
|
|
|
|
gimp_container_foreach (children,
|
|
|
|
(GFunc) gimp_item_tree_view_color_tag_changed,
|
|
|
|
view);
|
2016-10-29 16:50:13 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-08-19 21:29:34 +02:00
|
|
|
/* "Lock Content" callbacks */
|
|
|
|
|
|
|
|
static void
|
2021-02-09 00:04:05 +01:00
|
|
|
gimp_item_tree_view_lock_changed (GimpItem *item,
|
|
|
|
GimpItemTreeView *view)
|
2009-08-19 21:29:34 +02:00
|
|
|
{
|
2021-02-09 00:04:05 +01:00
|
|
|
GimpContainerView *container_view = GIMP_CONTAINER_VIEW (view);
|
|
|
|
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
|
|
|
|
GtkTreeIter *iter;
|
2021-02-25 18:40:42 +01:00
|
|
|
const gchar *icon_name;
|
2021-02-09 02:39:37 +01:00
|
|
|
gint n_locks;
|
2009-08-19 21:29:34 +02:00
|
|
|
|
2021-02-09 00:04:05 +01:00
|
|
|
iter = gimp_container_view_lookup (container_view,
|
|
|
|
(GimpViewable *) item);
|
2009-08-19 21:29:34 +02:00
|
|
|
|
2021-02-09 02:39:37 +01:00
|
|
|
n_locks = gimp_item_tree_view_get_n_locks (view, item, &icon_name);
|
2021-02-09 00:04:05 +01:00
|
|
|
|
|
|
|
if (iter)
|
|
|
|
gtk_tree_store_set (GTK_TREE_STORE (tree_view->model), iter,
|
|
|
|
|
|
|
|
view->priv->model_column_locked,
|
2021-02-09 02:39:37 +01:00
|
|
|
n_locks > 0,
|
2021-02-09 00:04:05 +01:00
|
|
|
|
|
|
|
view->priv->model_column_lock_icon,
|
|
|
|
icon_name,
|
|
|
|
|
|
|
|
-1);
|
|
|
|
|
|
|
|
if (view->priv->lock_box_item == item)
|
2021-02-11 10:33:57 +01:00
|
|
|
gimp_item_tree_view_update_lock_box (view, item, NULL);
|
2009-08-19 21:29:34 +02:00
|
|
|
}
|
|
|
|
|
2023-06-19 14:54:21 +00:00
|
|
|
static void
|
|
|
|
gimp_item_tree_view_filters_changed (GimpItem *item,
|
|
|
|
GimpItemTreeView *view)
|
|
|
|
{
|
|
|
|
GimpContainerView *container_view = GIMP_CONTAINER_VIEW (view);
|
|
|
|
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
|
|
|
|
GtkTreeIter *iter;
|
|
|
|
GimpContainer *filters;
|
|
|
|
GList *filter_list = NULL;
|
|
|
|
gint n_filters = 0;
|
|
|
|
gboolean fs_disabled = FALSE;
|
2025-04-19 17:38:16 +00:00
|
|
|
gboolean temporary_only = TRUE;
|
2023-06-19 14:54:21 +00:00
|
|
|
|
|
|
|
iter = gimp_container_view_lookup (container_view,
|
|
|
|
(GimpViewable *) item);
|
|
|
|
|
|
|
|
filters = gimp_drawable_get_filters (GIMP_DRAWABLE (item));
|
|
|
|
/* Since floating selections are also stored in the filter stack,
|
|
|
|
* we need to verify what's in there to get the correct count */
|
2024-02-02 11:33:00 +00:00
|
|
|
if (filters)
|
2023-06-19 14:54:21 +00:00
|
|
|
{
|
2024-02-02 11:33:00 +00:00
|
|
|
for (filter_list = GIMP_LIST (filters)->queue->tail; filter_list;
|
|
|
|
filter_list = g_list_previous (filter_list))
|
|
|
|
{
|
|
|
|
if (GIMP_IS_DRAWABLE_FILTER (filter_list->data))
|
2025-04-19 17:38:16 +00:00
|
|
|
{
|
|
|
|
n_filters++;
|
|
|
|
|
|
|
|
if (temporary_only)
|
|
|
|
g_object_get (filter_list->data,
|
|
|
|
"temporary", &temporary_only,
|
|
|
|
NULL);
|
|
|
|
}
|
2024-02-02 11:33:00 +00:00
|
|
|
else
|
2025-04-19 17:38:16 +00:00
|
|
|
{
|
|
|
|
fs_disabled = TRUE;
|
|
|
|
}
|
2024-02-02 11:33:00 +00:00
|
|
|
}
|
2023-06-19 14:54:21 +00:00
|
|
|
}
|
|
|
|
|
2025-04-19 17:38:16 +00:00
|
|
|
/* Don't show icon if we only have a temporary filter
|
|
|
|
* like a tool-based filter */
|
|
|
|
if (temporary_only)
|
|
|
|
n_filters = 0;
|
|
|
|
|
2024-02-02 11:33:00 +00:00
|
|
|
if (n_filters == 0 || fs_disabled)
|
2023-06-19 14:54:21 +00:00
|
|
|
view->priv->effects_filter = NULL;
|
|
|
|
|
|
|
|
if (iter)
|
|
|
|
gtk_tree_store_set (GTK_TREE_STORE (tree_view->model), iter,
|
|
|
|
view->priv->model_column_effects,
|
|
|
|
n_filters > 0,
|
|
|
|
-1);
|
|
|
|
|
|
|
|
/* Re-enable buttons after editing */
|
2024-02-08 14:03:55 +00:00
|
|
|
gimp_item_tree_effects_set_sensitive (view, ! fs_disabled);
|
2023-06-19 14:54:21 +00:00
|
|
|
|
|
|
|
if (view->priv->effects_popover &&
|
2024-02-08 14:03:55 +00:00
|
|
|
view->priv->effects_filter &&
|
2023-06-19 14:54:21 +00:00
|
|
|
! fs_disabled)
|
|
|
|
{
|
|
|
|
if (GIMP_IS_DRAWABLE_FILTER (view->priv->effects_filter))
|
|
|
|
{
|
|
|
|
gint index = gimp_container_get_child_index (filters,
|
|
|
|
GIMP_OBJECT (view->priv->effects_filter));
|
|
|
|
|
|
|
|
if (index == 0)
|
|
|
|
gtk_widget_set_sensitive (view->priv->effects_raise_button, FALSE);
|
|
|
|
else if (index == (n_filters - 1))
|
|
|
|
gtk_widget_set_sensitive (view->priv->effects_lower_button, FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-11 16:17:36 +01:00
|
|
|
static gboolean
|
|
|
|
gimp_item_tree_view_lock_button_release (GtkWidget *widget,
|
|
|
|
GdkEvent *event,
|
|
|
|
GimpItemTreeView *view)
|
|
|
|
{
|
|
|
|
GdkEventButton *bevent = (GdkEventButton *) event;
|
|
|
|
LockToggle *data;
|
|
|
|
GdkModifierType modifiers;
|
|
|
|
|
|
|
|
data = g_object_get_data (G_OBJECT (widget), "lock-data");
|
|
|
|
modifiers = bevent->state & gimp_get_all_modifiers_mask ();
|
|
|
|
|
2021-02-11 18:08:19 +01:00
|
|
|
if (modifiers == GDK_SHIFT_MASK ||
|
|
|
|
modifiers == GDK_MOD1_MASK)
|
2021-02-11 16:17:36 +01:00
|
|
|
gimp_item_toggle_exclusive (view->priv->lock_box_item,
|
|
|
|
data->is_locked,
|
|
|
|
data->lock,
|
|
|
|
data->can_lock,
|
|
|
|
NULL,
|
|
|
|
data->undo_push,
|
|
|
|
data->undo_exclusive_desc,
|
|
|
|
data->group_undo_type,
|
2021-02-11 18:08:19 +01:00
|
|
|
(modifiers == GDK_MOD1_MASK),
|
2021-02-11 16:17:36 +01:00
|
|
|
NULL);
|
|
|
|
else
|
|
|
|
return GDK_EVENT_PROPAGATE;
|
|
|
|
|
|
|
|
return GDK_EVENT_STOP;
|
|
|
|
}
|
|
|
|
|
2021-02-09 02:39:37 +01:00
|
|
|
static void
|
|
|
|
gimp_item_tree_view_lock_toggled (GtkWidget *widget,
|
|
|
|
GimpItemTreeView *view)
|
|
|
|
{
|
|
|
|
GimpImage *image = view->priv->image;
|
|
|
|
LockToggle *data;
|
|
|
|
GimpUndo *undo;
|
|
|
|
const gchar *undo_label;
|
|
|
|
gboolean push_undo = TRUE;
|
|
|
|
gboolean locked;
|
|
|
|
|
|
|
|
locked = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
|
|
|
|
data = g_object_get_data (G_OBJECT (widget), "lock-data");
|
|
|
|
|
|
|
|
if (! data->can_lock (view->priv->lock_box_item) ||
|
|
|
|
locked == data->is_locked (view->priv->lock_box_item))
|
|
|
|
return;
|
|
|
|
|
|
|
|
undo = gimp_image_undo_can_compress (image, GIMP_TYPE_ITEM_UNDO,
|
|
|
|
data->undo_type);
|
|
|
|
|
|
|
|
if (undo && GIMP_ITEM_UNDO (undo)->item == view->priv->lock_box_item)
|
|
|
|
push_undo = FALSE;
|
|
|
|
|
|
|
|
if (push_undo)
|
|
|
|
{
|
|
|
|
if (locked)
|
2021-02-11 16:17:36 +01:00
|
|
|
undo_label = data->undo_lock_desc;
|
2021-02-09 02:39:37 +01:00
|
|
|
else
|
2021-02-11 16:17:36 +01:00
|
|
|
undo_label = data->undo_unlock_desc;
|
2021-02-09 02:39:37 +01:00
|
|
|
|
|
|
|
gimp_image_undo_group_start (image, data->group_undo_type,
|
|
|
|
undo_label);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* TODO: maybe we should also have a modifier-interaction where we can
|
|
|
|
* lock all same-level items (Shift-click for instance like eye click)
|
|
|
|
* and maybe another modifier for all selected items at once.
|
|
|
|
*/
|
|
|
|
data->lock (view->priv->lock_box_item, locked, push_undo);
|
|
|
|
|
|
|
|
gimp_image_flush (image);
|
|
|
|
if (push_undo)
|
|
|
|
gimp_image_undo_group_end (image);
|
|
|
|
}
|
|
|
|
|
2010-07-20 23:36:16 +02:00
|
|
|
static gboolean
|
|
|
|
gimp_item_tree_view_item_pre_clicked (GimpCellRendererViewable *cell,
|
|
|
|
const gchar *path_str,
|
|
|
|
GdkModifierType state,
|
|
|
|
GimpItemTreeView *item_view)
|
|
|
|
{
|
|
|
|
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (item_view);
|
|
|
|
GtkTreePath *path;
|
|
|
|
GtkTreeIter iter;
|
2020-12-14 12:10:21 +01:00
|
|
|
GdkModifierType modifiers = (state & gimp_get_all_modifiers_mask ());
|
2020-12-14 00:37:24 +01:00
|
|
|
gboolean handled = FALSE;
|
2010-07-20 23:36:16 +02:00
|
|
|
|
|
|
|
path = gtk_tree_path_new_from_string (path_str);
|
|
|
|
|
2020-12-14 12:10:21 +01:00
|
|
|
/* Alt modifier at least and none other than Alt, Shift and Ctrl. */
|
|
|
|
if ((modifiers & GDK_MOD1_MASK) &&
|
|
|
|
! (modifiers & ~(GDK_MOD1_MASK | GDK_SHIFT_MASK | GDK_CONTROL_MASK)) &&
|
|
|
|
gtk_tree_model_get_iter (tree_view->model, &iter, path))
|
2010-07-20 23:36:16 +02:00
|
|
|
{
|
|
|
|
GimpImage *image = gimp_item_tree_view_get_image (item_view);
|
|
|
|
GimpViewRenderer *renderer = NULL;
|
|
|
|
|
2022-11-02 01:25:43 +01:00
|
|
|
renderer = gimp_container_tree_store_get_renderer (GIMP_CONTAINER_TREE_STORE (tree_view->model),
|
|
|
|
&iter);
|
2010-07-20 23:36:16 +02:00
|
|
|
|
|
|
|
if (renderer)
|
|
|
|
{
|
2011-10-05 19:19:14 +02:00
|
|
|
GimpItem *item = GIMP_ITEM (renderer->viewable);
|
2011-10-06 10:24:49 +02:00
|
|
|
GimpChannelOps op = gimp_modifiers_to_channel_op (state);
|
2010-07-20 23:36:16 +02:00
|
|
|
|
|
|
|
gimp_item_to_selection (item, op,
|
|
|
|
TRUE, FALSE, 0.0, 0.0);
|
|
|
|
gimp_image_flush (image);
|
|
|
|
|
|
|
|
g_object_unref (renderer);
|
|
|
|
|
|
|
|
/* Don't select the clicked layer */
|
|
|
|
handled = TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_tree_path_free (path);
|
|
|
|
|
|
|
|
return handled;
|
|
|
|
}
|
|
|
|
|
2009-08-19 21:29:34 +02:00
|
|
|
static void
|
2021-02-09 00:04:05 +01:00
|
|
|
gimp_item_tree_view_update_lock_box (GimpItemTreeView *view,
|
2021-02-11 10:33:57 +01:00
|
|
|
GimpItem *item,
|
|
|
|
GtkTreePath *path)
|
2009-08-19 21:29:34 +02:00
|
|
|
{
|
2021-02-09 13:12:35 +01:00
|
|
|
GList *list;
|
2009-08-19 21:29:34 +02:00
|
|
|
|
2021-02-09 13:12:35 +01:00
|
|
|
for (list = view->priv->locks; list; list = list->next)
|
2021-02-09 02:39:37 +01:00
|
|
|
{
|
|
|
|
LockToggle *data = list->data;
|
|
|
|
|
|
|
|
if (data->is_locked (item) !=
|
|
|
|
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (data->toggle)))
|
|
|
|
{
|
|
|
|
g_signal_handlers_block_by_func (data->toggle,
|
|
|
|
gimp_item_tree_view_lock_toggled,
|
|
|
|
view);
|
2021-02-11 16:17:36 +01:00
|
|
|
g_signal_handlers_block_by_func (data->toggle,
|
|
|
|
gimp_item_tree_view_lock_button_release,
|
|
|
|
view);
|
2021-02-09 02:39:37 +01:00
|
|
|
|
|
|
|
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (data->toggle),
|
|
|
|
data->is_locked (item));
|
|
|
|
|
|
|
|
g_signal_handlers_unblock_by_func (data->toggle,
|
|
|
|
gimp_item_tree_view_lock_toggled,
|
|
|
|
view);
|
2021-02-11 16:17:36 +01:00
|
|
|
g_signal_handlers_unblock_by_func (data->toggle,
|
|
|
|
gimp_item_tree_view_lock_button_release,
|
|
|
|
view);
|
2021-02-09 02:39:37 +01:00
|
|
|
}
|
|
|
|
gtk_widget_set_sensitive (data->toggle, data->can_lock (item));
|
|
|
|
}
|
2021-02-09 00:04:05 +01:00
|
|
|
view->priv->lock_box_item = item;
|
2021-02-11 10:33:57 +01:00
|
|
|
|
|
|
|
if (path)
|
|
|
|
{
|
|
|
|
if (view->priv->lock_box_path)
|
|
|
|
gtk_tree_path_free (view->priv->lock_box_path);
|
|
|
|
view->priv->lock_box_path = path;
|
|
|
|
}
|
2003-09-11 19:52:29 +00:00
|
|
|
}
|
2009-09-13 22:39:01 +02:00
|
|
|
|
2021-02-10 19:03:28 +01:00
|
|
|
static gboolean
|
|
|
|
gimp_item_tree_view_popover_button_press (GtkWidget *widget,
|
|
|
|
GdkEvent *event,
|
|
|
|
GimpItemTreeView *view)
|
|
|
|
{
|
|
|
|
GimpContainerTreeView *tree_view = GIMP_CONTAINER_TREE_VIEW (view);
|
|
|
|
GdkEventButton *bevent = (GdkEventButton *) event;
|
|
|
|
GdkEvent *new_event;
|
2021-02-11 10:33:57 +01:00
|
|
|
GtkTreeViewColumn *column;
|
|
|
|
GtkTreePath *path;
|
2021-02-10 19:03:28 +01:00
|
|
|
|
|
|
|
/* If we get to the popover signal handling, it means we didn't click
|
|
|
|
* inside popover's buttons, which would have stopped the signal
|
|
|
|
* first. So we were going to hide the popover anyway.
|
|
|
|
* Nevertheless I do with with gtk_widget_hide() instead of
|
|
|
|
* gtk_popover_popdown() because the animation stuff is very buggy
|
|
|
|
* (sometimes the popup stays displayed even though it doesn't react,
|
|
|
|
* blocking the GUI for a second or so).
|
|
|
|
* Moreover I directly retransfer the event as though it was sent to
|
|
|
|
* the item tree view. This allows much faster GUI interaction, not
|
|
|
|
* having to click twice, once to close the popup, then a second for
|
|
|
|
* the actual action (like eye switching or lock on another item or
|
|
|
|
* item selection).
|
|
|
|
*/
|
|
|
|
gtk_widget_hide (widget);
|
|
|
|
|
|
|
|
if (gtk_tree_view_get_path_at_pos (tree_view->view,
|
|
|
|
bevent->x, bevent->y,
|
2021-02-11 10:33:57 +01:00
|
|
|
&path, &column, NULL, NULL))
|
2021-02-10 19:03:28 +01:00
|
|
|
{
|
2021-02-11 10:33:57 +01:00
|
|
|
/* Clicking on the lock cell from the currently displayed lock box
|
|
|
|
* should only toggle-hide the lock box.
|
|
|
|
*/
|
|
|
|
if (gtk_tree_path_compare (path, view->priv->lock_box_path) != 0 ||
|
|
|
|
column != gtk_tree_view_get_column (GIMP_CONTAINER_TREE_VIEW (view)->view, 1))
|
|
|
|
{
|
2021-06-22 20:48:59 +02:00
|
|
|
/* Propagate the press event to the tree view. */
|
2021-02-11 10:33:57 +01:00
|
|
|
new_event = gdk_event_copy (event);
|
|
|
|
g_object_unref (new_event->any.window);
|
|
|
|
new_event->any.window = g_object_ref (gtk_widget_get_window (GTK_WIDGET (tree_view->view)));
|
|
|
|
new_event->any.send_event = TRUE;
|
2021-06-22 20:48:59 +02:00
|
|
|
gtk_main_do_event (new_event);
|
2021-02-10 19:03:28 +01:00
|
|
|
|
2021-06-22 20:48:59 +02:00
|
|
|
/* Also immediately pass a release event at same position.
|
|
|
|
* Without this, we get weird pointer as though a quick drag'n
|
|
|
|
* drop occured.
|
|
|
|
*/
|
|
|
|
new_event->type = GDK_BUTTON_RELEASE;
|
2021-02-11 10:33:57 +01:00
|
|
|
gtk_main_do_event (new_event);
|
|
|
|
|
|
|
|
gdk_event_free (new_event);
|
|
|
|
}
|
|
|
|
gtk_tree_path_free (path);
|
2021-02-10 19:03:28 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return GDK_EVENT_STOP;
|
|
|
|
}
|
|
|
|
|
2009-09-13 22:39:01 +02:00
|
|
|
|
|
|
|
/* GtkTreeView callbacks */
|
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_item_tree_view_row_expanded (GtkTreeView *tree_view,
|
|
|
|
GtkTreeIter *iter,
|
|
|
|
GtkTreePath *path,
|
|
|
|
GimpItemTreeView *item_view)
|
|
|
|
{
|
2021-06-10 17:44:08 +02:00
|
|
|
GimpItemTreeViewClass *item_view_class;
|
2021-06-11 22:01:35 +02:00
|
|
|
GList *selected_items;
|
|
|
|
GList *list;
|
2021-06-10 17:44:08 +02:00
|
|
|
|
|
|
|
item_view_class = GIMP_ITEM_TREE_VIEW_GET_CLASS (item_view);
|
2021-06-11 22:01:35 +02:00
|
|
|
selected_items = item_view_class->get_selected_items (item_view->priv->image);
|
2021-06-10 17:44:08 +02:00
|
|
|
|
2021-06-11 22:01:35 +02:00
|
|
|
if (selected_items)
|
2009-09-13 22:39:01 +02:00
|
|
|
{
|
2022-11-02 01:25:43 +01:00
|
|
|
GimpContainerTreeStore *store;
|
|
|
|
GimpViewRenderer *renderer;
|
|
|
|
GimpItem *expanded_item;
|
2009-09-13 22:39:01 +02:00
|
|
|
|
2022-11-02 01:25:43 +01:00
|
|
|
store = GIMP_CONTAINER_TREE_STORE (GIMP_CONTAINER_TREE_VIEW (item_view)->model);
|
|
|
|
renderer = gimp_container_tree_store_get_renderer (store, iter);
|
2012-02-09 20:38:46 +01:00
|
|
|
expanded_item = GIMP_ITEM (renderer->viewable);
|
|
|
|
g_object_unref (renderer);
|
|
|
|
|
2021-06-11 22:01:35 +02:00
|
|
|
for (list = selected_items; list; list = list->next)
|
2012-02-09 20:38:46 +01:00
|
|
|
{
|
2021-06-11 22:01:35 +02:00
|
|
|
/* don't select an item while it is being inserted */
|
|
|
|
if (! gimp_container_view_lookup (GIMP_CONTAINER_VIEW (item_view),
|
|
|
|
list->data))
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* select items only if they were made visible by expanding
|
|
|
|
* their immediate parent. See bug #666561.
|
|
|
|
*/
|
|
|
|
if (gimp_item_get_parent (list->data) != expanded_item)
|
|
|
|
return;
|
2012-02-09 20:38:46 +01:00
|
|
|
}
|
2021-06-11 22:01:35 +02:00
|
|
|
|
|
|
|
gimp_container_view_select_items (GIMP_CONTAINER_VIEW (item_view),
|
|
|
|
selected_items);
|
2009-09-13 22:39:01 +02:00
|
|
|
}
|
|
|
|
}
|
2021-02-09 02:39:37 +01:00
|
|
|
|
|
|
|
|
|
|
|
/* Helper functions. */
|
|
|
|
|
|
|
|
static gint
|
|
|
|
gimp_item_tree_view_get_n_locks (GimpItemTreeView *view,
|
|
|
|
GimpItem *item,
|
|
|
|
const gchar **icon_name)
|
|
|
|
{
|
2021-02-09 13:12:35 +01:00
|
|
|
GList *list;
|
|
|
|
gint n_locks = 0;
|
2021-02-09 02:39:37 +01:00
|
|
|
|
2021-03-09 11:08:00 +01:00
|
|
|
*icon_name = GIMP_ICON_LOCK_MULTI;
|
2021-02-09 02:39:37 +01:00
|
|
|
|
2021-02-09 13:12:35 +01:00
|
|
|
for (list = view->priv->locks; list; list = list->next)
|
2021-02-09 02:39:37 +01:00
|
|
|
{
|
|
|
|
LockToggle *data = list->data;
|
|
|
|
|
|
|
|
n_locks += (gint) data->is_locked (item);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (n_locks == 1)
|
|
|
|
{
|
2021-02-09 13:12:35 +01:00
|
|
|
for (list = view->priv->locks; list; list = list->next)
|
2021-02-09 02:39:37 +01:00
|
|
|
{
|
2021-02-09 13:12:35 +01:00
|
|
|
LockToggle *data = list->data;
|
2021-02-09 02:39:37 +01:00
|
|
|
|
2021-02-09 13:12:35 +01:00
|
|
|
if (data->is_locked (item))
|
|
|
|
{
|
|
|
|
*icon_name = data->icon_name;
|
|
|
|
break;
|
2021-02-09 02:39:37 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return n_locks;
|
|
|
|
}
|
2024-02-08 14:03:55 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
gimp_item_tree_effects_set_sensitive (GimpItemTreeView *view,
|
|
|
|
gboolean is_sensitive)
|
|
|
|
{
|
2024-02-27 20:10:50 +00:00
|
|
|
gboolean is_group = FALSE;
|
|
|
|
|
|
|
|
/* Do not allow merging down effects on group layers */
|
|
|
|
if (view->priv->effects_drawable &&
|
|
|
|
gimp_viewable_get_children (GIMP_VIEWABLE (view->priv->effects_drawable)))
|
|
|
|
is_group = TRUE;
|
|
|
|
|
2024-02-08 14:03:55 +00:00
|
|
|
gtk_widget_set_sensitive (view->priv->effects_box, is_sensitive);
|
|
|
|
gtk_widget_set_sensitive (view->priv->effects_visible_button, is_sensitive);
|
|
|
|
gtk_widget_set_sensitive (view->priv->effects_edit_button, is_sensitive);
|
|
|
|
gtk_widget_set_sensitive (view->priv->effects_raise_button, is_sensitive);
|
|
|
|
gtk_widget_set_sensitive (view->priv->effects_lower_button, is_sensitive);
|
2024-02-27 20:10:50 +00:00
|
|
|
gtk_widget_set_sensitive (view->priv->effects_merge_button,
|
|
|
|
(is_sensitive && ! is_group));
|
2024-02-08 14:03:55 +00:00
|
|
|
gtk_widget_set_sensitive (view->priv->effects_remove_button, is_sensitive);
|
|
|
|
}
|
2024-02-06 21:05:43 +01:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
}
|
2024-08-14 23:34:27 +02:00
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gimp_item_tree_view_move_cursor (GimpItemTreeView *view,
|
|
|
|
guint keyval,
|
|
|
|
GdkModifierType modifiers)
|
|
|
|
{
|
|
|
|
GimpItemTreeViewClass *klass;
|
|
|
|
const gchar *action_name = NULL;
|
|
|
|
|
|
|
|
g_return_val_if_fail (GIMP_IS_ITEM_TREE_VIEW (view), FALSE);
|
|
|
|
|
|
|
|
klass = GIMP_ITEM_TREE_VIEW_GET_CLASS (view);
|
|
|
|
switch (keyval)
|
|
|
|
{
|
|
|
|
case GDK_KEY_Down:
|
|
|
|
case GDK_KEY_KP_Down:
|
|
|
|
if (klass->move_cursor_down_flat_action)
|
|
|
|
action_name = klass->move_cursor_down_flat_action;
|
|
|
|
else
|
|
|
|
action_name = klass->move_cursor_down_action;
|
|
|
|
break;
|
|
|
|
case GDK_KEY_Up:
|
|
|
|
case GDK_KEY_KP_Up:
|
|
|
|
if (klass->move_cursor_up_flat_action)
|
|
|
|
action_name = klass->move_cursor_up_flat_action;
|
|
|
|
else
|
|
|
|
action_name = klass->move_cursor_up_action;
|
|
|
|
break;
|
|
|
|
case GDK_KEY_Page_Down:
|
|
|
|
case GDK_KEY_KP_Page_Down:
|
|
|
|
action_name = klass->move_cursor_down_action;
|
|
|
|
break;
|
|
|
|
case GDK_KEY_Page_Up:
|
|
|
|
case GDK_KEY_KP_Page_Up:
|
|
|
|
action_name = klass->move_cursor_up_action;
|
|
|
|
break;
|
|
|
|
case GDK_KEY_End:
|
|
|
|
case GDK_KEY_KP_End:
|
|
|
|
action_name = klass->move_cursor_end_action;
|
|
|
|
break;
|
|
|
|
case GDK_KEY_Home:
|
|
|
|
case GDK_KEY_KP_Home:
|
|
|
|
action_name = klass->move_cursor_start_action;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (action_name != NULL)
|
|
|
|
{
|
|
|
|
GAction *action;
|
|
|
|
|
|
|
|
action = g_action_map_lookup_action (G_ACTION_MAP (g_application_get_default ()),
|
|
|
|
action_name);
|
|
|
|
g_return_val_if_fail (action != NULL, FALSE);
|
|
|
|
|
|
|
|
gimp_action_activate (GIMP_ACTION (action));
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|