mirror of
https://gitlab.gnome.org/GNOME/gimp
synced 2024-10-22 12:32:37 +00:00
2fd2a4e6b5
2001-02-25 Michael Natterer <mitch@gimp.org> * app/channel_ops.c * app/channels_dialog.c * app/commands.c * app/floating_sel.c * app/gdisplay.c * app/gimpimage.[ch] * app/layer_select.c * app/layers_dialog.c * app/undo.c * app/xcf.c * app/tools/move.c: remove direct access of gimage->active_layer and gimage->active_channel. Reading access is of course harmless, but gimp_image_set_active_blah() will trigger a signal emission soon. It will probably be neccessary to change the functions to accept NULL layers and channels to acheive exactly what weird places like floating_sel.c did before by setting it directly. * gimptool-1.4.in * libgimp/Makefile.am * libgimpcolor/Makefile.am * libgimpmath/Makefile.am * libgimpwidgets/Makefile.am * plug-ins/libgck/gck/Makefile.am: made linking against stable GIMP installed in the same prefix work again by renaming all our libraries explicitly to libgimp<foo>-1.3.* (not as part of the libtool revision but as part of the library name). Removed the libtool revision to avoid double versioning. This has to be hardcoded in the libraries' Makefile.am ... * app/Makefile.am * plug-ins/FractalExplorer/Makefile.am * plug-ins/Lighting/Makefile.am * plug-ins/MapObject/Makefile.am * plug-ins/bmp/Makefile.am * plug-ins/common/Makefile.am * plug-ins/common/mkgen.pl * plug-ins/dbbrowser/Makefile.am * plug-ins/faxg3/Makefile.am * plug-ins/fits/Makefile.am * plug-ins/flame/Makefile.am * plug-ins/fp/Makefile.am * plug-ins/gap/Makefile.am * plug-ins/gdyntext/Makefile.am * plug-ins/gfig/Makefile.am * plug-ins/gflare/Makefile.am * plug-ins/gfli/Makefile.am * plug-ins/gimpressionist/Makefile.am * plug-ins/helpbrowser/Makefile.am * plug-ins/ifscompose/Makefile.am * plug-ins/imagemap/Makefile.am * plug-ins/maze/Makefile.am * plug-ins/mosaic/Makefile.am * plug-ins/pagecurl/Makefile.am * plug-ins/plugin-helper/Makefile.am * plug-ins/print/Makefile.am * plug-ins/rcm/Makefile.am * plug-ins/script-fu/Makefile.am * plug-ins/sel2path/Makefile.am * plug-ins/sgi/Makefile.am * plug-ins/webbrowser/Makefile.am * plug-ins/xjt/Makefile.am: ... while all other Makefiles can simply link against "libgimp<foo>-$(LT_REVISION).la"
483 lines
13 KiB
C
483 lines
13 KiB
C
/* The GIMP -- an 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 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
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include "config.h"
|
|
|
|
#include <gtk/gtk.h>
|
|
#include <gdk/gdkkeysyms.h>
|
|
|
|
#include "apptypes.h"
|
|
|
|
#include "gdisplay.h"
|
|
#include "gimpdrawable.h"
|
|
#include "gimpimage.h"
|
|
#include "gimplayer.h"
|
|
#include "gimprc.h"
|
|
#include "layer_select.h"
|
|
#include "layers_dialogP.h"
|
|
#include "temp_buf.h"
|
|
|
|
#include "libgimp/gimpintl.h"
|
|
|
|
|
|
#define PREVIEW_EVENT_MASK GDK_EXPOSURE_MASK | GDK_ENTER_NOTIFY_MASK
|
|
|
|
|
|
typedef struct _LayerSelect LayerSelect;
|
|
|
|
struct _LayerSelect
|
|
{
|
|
GtkWidget *shell;
|
|
GtkWidget *layer_preview;
|
|
GtkWidget *label;
|
|
GdkPixmap *layer_pixmap;
|
|
GtkWidget *preview;
|
|
|
|
GImage *gimage;
|
|
GimpLayer *current_layer;
|
|
gboolean dirty;
|
|
gint image_width;
|
|
gint image_height;
|
|
gdouble ratio;
|
|
};
|
|
|
|
|
|
/* layer widget function prototypes */
|
|
static void layer_select_advance (LayerSelect *layer_select,
|
|
gint move);
|
|
static void layer_select_forward (LayerSelect *layer_select);
|
|
static void layer_select_backward (LayerSelect *layer_select);
|
|
static void layer_select_end (LayerSelect *layer_select,
|
|
guint32 time);
|
|
static void layer_select_set_gimage (LayerSelect *layer_select,
|
|
GImage *gimage);
|
|
static void layer_select_set_layer (LayerSelect *layer_select);
|
|
static gint layer_select_events (GtkWidget *widget,
|
|
GdkEvent *event);
|
|
static gint preview_events (GtkWidget *widget,
|
|
GdkEvent *event);
|
|
static void preview_redraw (LayerSelect *layer_select);
|
|
|
|
|
|
/*
|
|
* Local variables
|
|
*/
|
|
LayerSelect *layer_select = NULL;
|
|
|
|
|
|
/**********************/
|
|
/* Public functions */
|
|
/**********************/
|
|
|
|
|
|
void
|
|
layer_select_init (GImage *gimage,
|
|
gint move,
|
|
guint32 time)
|
|
{
|
|
GtkWidget *frame1;
|
|
GtkWidget *frame2;
|
|
GtkWidget *hbox;
|
|
GtkWidget *alignment;
|
|
|
|
if (!layer_select)
|
|
{
|
|
layer_select = g_malloc (sizeof (LayerSelect));
|
|
layer_select->layer_pixmap = NULL;
|
|
layer_select->layer_preview = NULL;
|
|
layer_select->preview = NULL;
|
|
layer_select->image_width = layer_select->image_height = 0;
|
|
layer_select_set_gimage (layer_select, gimage);
|
|
layer_select_advance (layer_select, move);
|
|
|
|
if (preview_size)
|
|
{
|
|
layer_select->preview = gtk_preview_new (GTK_PREVIEW_COLOR);
|
|
gtk_preview_size (GTK_PREVIEW (layer_select->preview),
|
|
preview_size, preview_size);
|
|
}
|
|
|
|
/* The shell and main vbox */
|
|
layer_select->shell = gtk_window_new (GTK_WINDOW_POPUP);
|
|
gtk_window_set_wmclass (GTK_WINDOW (layer_select->shell),
|
|
"layer_select", "Gimp");
|
|
gtk_window_set_title (GTK_WINDOW (layer_select->shell),
|
|
_("Layer Select"));
|
|
gtk_window_set_position (GTK_WINDOW (layer_select->shell),
|
|
GTK_WIN_POS_MOUSE);
|
|
gtk_signal_connect (GTK_OBJECT (layer_select->shell), "event",
|
|
(GtkSignalFunc) layer_select_events,
|
|
layer_select);
|
|
gtk_widget_set_events (layer_select->shell, (GDK_KEY_PRESS_MASK |
|
|
GDK_KEY_RELEASE_MASK |
|
|
GDK_BUTTON_PRESS_MASK));
|
|
|
|
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);
|
|
frame2 = gtk_frame_new (NULL);
|
|
gtk_frame_set_shadow_type (GTK_FRAME (frame2), GTK_SHADOW_IN);
|
|
gtk_container_add (GTK_CONTAINER (frame1), frame2);
|
|
|
|
hbox = gtk_hbox_new (FALSE, 1);
|
|
gtk_container_add (GTK_CONTAINER (frame2), hbox);
|
|
|
|
/* The preview */
|
|
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->layer_preview = gtk_drawing_area_new ();
|
|
gtk_drawing_area_size (GTK_DRAWING_AREA (layer_select->layer_preview),
|
|
layer_select->image_width,
|
|
layer_select->image_height);
|
|
gtk_widget_set_events (layer_select->layer_preview, PREVIEW_EVENT_MASK);
|
|
gtk_signal_connect (GTK_OBJECT (layer_select->layer_preview), "event",
|
|
(GtkSignalFunc) preview_events, layer_select);
|
|
gtk_object_set_user_data (GTK_OBJECT (layer_select->layer_preview),
|
|
layer_select);
|
|
gtk_container_add (GTK_CONTAINER (alignment),
|
|
layer_select->layer_preview);
|
|
gtk_widget_show (layer_select->layer_preview);
|
|
gtk_widget_show (alignment);
|
|
|
|
/* the layer name label */
|
|
layer_select->label = gtk_label_new (_("Layer"));
|
|
gtk_box_pack_start (GTK_BOX (hbox),
|
|
layer_select->label, FALSE, FALSE, 2);
|
|
gtk_widget_show (layer_select->label);
|
|
|
|
gtk_widget_show (hbox);
|
|
gtk_widget_show (frame1);
|
|
gtk_widget_show (frame2);
|
|
gtk_widget_show (layer_select->shell);
|
|
}
|
|
else
|
|
{
|
|
layer_select_set_gimage (layer_select, gimage);
|
|
layer_select_advance (layer_select, move);
|
|
|
|
if (! GTK_WIDGET_VISIBLE (layer_select->shell))
|
|
gtk_widget_show (layer_select->shell);
|
|
else
|
|
gtk_widget_draw (layer_select->layer_preview, NULL);
|
|
}
|
|
|
|
gdk_key_repeat_disable ();
|
|
gdk_keyboard_grab (layer_select->shell->window, FALSE, time);
|
|
}
|
|
|
|
void
|
|
layer_select_update_preview_size (void)
|
|
{
|
|
if (layer_select != NULL)
|
|
{ gtk_preview_size (GTK_PREVIEW (layer_select->preview),
|
|
preview_size, preview_size);
|
|
if (GTK_WIDGET_VISIBLE (layer_select->shell))
|
|
gtk_widget_draw (layer_select->layer_preview, NULL);
|
|
}
|
|
}
|
|
|
|
|
|
/***********************/
|
|
/* Private functions */
|
|
/***********************/
|
|
|
|
|
|
static void
|
|
layer_select_advance (LayerSelect *layer_select,
|
|
gint move)
|
|
{
|
|
gint index;
|
|
gint count;
|
|
GSList *list;
|
|
GSList *nth;
|
|
GimpLayer *layer;
|
|
|
|
index = 0;
|
|
|
|
if (move == 0)
|
|
return;
|
|
|
|
/* If there is a floating selection, allow no advancement */
|
|
if (gimp_image_floating_sel (layer_select->gimage))
|
|
return;
|
|
|
|
for (list = layer_select->gimage->layer_stack, count = 0;
|
|
list;
|
|
list = g_slist_next (list), count++)
|
|
{
|
|
layer = (GimpLayer *) list->data;
|
|
|
|
if (layer == layer_select->current_layer)
|
|
index = count;
|
|
}
|
|
|
|
index += move;
|
|
index = CLAMP (index, 0, count - 1);
|
|
|
|
nth = g_slist_nth (layer_select->gimage->layer_stack, index);
|
|
|
|
if (nth)
|
|
{
|
|
layer = (GimpLayer *) nth->data;
|
|
layer_select->current_layer = layer;
|
|
}
|
|
}
|
|
|
|
static void
|
|
layer_select_forward (LayerSelect *layer_select)
|
|
{
|
|
layer_select_advance (layer_select, 1);
|
|
layer_select->dirty = TRUE;
|
|
gtk_widget_draw (layer_select->layer_preview, NULL);
|
|
}
|
|
|
|
static void
|
|
layer_select_backward (LayerSelect *layer_select)
|
|
{
|
|
layer_select_advance (layer_select, -1);
|
|
layer_select->dirty = TRUE;
|
|
gtk_widget_draw (layer_select->layer_preview, NULL);
|
|
}
|
|
|
|
static void
|
|
layer_select_end (LayerSelect *layer_select,
|
|
guint32 time)
|
|
{
|
|
gdk_key_repeat_restore ();
|
|
gdk_keyboard_ungrab (time);
|
|
|
|
gtk_widget_hide (layer_select->shell);
|
|
|
|
/* only reset the active layer if a new layer was specified */
|
|
if (layer_select->current_layer !=
|
|
gimp_image_get_active_layer (layer_select->gimage))
|
|
{
|
|
gimp_image_set_active_layer (layer_select->gimage,
|
|
layer_select->current_layer);
|
|
gdisplays_flush ();
|
|
}
|
|
}
|
|
|
|
static void
|
|
layer_select_set_gimage (LayerSelect *layer_select,
|
|
GImage *gimage)
|
|
{
|
|
gint image_width;
|
|
gint image_height;
|
|
|
|
layer_select->gimage = gimage;
|
|
layer_select->current_layer = gimp_image_get_active_layer (gimage);
|
|
layer_select->dirty = TRUE;
|
|
|
|
/* Get the image width and height variables, based on the gimage */
|
|
if (gimage->width > gimage->height)
|
|
layer_select->ratio =
|
|
MIN (1.0, (gdouble) preview_size / (gdouble) gimage->width);
|
|
else
|
|
layer_select->ratio =
|
|
MIN (1.0, (gdouble) preview_size / (gdouble) gimage->height);
|
|
|
|
image_width = (gint) (layer_select->ratio * gimage->width);
|
|
image_height = (gint) (layer_select->ratio * gimage->height);
|
|
|
|
if (layer_select->image_width != image_width ||
|
|
layer_select->image_height != image_height)
|
|
{
|
|
layer_select->image_width = image_width;
|
|
layer_select->image_height = image_height;
|
|
|
|
if (layer_select->layer_preview)
|
|
gtk_widget_set_usize (layer_select->layer_preview,
|
|
layer_select->image_width,
|
|
layer_select->image_height);
|
|
|
|
if (layer_select->layer_pixmap)
|
|
{
|
|
gdk_pixmap_unref (layer_select->layer_pixmap);
|
|
layer_select->layer_pixmap = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void
|
|
layer_select_set_layer (LayerSelect *layer_select)
|
|
{
|
|
GimpLayer *layer;
|
|
|
|
if (! (layer = (layer_select->current_layer)))
|
|
return;
|
|
|
|
/* Set the layer label */
|
|
gtk_label_set_text (GTK_LABEL (layer_select->label),
|
|
gimp_object_get_name (GIMP_OBJECT (layer)));
|
|
}
|
|
|
|
static gint
|
|
layer_select_events (GtkWidget *widget,
|
|
GdkEvent *event)
|
|
{
|
|
GdkEventKey *kevent;
|
|
GdkEventButton *bevent;
|
|
|
|
switch (event->type)
|
|
{
|
|
case GDK_BUTTON_PRESS:
|
|
bevent = (GdkEventButton *) event;
|
|
layer_select_end (layer_select, bevent->time);
|
|
break;
|
|
|
|
case GDK_KEY_PRESS:
|
|
kevent = (GdkEventKey *) event;
|
|
|
|
switch (kevent->keyval)
|
|
{
|
|
case GDK_Tab:
|
|
if (kevent->state & GDK_MOD1_MASK)
|
|
layer_select_forward (layer_select);
|
|
else if (kevent->state & GDK_CONTROL_MASK)
|
|
layer_select_backward (layer_select);
|
|
break;
|
|
}
|
|
return TRUE;
|
|
break;
|
|
|
|
case GDK_KEY_RELEASE:
|
|
kevent = (GdkEventKey *) event;
|
|
|
|
switch (kevent->keyval)
|
|
{
|
|
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;
|
|
}
|
|
|
|
if (! (kevent->state & (GDK_MOD1_MASK | GDK_CONTROL_MASK)))
|
|
layer_select_end (layer_select, kevent->time);
|
|
|
|
return TRUE;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gint
|
|
preview_events (GtkWidget *widget,
|
|
GdkEvent *event)
|
|
{
|
|
switch (event->type)
|
|
{
|
|
case GDK_EXPOSE:
|
|
if (layer_select->dirty)
|
|
{
|
|
/* If a preview exists, draw it */
|
|
if (preview_size)
|
|
preview_redraw (layer_select);
|
|
|
|
/* Change the layer name label */
|
|
layer_select_set_layer (layer_select);
|
|
|
|
layer_select->dirty = FALSE;
|
|
}
|
|
|
|
if (preview_size)
|
|
gdk_draw_pixmap (layer_select->layer_preview->window,
|
|
layer_select->layer_preview->style->black_gc,
|
|
layer_select->layer_pixmap,
|
|
0, 0, 0, 0,
|
|
layer_select->image_width,
|
|
layer_select->image_height);
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static void
|
|
preview_redraw (LayerSelect *layer_select)
|
|
{
|
|
GimpLayer *layer;
|
|
TempBuf *preview_buf;
|
|
gint w, h;
|
|
gint offx, offy;
|
|
|
|
if (! (layer = (layer_select->current_layer)))
|
|
return;
|
|
|
|
if (! layer_select->layer_pixmap)
|
|
layer_select->layer_pixmap =
|
|
gdk_pixmap_new (layer_select->layer_preview->window,
|
|
layer_select->image_width,
|
|
layer_select->image_height,
|
|
-1);
|
|
|
|
if (gimp_layer_is_floating_sel (layer))
|
|
{
|
|
render_fs_preview (layer_select->layer_preview,
|
|
layer_select->layer_pixmap);
|
|
}
|
|
else
|
|
{
|
|
gint off_x;
|
|
gint off_y;
|
|
|
|
gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
|
|
|
|
/* determine width and height */
|
|
w = (gint) (layer_select->ratio *
|
|
gimp_drawable_width (GIMP_DRAWABLE (layer)));
|
|
h = (gint) (layer_select->ratio *
|
|
gimp_drawable_height (GIMP_DRAWABLE (layer)));
|
|
offx = (gint) (layer_select->ratio * off_x);
|
|
offy = (gint) (layer_select->ratio * off_y);
|
|
|
|
preview_buf = gimp_viewable_get_preview (GIMP_VIEWABLE (layer), w, h);
|
|
preview_buf->x = offx;
|
|
preview_buf->y = offy;
|
|
|
|
render_preview (preview_buf,
|
|
layer_select->preview,
|
|
layer_select->image_width,
|
|
layer_select->image_height,
|
|
-1);
|
|
|
|
/* Set the layer pixmap */
|
|
gtk_preview_put (GTK_PREVIEW (layer_select->preview),
|
|
layer_select->layer_pixmap,
|
|
layer_select->layer_preview->style->black_gc,
|
|
0, 0, 0, 0,
|
|
layer_select->image_width, layer_select->image_height);
|
|
|
|
/* make sure the image has been transfered completely
|
|
* to the pixmap before we use it again...
|
|
*/
|
|
gdk_flush ();
|
|
}
|
|
}
|