/* 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 . */ #include "config.h" #include #include #include #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; }