summaryrefslogtreecommitdiffstats
path: root/app/display/gimpdisplayshell-layer-select.c
diff options
context:
space:
mode:
Diffstat (limited to 'app/display/gimpdisplayshell-layer-select.c')
-rw-r--r--app/display/gimpdisplayshell-layer-select.c305
1 files changed, 305 insertions, 0 deletions
diff --git a/app/display/gimpdisplayshell-layer-select.c b/app/display/gimpdisplayshell-layer-select.c
new file mode 100644
index 0000000..0618eea
--- /dev/null
+++ b/app/display/gimpdisplayshell-layer-select.c
@@ -0,0 +1,305 @@
+/* GIMP - The GNU Image Manipulation Program
+ * Copyright (C) 1995 Spencer Kimball and Peter Mattis
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (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
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <gegl.h>
+#include <gtk/gtk.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "libgimpwidgets/gimpwidgets.h"
+
+#include "display-types.h"
+
+#include "config/gimpcoreconfig.h"
+
+#include "core/gimp.h"
+#include "core/gimpcontainer.h"
+#include "core/gimpimage.h"
+#include "core/gimplayer.h"
+
+#include "widgets/gimpview.h"
+#include "widgets/gimpviewrenderer.h"
+
+#include "gimpdisplay.h"
+#include "gimpdisplayshell.h"
+#include "gimpdisplayshell-layer-select.h"
+
+#include "gimp-intl.h"
+
+
+typedef struct
+{
+ GtkWidget *window;
+ GtkWidget *view;
+ GtkWidget *label;
+
+ GimpImage *image;
+ GimpLayer *orig_layer;
+} LayerSelect;
+
+
+/* local function prototypes */
+
+static LayerSelect * layer_select_new (GimpDisplayShell *shell,
+ GimpImage *image,
+ GimpLayer *layer,
+ gint view_size);
+static void layer_select_destroy (LayerSelect *layer_select,
+ guint32 time);
+static void layer_select_advance (LayerSelect *layer_select,
+ gint move);
+static gboolean layer_select_events (GtkWidget *widget,
+ GdkEvent *event,
+ LayerSelect *layer_select);
+
+
+/* public functions */
+
+void
+gimp_display_shell_layer_select_init (GimpDisplayShell *shell,
+ gint move,
+ guint32 time)
+{
+ LayerSelect *layer_select;
+ GimpImage *image;
+ GimpLayer *layer;
+ GdkGrabStatus status;
+
+ g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
+
+ image = gimp_display_get_image (shell->display);
+
+ layer = gimp_image_get_active_layer (image);
+
+ if (! layer)
+ return;
+
+ layer_select = layer_select_new (shell, image, layer,
+ image->gimp->config->layer_preview_size);
+ layer_select_advance (layer_select, move);
+
+ gtk_window_set_screen (GTK_WINDOW (layer_select->window),
+ gtk_widget_get_screen (GTK_WIDGET (shell)));
+
+ gtk_widget_show (layer_select->window);
+
+ status = gdk_keyboard_grab (gtk_widget_get_window (layer_select->window), FALSE, time);
+ if (status != GDK_GRAB_SUCCESS)
+ g_printerr ("gdk_keyboard_grab failed with status %d\n", status);
+}
+
+
+/* private functions */
+
+static LayerSelect *
+layer_select_new (GimpDisplayShell *shell,
+ GimpImage *image,
+ GimpLayer *layer,
+ gint view_size)
+{
+ LayerSelect *layer_select;
+ GtkWidget *frame1;
+ GtkWidget *frame2;
+ GtkWidget *hbox;
+ GtkWidget *alignment;
+
+ layer_select = g_slice_new0 (LayerSelect);
+
+ layer_select->image = image;
+ layer_select->orig_layer = layer;
+
+ layer_select->window = gtk_window_new (GTK_WINDOW_POPUP);
+ gtk_window_set_role (GTK_WINDOW (layer_select->window), "gimp-layer-select");
+ gtk_window_set_title (GTK_WINDOW (layer_select->window), _("Layer Select"));
+ gtk_window_set_position (GTK_WINDOW (layer_select->window), GTK_WIN_POS_MOUSE);
+ gtk_widget_set_events (layer_select->window,
+ GDK_KEY_PRESS_MASK |
+ GDK_KEY_RELEASE_MASK |
+ GDK_BUTTON_PRESS_MASK);
+
+ g_signal_connect (layer_select->window, "event",
+ G_CALLBACK (layer_select_events),
+ layer_select);
+
+ frame1 = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame1), GTK_SHADOW_OUT);
+ gtk_container_add (GTK_CONTAINER (layer_select->window), frame1);
+ gtk_widget_show (frame1);
+
+ frame2 = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (frame1), frame2);
+ gtk_widget_show (frame2);
+
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+ gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
+ gtk_container_add (GTK_CONTAINER (frame2), hbox);
+ gtk_widget_show (hbox);
+
+ /* The view */
+ alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
+ gtk_box_pack_start (GTK_BOX (hbox), alignment, FALSE, FALSE, 0);
+ gtk_widget_show (alignment);
+
+ layer_select->view =
+ gimp_view_new_by_types (gimp_get_user_context (image->gimp),
+ GIMP_TYPE_VIEW,
+ GIMP_TYPE_LAYER,
+ view_size, 1, FALSE);
+ gimp_view_renderer_set_color_config (GIMP_VIEW (layer_select->view)->renderer,
+ gimp_display_shell_get_color_config (shell));
+ gimp_view_set_viewable (GIMP_VIEW (layer_select->view),
+ GIMP_VIEWABLE (layer));
+ gtk_container_add (GTK_CONTAINER (alignment), layer_select->view);
+ gtk_widget_show (layer_select->view);
+ gtk_widget_show (alignment);
+
+ /* the layer name label */
+ layer_select->label = gtk_label_new (gimp_object_get_name (layer));
+ gtk_box_pack_start (GTK_BOX (hbox), layer_select->label, FALSE, FALSE, 0);
+ gtk_widget_show (layer_select->label);
+
+ return layer_select;
+}
+
+static void
+layer_select_destroy (LayerSelect *layer_select,
+ guint32 time)
+{
+ gdk_display_keyboard_ungrab (gtk_widget_get_display (layer_select->window),
+ time);
+
+ gtk_widget_destroy (layer_select->window);
+
+ if (layer_select->orig_layer !=
+ gimp_image_get_active_layer (layer_select->image))
+ {
+ gimp_image_flush (layer_select->image);
+ }
+
+ g_slice_free (LayerSelect, layer_select);
+}
+
+static void
+layer_select_advance (LayerSelect *layer_select,
+ gint move)
+{
+ GimpLayer *active_layer;
+ GimpLayer *next_layer;
+ GList *layers;
+ gint n_layers;
+ gint index;
+
+ if (move == 0)
+ return;
+
+ /* If there is a floating selection, allow no advancement */
+ if (gimp_image_get_floating_selection (layer_select->image))
+ return;
+
+ active_layer = gimp_image_get_active_layer (layer_select->image);
+
+ layers = gimp_image_get_layer_list (layer_select->image);
+ n_layers = g_list_length (layers);
+
+ index = g_list_index (layers, active_layer);
+ index += move;
+
+ if (index < 0)
+ index = n_layers - 1;
+ else if (index >= n_layers)
+ index = 0;
+
+ next_layer = g_list_nth_data (layers, index);
+
+ g_list_free (layers);
+
+ if (next_layer && next_layer != active_layer)
+ {
+ active_layer = gimp_image_set_active_layer (layer_select->image,
+ next_layer);
+
+ if (active_layer)
+ {
+ gimp_view_set_viewable (GIMP_VIEW (layer_select->view),
+ GIMP_VIEWABLE (active_layer));
+ gtk_label_set_text (GTK_LABEL (layer_select->label),
+ gimp_object_get_name (active_layer));
+ }
+ }
+}
+
+static gboolean
+layer_select_events (GtkWidget *widget,
+ GdkEvent *event,
+ LayerSelect *layer_select)
+{
+ GdkEventKey *kevent;
+ GdkEventButton *bevent;
+
+ switch (event->type)
+ {
+ case GDK_BUTTON_PRESS:
+ bevent = (GdkEventButton *) event;
+
+ layer_select_destroy (layer_select, bevent->time);
+ break;
+
+ case GDK_KEY_PRESS:
+ kevent = (GdkEventKey *) event;
+
+ switch (kevent->keyval)
+ {
+ case GDK_KEY_Tab:
+ layer_select_advance (layer_select, 1);
+ break;
+ case GDK_KEY_ISO_Left_Tab:
+ layer_select_advance (layer_select, -1);
+ break;
+ }
+ return TRUE;
+ break;
+
+ case GDK_KEY_RELEASE:
+ kevent = (GdkEventKey *) event;
+
+ switch (kevent->keyval)
+ {
+ case GDK_KEY_Alt_L: case GDK_KEY_Alt_R:
+ kevent->state &= ~GDK_MOD1_MASK;
+ break;
+ case GDK_KEY_Control_L: case GDK_KEY_Control_R:
+ kevent->state &= ~GDK_CONTROL_MASK;
+ break;
+ case GDK_KEY_Shift_L: case GDK_KEY_Shift_R:
+ kevent->state &= ~GDK_SHIFT_MASK;
+ break;
+ }
+
+ if (! (kevent->state & GDK_CONTROL_MASK))
+ layer_select_destroy (layer_select, kevent->time);
+
+ return TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ return FALSE;
+}