2006-12-10 05:33:38 +08:00
|
|
|
/* GIMP - The GNU Image Manipulation Program
|
1997-11-25 06:05:25 +08:00
|
|
|
* 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 2 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, write to the Free Software
|
1998-04-13 13:44:11 +08:00
|
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
1997-11-25 06:05:25 +08:00
|
|
|
*/
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2000-04-28 01:27:28 +08:00
|
|
|
#include "config.h"
|
|
|
|
|
2000-12-17 05:37:03 +08:00
|
|
|
#include <gtk/gtk.h>
|
2000-04-28 01:27:28 +08:00
|
|
|
#include <gdk/gdkkeysyms.h>
|
|
|
|
|
2001-11-09 03:14:51 +08:00
|
|
|
#include "display-types.h"
|
2000-12-17 05:37:03 +08:00
|
|
|
|
2002-11-19 04:50:31 +08:00
|
|
|
#include "config/gimpcoreconfig.h"
|
|
|
|
|
|
|
|
#include "core/gimp.h"
|
2001-11-09 03:14:51 +08:00
|
|
|
#include "core/gimpcontainer.h"
|
2001-05-09 10:32:03 +08:00
|
|
|
#include "core/gimpimage.h"
|
|
|
|
#include "core/gimplayer.h"
|
|
|
|
|
2004-08-25 01:16:46 +08:00
|
|
|
#include "widgets/gimpview.h"
|
2001-05-11 23:17:39 +08:00
|
|
|
|
2003-11-08 23:29:47 +08:00
|
|
|
#include "gimpdisplay.h"
|
|
|
|
#include "gimpdisplayshell.h"
|
2001-11-09 03:14:51 +08:00
|
|
|
#include "gimpdisplayshell-layer-select.h"
|
2001-04-21 00:27:44 +08:00
|
|
|
|
2003-03-26 00:38:19 +08:00
|
|
|
#include "gimp-intl.h"
|
1998-12-16 08:37:09 +08:00
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2007-05-23 18:22:09 +08:00
|
|
|
typedef struct
|
2000-04-28 01:27:28 +08:00
|
|
|
{
|
1997-11-25 06:05:25 +08:00
|
|
|
GtkWidget *shell;
|
2006-01-17 18:08:50 +08:00
|
|
|
GtkWidget *view;
|
2001-05-11 23:17:39 +08:00
|
|
|
GtkWidget *label;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image;
|
2003-09-11 01:00:35 +08:00
|
|
|
GimpLayer *orig_layer;
|
2007-05-23 18:22:09 +08:00
|
|
|
} LayerSelect;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-12-29 01:31:07 +08:00
|
|
|
|
2001-11-09 03:14:51 +08:00
|
|
|
/* local function prototypes */
|
2000-12-29 01:31:07 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
static LayerSelect * layer_select_new (GimpImage *image,
|
2003-08-18 00:58:39 +08:00
|
|
|
GimpLayer *layer,
|
2006-01-17 18:08:50 +08:00
|
|
|
gint view_size);
|
2003-08-18 00:58:39 +08:00
|
|
|
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);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
|
2001-11-09 03:14:51 +08:00
|
|
|
/* public functions */
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
void
|
2003-11-08 23:29:47 +08:00
|
|
|
gimp_display_shell_layer_select_init (GimpDisplayShell *shell,
|
|
|
|
gint move,
|
|
|
|
guint32 time)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2003-08-18 00:58:39 +08:00
|
|
|
LayerSelect *layer_select;
|
2006-03-29 01:08:36 +08:00
|
|
|
GimpImage *image;
|
2003-08-18 00:58:39 +08:00
|
|
|
GimpLayer *layer;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-11-08 23:29:47 +08:00
|
|
|
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
|
|
|
|
2006-03-29 01:55:52 +08:00
|
|
|
image = shell->display->image;
|
2001-11-09 03:14:51 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
layer = gimp_image_get_active_layer (image);
|
2001-05-11 23:17:39 +08:00
|
|
|
|
|
|
|
if (! layer)
|
|
|
|
return;
|
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
layer_select = layer_select_new (image, layer,
|
2008-04-14 14:50:55 +08:00
|
|
|
image->gimp->config->layer_preview_size);
|
2003-08-18 00:58:39 +08:00
|
|
|
layer_select_advance (layer_select, move);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-11-08 23:29:47 +08:00
|
|
|
gtk_window_set_screen (GTK_WINDOW (layer_select->shell),
|
|
|
|
gtk_widget_get_screen (GTK_WIDGET (shell)));
|
|
|
|
|
2003-08-18 00:58:39 +08:00
|
|
|
gtk_widget_show (layer_select->shell);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
gdk_keyboard_grab (layer_select->shell->window, FALSE, time);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-11-09 03:14:51 +08:00
|
|
|
/* private functions */
|
2000-12-29 01:31:07 +08:00
|
|
|
|
2003-08-18 00:58:39 +08:00
|
|
|
static LayerSelect *
|
2006-03-29 01:08:36 +08:00
|
|
|
layer_select_new (GimpImage *image,
|
2003-08-18 00:58:39 +08:00
|
|
|
GimpLayer *layer,
|
2006-01-17 18:08:50 +08:00
|
|
|
gint view_size)
|
2003-08-18 00:58:39 +08:00
|
|
|
{
|
|
|
|
LayerSelect *layer_select;
|
|
|
|
GtkWidget *frame1;
|
|
|
|
GtkWidget *frame2;
|
|
|
|
GtkWidget *hbox;
|
|
|
|
GtkWidget *alignment;
|
|
|
|
|
2007-05-23 18:22:09 +08:00
|
|
|
layer_select = g_slice_new0 (LayerSelect);
|
2003-08-18 00:58:39 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
layer_select->image = image;
|
2003-09-11 01:00:35 +08:00
|
|
|
layer_select->orig_layer = layer;
|
2003-08-18 00:58:39 +08:00
|
|
|
|
|
|
|
layer_select->shell = gtk_window_new (GTK_WINDOW_POPUP);
|
2003-11-08 01:29:02 +08:00
|
|
|
gtk_window_set_role (GTK_WINDOW (layer_select->shell), "gimp-layer-select");
|
2003-11-08 23:29:47 +08:00
|
|
|
gtk_window_set_title (GTK_WINDOW (layer_select->shell), _("Layer Select"));
|
|
|
|
gtk_window_set_position (GTK_WINDOW (layer_select->shell), GTK_WIN_POS_MOUSE);
|
2003-08-18 00:58:39 +08:00
|
|
|
gtk_widget_set_events (layer_select->shell, (GDK_KEY_PRESS_MASK |
|
|
|
|
GDK_KEY_RELEASE_MASK |
|
|
|
|
GDK_BUTTON_PRESS_MASK));
|
|
|
|
|
|
|
|
g_signal_connect (layer_select->shell, "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->shell), 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);
|
|
|
|
|
2004-05-26 21:39:23 +08:00
|
|
|
hbox = gtk_hbox_new (FALSE, 6);
|
|
|
|
gtk_container_set_border_width (GTK_CONTAINER (hbox), 6);
|
2003-08-18 00:58:39 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (frame2), hbox);
|
|
|
|
gtk_widget_show (hbox);
|
|
|
|
|
2006-01-17 18:08:50 +08:00
|
|
|
/* The view */
|
2003-08-18 00:58:39 +08:00
|
|
|
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);
|
|
|
|
|
2006-08-30 05:44:51 +08:00
|
|
|
layer_select->view =
|
|
|
|
gimp_view_new_by_types (gimp_get_user_context (image->gimp),
|
|
|
|
GIMP_TYPE_VIEW,
|
|
|
|
GIMP_TYPE_LAYER,
|
|
|
|
view_size, 1, FALSE);
|
2006-01-17 18:08:50 +08:00
|
|
|
gimp_view_set_viewable (GIMP_VIEW (layer_select->view),
|
2004-08-25 01:16:46 +08:00
|
|
|
GIMP_VIEWABLE (layer));
|
2006-01-17 18:08:50 +08:00
|
|
|
gtk_container_add (GTK_CONTAINER (alignment), layer_select->view);
|
|
|
|
gtk_widget_show (layer_select->view);
|
2003-08-18 00:58:39 +08:00
|
|
|
gtk_widget_show (alignment);
|
|
|
|
|
|
|
|
/* the layer name label */
|
|
|
|
layer_select->label = gtk_label_new (GIMP_OBJECT (layer)->name);
|
|
|
|
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)
|
|
|
|
{
|
2003-10-30 04:57:21 +08:00
|
|
|
gdk_display_keyboard_ungrab (gtk_widget_get_display (layer_select->shell),
|
|
|
|
time);
|
2003-08-18 00:58:39 +08:00
|
|
|
|
|
|
|
gtk_widget_destroy (layer_select->shell);
|
|
|
|
|
2003-09-11 01:00:35 +08:00
|
|
|
if (layer_select->orig_layer !=
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_image_get_active_layer (layer_select->image))
|
2003-08-18 00:58:39 +08:00
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_image_flush (layer_select->image);
|
2003-08-18 00:58:39 +08:00
|
|
|
}
|
|
|
|
|
2007-05-23 18:22:09 +08:00
|
|
|
g_slice_free (LayerSelect, layer_select);
|
2003-08-18 00:58:39 +08:00
|
|
|
}
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
static void
|
|
|
|
layer_select_advance (LayerSelect *layer_select,
|
2006-04-12 20:49:29 +08:00
|
|
|
gint move)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2003-09-11 01:00:35 +08:00
|
|
|
GimpLayer *current_layer;
|
|
|
|
GimpLayer *next_layer;
|
2001-11-09 03:14:51 +08:00
|
|
|
gint index;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-12-29 01:31:07 +08:00
|
|
|
if (move == 0)
|
|
|
|
return;
|
|
|
|
|
1997-11-25 06:05:25 +08:00
|
|
|
/* If there is a floating selection, allow no advancement */
|
2006-03-29 01:08:36 +08:00
|
|
|
if (gimp_image_floating_sel (layer_select->image))
|
1997-11-25 06:05:25 +08:00
|
|
|
return;
|
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
current_layer = gimp_image_get_active_layer (layer_select->image);
|
2003-09-11 01:00:35 +08:00
|
|
|
|
2006-03-29 01:08:36 +08:00
|
|
|
index = gimp_container_get_child_index (layer_select->image->layers,
|
2003-09-11 01:00:35 +08:00
|
|
|
GIMP_OBJECT (current_layer));
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2000-12-29 01:31:07 +08:00
|
|
|
index += move;
|
2003-08-18 00:58:39 +08:00
|
|
|
|
|
|
|
if (index < 0)
|
2006-03-29 01:08:36 +08:00
|
|
|
index = gimp_container_num_children (layer_select->image->layers) - 1;
|
|
|
|
else if (index >= gimp_container_num_children (layer_select->image->layers))
|
2003-08-18 00:58:39 +08:00
|
|
|
index = 0;
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-09-11 01:00:35 +08:00
|
|
|
next_layer = (GimpLayer *)
|
2006-03-29 01:08:36 +08:00
|
|
|
gimp_container_get_child_by_index (layer_select->image->layers, index);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-09-11 01:00:35 +08:00
|
|
|
if (next_layer && next_layer != current_layer)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2006-03-29 01:08:36 +08:00
|
|
|
current_layer = gimp_image_set_active_layer (layer_select->image,
|
don't allow to select anything but the floating selection. Fixes bug
2004-01-18 Michael Natterer <mitch@gimp.org>
* app/core/gimpimage.c (gimp_image_set_active_layer): don't allow
to select anything but the floating selection. Fixes bug #128025.
(gimp_image_set_active_layer,channel,vectors): allow to pass NULL
to unselect the active item. Removed the silly feature that
passing some random item of another image would select the first
item in the list (was unused anyway).
(gimp_image_unset_active_channel): use gimp_image_set_active_channel()
now that it accepts NULL.
(gimp_image_add_layer,channel,vectors): cleaned up / simplified.
(gimp_image_remove_layer,channel,vectors): cleanup,
simplification, use gimp_image_set_active_layer,channel,vectors()
now that they accept NULL, make sure the item next to the removed
item becomes the active one (and not the first in the list, which
was a severe usability problem in the dialogs).
* app/core/gimpimage-undo-push.c (undo_pop_layer,channel): pass
NULL to the set_active functions, cleanup.
* app/core/gimpimage-duplicate.c: attach the floating selection
before setting the active layer. Code relied on broken
gimp_image_set_active_layer() behaviour before.
* app/core/gimplayer-floating-sel.c: no need to set
gimage->floating_sel before calling gimp_image_add_layer(). The
weird GUI mentioned in the comment existed in 1.2 only.
* app/display/gimpdisplayshell-layer-select.c (layer_select_advance):
don't assume that setting the active_layer always succeeds.
* tools/pdbgen/pdb/image.pdb: behave as the documentation says
and return an execution error if setting the active layer or
channel failed.
Unrelated:
* tools/pdbgen/pdb/image.pdb
* tools/pdbgen/pdb/layer.pdb: removed leftover cruft from the old
guchar based color API.
* tools/pdbgen/pdb/channel.pdb: simplified code which handles the
channel's color.
* app/pdb/channel_cmds.c
* app/pdb/image_cmds.c: regenerated.
2004-01-18 20:16:44 +08:00
|
|
|
next_layer);
|
|
|
|
|
|
|
|
if (current_layer)
|
|
|
|
{
|
2006-01-17 18:08:50 +08:00
|
|
|
gimp_view_set_viewable (GIMP_VIEW (layer_select->view),
|
2004-08-25 01:16:46 +08:00
|
|
|
GIMP_VIEWABLE (current_layer));
|
don't allow to select anything but the floating selection. Fixes bug
2004-01-18 Michael Natterer <mitch@gimp.org>
* app/core/gimpimage.c (gimp_image_set_active_layer): don't allow
to select anything but the floating selection. Fixes bug #128025.
(gimp_image_set_active_layer,channel,vectors): allow to pass NULL
to unselect the active item. Removed the silly feature that
passing some random item of another image would select the first
item in the list (was unused anyway).
(gimp_image_unset_active_channel): use gimp_image_set_active_channel()
now that it accepts NULL.
(gimp_image_add_layer,channel,vectors): cleaned up / simplified.
(gimp_image_remove_layer,channel,vectors): cleanup,
simplification, use gimp_image_set_active_layer,channel,vectors()
now that they accept NULL, make sure the item next to the removed
item becomes the active one (and not the first in the list, which
was a severe usability problem in the dialogs).
* app/core/gimpimage-undo-push.c (undo_pop_layer,channel): pass
NULL to the set_active functions, cleanup.
* app/core/gimpimage-duplicate.c: attach the floating selection
before setting the active layer. Code relied on broken
gimp_image_set_active_layer() behaviour before.
* app/core/gimplayer-floating-sel.c: no need to set
gimage->floating_sel before calling gimp_image_add_layer(). The
weird GUI mentioned in the comment existed in 1.2 only.
* app/display/gimpdisplayshell-layer-select.c (layer_select_advance):
don't assume that setting the active_layer always succeeds.
* tools/pdbgen/pdb/image.pdb: behave as the documentation says
and return an execution error if setting the active layer or
channel failed.
Unrelated:
* tools/pdbgen/pdb/image.pdb
* tools/pdbgen/pdb/layer.pdb: removed leftover cruft from the old
guchar based color API.
* tools/pdbgen/pdb/channel.pdb: simplified code which handles the
channel's color.
* app/pdb/channel_cmds.c
* app/pdb/image_cmds.c: regenerated.
2004-01-18 20:16:44 +08:00
|
|
|
gtk_label_set_text (GTK_LABEL (layer_select->label),
|
|
|
|
GIMP_OBJECT (current_layer)->name);
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-08-18 00:58:39 +08:00
|
|
|
static gboolean
|
|
|
|
layer_select_events (GtkWidget *widget,
|
2006-04-12 20:49:29 +08:00
|
|
|
GdkEvent *event,
|
2003-08-18 00:58:39 +08:00
|
|
|
LayerSelect *layer_select)
|
1997-11-25 06:05:25 +08:00
|
|
|
{
|
2000-12-11 11:33:25 +08:00
|
|
|
GdkEventKey *kevent;
|
1997-11-25 06:05:25 +08:00
|
|
|
GdkEventButton *bevent;
|
|
|
|
|
|
|
|
switch (event->type)
|
|
|
|
{
|
|
|
|
case GDK_BUTTON_PRESS:
|
|
|
|
bevent = (GdkEventButton *) event;
|
2003-08-18 00:58:39 +08:00
|
|
|
|
|
|
|
layer_select_destroy (layer_select, bevent->time);
|
1997-11-25 06:05:25 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GDK_KEY_PRESS:
|
|
|
|
kevent = (GdkEventKey *) event;
|
|
|
|
|
|
|
|
switch (kevent->keyval)
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
case GDK_Tab:
|
2003-08-18 00:58:39 +08:00
|
|
|
layer_select_advance (layer_select, 1);
|
|
|
|
break;
|
2006-04-12 20:49:29 +08:00
|
|
|
case GDK_ISO_Left_Tab:
|
2003-08-18 00:58:39 +08:00
|
|
|
layer_select_advance (layer_select, -1);
|
2006-04-12 20:49:29 +08:00
|
|
|
break;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GDK_KEY_RELEASE:
|
|
|
|
kevent = (GdkEventKey *) event;
|
|
|
|
|
|
|
|
switch (kevent->keyval)
|
2006-04-12 20:49:29 +08:00
|
|
|
{
|
|
|
|
case GDK_Alt_L: case GDK_Alt_R:
|
|
|
|
kevent->state &= ~GDK_MOD1_MASK;
|
|
|
|
break;
|
|
|
|
case GDK_Control_L: case GDK_Control_R:
|
|
|
|
kevent->state &= ~GDK_CONTROL_MASK;
|
|
|
|
break;
|
|
|
|
case GDK_Shift_L: case GDK_Shift_R:
|
|
|
|
kevent->state &= ~GDK_SHIFT_MASK;
|
|
|
|
break;
|
|
|
|
}
|
1997-11-25 06:05:25 +08:00
|
|
|
|
2003-08-18 00:58:39 +08:00
|
|
|
if (! (kevent->state & GDK_CONTROL_MASK))
|
2006-04-12 20:49:29 +08:00
|
|
|
layer_select_destroy (layer_select, kevent->time);
|
1997-11-25 06:05:25 +08:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|