2002-11-18 Sven Neumann <sven@gimp.org> Finally landed the new GimpConfig based gimprc parser. It's not finished yet but we need to start somewhere. This release removes the old gimprc.[ch] files. The gimprc format changes slightly, but the changes are minimal. The Preferences dialog is temporarily disabled since it still needs to be ported. If you are are afraid, stay away from CVS for a few days ;-) * app/Makefile.am * app/gimprc.[ch]: removed the old gimprc system. * app/base/Makefile.am * app/base/base-config.[ch]: removed these files in favor of config/gimpbaseconfig.[ch]. * app/core/Makefile.am * app/core/gimpcoreconfig.[ch]: removed these files in favor of config/gimpcoreconfig.[ch]. * app/config/Makefile.am * app/config/config-types.h: moved typedefs into this new file. * app/config/gimpbaseconfig.[ch] * app/config/gimpcoreconfig.[ch] * app/config/gimpdisplayconfig.[ch] * app/config/gimpguiconfig.[ch] * app/config/gimprc.[ch] * app/config/test-config.c: brought into shape for real use. * app/base/base-types.h: include config/config-types.h here. Added a global GimpBaseConfig *base_config variable to ease migration. * app/gui/Makefile.am: temporarily disabled the preferences dialog. * app/app_procs.c * app/undo.c * app/undo_history.c * app/base/base.[ch] * app/base/gimphistogram.c * app/base/pixel-processor.c * app/base/temp-buf.c * app/base/tile-cache.c * app/core/core-types.h * app/core/gimp-documents.c * app/core/gimp.c * app/core/gimpbrush.c * app/core/gimpbrushgenerated.c * app/core/gimpcontext.c * app/core/gimpdrawable-transform.c * app/core/gimpimage-new.c * app/core/gimpimage.c * app/core/gimpimagefile.c * app/core/gimpmodules.c * app/core/gimppattern.c * app/display/Makefile.am * app/display/gimpdisplay-handlers.c * app/display/gimpdisplay.[ch] * app/display/gimpdisplayshell-callbacks.c * app/display/gimpdisplayshell-handlers.c * app/display/gimpdisplayshell-layer-select.c * app/display/gimpdisplayshell-render.c * app/display/gimpdisplayshell-scale.c * app/display/gimpdisplayshell-scroll.c * app/display/gimpdisplayshell-selection.c * app/display/gimpdisplayshell.[ch] * app/display/gimpnavigationview.c * app/file/file-save.c * app/gui/device-status-dialog.c * app/gui/dialogs-constructors.c * app/gui/file-commands.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.c * app/gui/file-save-dialog.c * app/gui/gui.c * app/gui/menus.c * app/gui/paths-dialog.c * app/gui/resize-dialog.c * app/gui/session.c * app/gui/test-commands.c * app/gui/tips-dialog.c * app/gui/tips-dialog.h * app/gui/user-install-dialog.c * app/gui/view-commands.c * app/paint/gimppaintcore.c * app/plug-in/plug-in.c * app/plug-in/plug-ins.c * app/tools/gimpbezierselecttool.c * app/tools/gimpbucketfilltool.c * app/tools/gimpcolorpickertool.c * app/tools/gimpcroptool.c * app/tools/gimpeditselectiontool.c * app/tools/gimpfuzzyselecttool.c * app/tools/gimpinktool.c * app/tools/gimpmagnifytool.c * app/tools/gimpmeasuretool.c * app/tools/gimppainttool.c * app/tools/gimppathtool.c * app/tools/gimptexttool.[ch] * app/tools/selection_options.c * app/tools/tools.c * app/tools/transform_options.c * app/widgets/gimphelp.c * app/widgets/gimpitemfactory.c * app/widgets/gimpselectioneditor.c * app/xcf/xcf-load.c * tools/pdbgen/pdb/fileops.pdb * tools/pdbgen/pdb/gimprc.pdb * tools/pdbgen/pdb/image.pdb * tools/pdbgen/pdb/layer.pdb * tools/pdbgen/pdb/transform_tools.pdb: use the new config system instead of the old gimprc stuff. * etc/gimprc.in * etc/gimprc_user.in: adapted to the new gimprc format. Will update the man-page later... * app/pdb/fileops_cmds.c * app/pdb/gimprc_cmds.c * app/pdb/image_cmds.c * app/pdb/layer_cmds.c * app/pdb/transform_tools_cmds.c * libgimp/gimpgimprc_pdb.c: regenerated.
2556 lines
78 KiB
C
2556 lines
78 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 <string.h>
|
||
|
||
#include <gtk/gtk.h>
|
||
|
||
#include "libgimpbase/gimpbase.h"
|
||
#include "libgimpcolor/gimpcolor.h"
|
||
#include "libgimpwidgets/gimpwidgets.h"
|
||
|
||
#include "display-types.h"
|
||
|
||
#ifdef __GNUC__
|
||
#warning FIXME #include "gui/gui-types.h"
|
||
#endif
|
||
#include "gui/gui-types.h"
|
||
|
||
#include "config/gimpdisplayconfig.h"
|
||
|
||
#include "core/gimp.h"
|
||
#include "core/gimpbuffer.h"
|
||
#include "core/gimpcontext.h"
|
||
#include "core/gimpcontainer.h"
|
||
#include "core/gimpimage.h"
|
||
#include "core/gimpimage-guides.h"
|
||
#include "core/gimpimage-mask.h"
|
||
#include "core/gimpimage-new.h"
|
||
#include "core/gimplayer.h"
|
||
#include "core/gimplayermask.h"
|
||
#include "core/gimpmarshal.h"
|
||
#include "core/gimppattern.h"
|
||
|
||
#include "file/file-utils.h"
|
||
|
||
#include "widgets/gimpcolorpanel.h"
|
||
#include "widgets/gimpcursor.h"
|
||
#include "widgets/gimpdnd.h"
|
||
#include "widgets/gimpitemfactory.h"
|
||
#include "widgets/gimpwidgets-utils.h"
|
||
|
||
#include "gui/info-window.h"
|
||
#include "gui/plug-in-menus.h"
|
||
|
||
#include "tools/tools-types.h"
|
||
|
||
#include "tools/tool_manager.h"
|
||
|
||
#include "gimpdisplay.h"
|
||
#include "gimpdisplay-area.h"
|
||
#include "gimpdisplayshell.h"
|
||
#include "gimpdisplayshell-callbacks.h"
|
||
#include "gimpdisplayshell-dnd.h"
|
||
#include "gimpdisplayshell-filter.h"
|
||
#include "gimpdisplayshell-handlers.h"
|
||
#include "gimpdisplayshell-render.h"
|
||
#include "gimpdisplayshell-selection.h"
|
||
#include "gimpstatusbar.h"
|
||
|
||
#include "app_procs.h"
|
||
#include "undo.h"
|
||
|
||
#include "libgimp/gimpintl.h"
|
||
|
||
|
||
#define MAX_TITLE_BUF 256
|
||
|
||
enum
|
||
{
|
||
SCALED,
|
||
SCROLLED,
|
||
RECONNECT,
|
||
LAST_SIGNAL
|
||
};
|
||
|
||
|
||
/* local function prototypes */
|
||
|
||
static void gimp_display_shell_class_init (GimpDisplayShellClass *klass);
|
||
static void gimp_display_shell_init (GimpDisplayShell *shell);
|
||
|
||
static void gimp_display_shell_destroy (GtkObject *object);
|
||
static gboolean gimp_display_shell_delete_event (GtkWidget *widget,
|
||
GdkEventAny *aevent);
|
||
|
||
static gpointer gimp_display_shell_get_accel_context (gpointer data);
|
||
|
||
static void gimp_display_shell_display_area (GimpDisplayShell *shell,
|
||
gint x,
|
||
gint y,
|
||
gint w,
|
||
gint h);
|
||
static void gimp_display_shell_real_set_cursor (GimpDisplayShell *shell,
|
||
GdkCursorType cursor_type,
|
||
GimpToolCursorType tool_cursor,
|
||
GimpCursorModifier modifier,
|
||
gboolean always_install);
|
||
static void gimp_display_shell_draw_cursor (GimpDisplayShell *shell);
|
||
|
||
static void gimp_display_shell_format_title (GimpDisplayShell *gdisp,
|
||
gchar *title,
|
||
gint title_len,
|
||
const gchar *format);
|
||
|
||
static void gimp_display_shell_close_warning_dialog (GimpDisplayShell *shell,
|
||
const gchar *image_name);
|
||
static void gimp_display_shell_close_warning_callback (GtkWidget *widget,
|
||
gboolean close,
|
||
gpointer data);
|
||
|
||
|
||
static guint display_shell_signals[LAST_SIGNAL] = { 0 };
|
||
|
||
static GtkWindowClass *parent_class = NULL;
|
||
|
||
|
||
GType
|
||
gimp_display_shell_get_type (void)
|
||
{
|
||
static GType shell_type = 0;
|
||
|
||
if (! shell_type)
|
||
{
|
||
static const GTypeInfo shell_info =
|
||
{
|
||
sizeof (GimpDisplayShellClass),
|
||
(GBaseInitFunc) NULL,
|
||
(GBaseFinalizeFunc) NULL,
|
||
(GClassInitFunc) gimp_display_shell_class_init,
|
||
NULL, /* class_finalize */
|
||
NULL, /* class_data */
|
||
sizeof (GimpDisplayShell),
|
||
0, /* n_preallocs */
|
||
(GInstanceInitFunc) gimp_display_shell_init,
|
||
};
|
||
|
||
shell_type = g_type_register_static (GTK_TYPE_WINDOW,
|
||
"GimpDisplayShell",
|
||
&shell_info, 0);
|
||
}
|
||
|
||
return shell_type;
|
||
}
|
||
|
||
static void
|
||
gimp_display_shell_class_init (GimpDisplayShellClass *klass)
|
||
{
|
||
GtkObjectClass *object_class;
|
||
GtkWidgetClass *widget_class;
|
||
|
||
object_class = GTK_OBJECT_CLASS (klass);
|
||
widget_class = GTK_WIDGET_CLASS (klass);
|
||
|
||
parent_class = g_type_class_peek_parent (klass);
|
||
|
||
display_shell_signals[SCALED] =
|
||
g_signal_new ("scaled",
|
||
G_TYPE_FROM_CLASS (klass),
|
||
G_SIGNAL_RUN_FIRST,
|
||
G_STRUCT_OFFSET (GimpDisplayShellClass, scaled),
|
||
NULL, NULL,
|
||
gimp_marshal_VOID__VOID,
|
||
G_TYPE_NONE, 0);
|
||
|
||
display_shell_signals[SCROLLED] =
|
||
g_signal_new ("scrolled",
|
||
G_TYPE_FROM_CLASS (klass),
|
||
G_SIGNAL_RUN_FIRST,
|
||
G_STRUCT_OFFSET (GimpDisplayShellClass, scrolled),
|
||
NULL, NULL,
|
||
gimp_marshal_VOID__VOID,
|
||
G_TYPE_NONE, 0);
|
||
|
||
display_shell_signals[RECONNECT] =
|
||
g_signal_new ("reconnect",
|
||
G_TYPE_FROM_CLASS (klass),
|
||
G_SIGNAL_RUN_FIRST,
|
||
G_STRUCT_OFFSET (GimpDisplayShellClass, reconnect),
|
||
NULL, NULL,
|
||
gimp_marshal_VOID__VOID,
|
||
G_TYPE_NONE, 0);
|
||
|
||
object_class->destroy = gimp_display_shell_destroy;
|
||
|
||
widget_class->delete_event = gimp_display_shell_delete_event;
|
||
|
||
klass->scaled = NULL;
|
||
klass->scrolled = NULL;
|
||
klass->reconnect = NULL;
|
||
}
|
||
|
||
static void
|
||
gimp_display_shell_init (GimpDisplayShell *shell)
|
||
{
|
||
shell->gdisp = NULL;
|
||
shell->item_factory = NULL;
|
||
|
||
shell->scale = 0;
|
||
shell->dot_for_dot = TRUE;
|
||
|
||
shell->offset_x = 0;
|
||
shell->offset_y = 0;
|
||
|
||
shell->disp_width = 0;
|
||
shell->disp_height = 0;
|
||
shell->disp_xoffset = 0;
|
||
shell->disp_yoffset = 0;
|
||
|
||
shell->proximity = FALSE;
|
||
|
||
shell->select = NULL;
|
||
|
||
shell->display_areas = NULL;
|
||
|
||
shell->hsbdata = NULL;
|
||
shell->vsbdata = NULL;
|
||
|
||
shell->canvas = NULL;
|
||
|
||
shell->hsb = NULL;
|
||
shell->vsb = NULL;
|
||
shell->qmask = NULL;
|
||
shell->hrule = NULL;
|
||
shell->vrule = NULL;
|
||
shell->origin = NULL;
|
||
|
||
shell->statusbar = NULL;
|
||
|
||
shell->render_buf = g_malloc (GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH *
|
||
GIMP_DISPLAY_SHELL_RENDER_BUF_HEIGHT *
|
||
3);
|
||
shell->render_gc = NULL;
|
||
|
||
shell->title_dirty = FALSE;
|
||
|
||
shell->icon_size = 32;
|
||
shell->icon_idle_id = 0;
|
||
|
||
shell->current_cursor = (GdkCursorType) -1;
|
||
shell->tool_cursor = GIMP_TOOL_CURSOR_NONE;
|
||
shell->cursor_modifier = GIMP_CURSOR_MODIFIER_NONE;
|
||
|
||
shell->override_cursor = (GdkCursorType) -1;
|
||
shell->using_override_cursor = FALSE;
|
||
|
||
shell->draw_cursor = FALSE;
|
||
shell->have_cursor = FALSE;
|
||
shell->cursor_x = 0;
|
||
shell->cursor_y = 0;
|
||
|
||
shell->padding_button = NULL;
|
||
gimp_rgb_set (&shell->padding_color, 1.0, 1.0, 1.0);
|
||
shell->padding_gc = NULL;
|
||
|
||
shell->warning_dialog = NULL;
|
||
shell->info_dialog = NULL;
|
||
shell->nav_popup = NULL;
|
||
|
||
shell->filters = NULL;
|
||
shell->filters_dialog = NULL;
|
||
|
||
shell->space_pressed = FALSE;
|
||
shell->space_release_pending = FALSE;
|
||
|
||
gtk_window_set_wmclass (GTK_WINDOW (shell), "image_window", "Gimp");
|
||
gtk_window_set_resizable (GTK_WINDOW (shell), TRUE);
|
||
|
||
gtk_widget_set_events (GTK_WIDGET (shell), (GDK_POINTER_MOTION_MASK |
|
||
GDK_POINTER_MOTION_HINT_MASK |
|
||
GDK_BUTTON_PRESS_MASK |
|
||
GDK_KEY_PRESS_MASK |
|
||
GDK_KEY_RELEASE_MASK));
|
||
|
||
/* active display callback */
|
||
g_signal_connect (G_OBJECT (shell), "button_press_event",
|
||
G_CALLBACK (gimp_display_shell_events),
|
||
shell);
|
||
g_signal_connect (G_OBJECT (shell), "button_release_event",
|
||
G_CALLBACK (gimp_display_shell_events),
|
||
shell);
|
||
g_signal_connect (G_OBJECT (shell), "key_press_event",
|
||
G_CALLBACK (gimp_display_shell_events),
|
||
shell);
|
||
|
||
/* dnd stuff */
|
||
gimp_dnd_viewable_dest_add (GTK_WIDGET (shell), GIMP_TYPE_LAYER,
|
||
gimp_display_shell_drop_drawable,
|
||
shell);
|
||
gimp_dnd_viewable_dest_add (GTK_WIDGET (shell), GIMP_TYPE_LAYER_MASK,
|
||
gimp_display_shell_drop_drawable,
|
||
shell);
|
||
gimp_dnd_viewable_dest_add (GTK_WIDGET (shell), GIMP_TYPE_CHANNEL,
|
||
gimp_display_shell_drop_drawable,
|
||
shell);
|
||
gimp_dnd_viewable_dest_add (GTK_WIDGET (shell), GIMP_TYPE_PATTERN,
|
||
gimp_display_shell_drop_pattern,
|
||
shell);
|
||
gimp_dnd_viewable_dest_add (GTK_WIDGET (shell), GIMP_TYPE_BUFFER,
|
||
gimp_display_shell_drop_buffer,
|
||
shell);
|
||
gimp_dnd_color_dest_add (GTK_WIDGET (shell),
|
||
gimp_display_shell_drop_color,
|
||
shell);
|
||
|
||
/* connect the "F1" help key */
|
||
gimp_help_connect (GTK_WIDGET (shell),
|
||
gimp_standard_help_func,
|
||
"image/image_window.html");
|
||
|
||
}
|
||
|
||
static void
|
||
gimp_display_shell_destroy (GtkObject *object)
|
||
{
|
||
GimpDisplayShell *shell;
|
||
|
||
shell = GIMP_DISPLAY_SHELL (object);
|
||
|
||
if (shell->gdisp)
|
||
{
|
||
gimp_display_shell_disconnect (shell);
|
||
}
|
||
|
||
if (shell->select)
|
||
{
|
||
gimp_display_shell_selection_free (shell->select);
|
||
shell->select = NULL;
|
||
}
|
||
|
||
shell->display_areas = gimp_display_area_list_free (shell->display_areas);
|
||
|
||
gimp_display_shell_filter_detach_all (shell);
|
||
|
||
if (shell->render_buf)
|
||
{
|
||
g_free (shell->render_buf);
|
||
shell->render_buf = NULL;
|
||
}
|
||
|
||
if (shell->render_gc)
|
||
{
|
||
g_object_unref (shell->render_gc);
|
||
shell->render_gc = NULL;
|
||
}
|
||
|
||
if (shell->padding_gc)
|
||
{
|
||
g_object_unref (G_OBJECT (shell->padding_gc));
|
||
shell->padding_gc = NULL;
|
||
}
|
||
|
||
if (shell->info_dialog)
|
||
{
|
||
info_window_free (shell->info_dialog);
|
||
shell->info_dialog = NULL;
|
||
}
|
||
|
||
if (shell->nav_popup)
|
||
{
|
||
gtk_widget_destroy (shell->nav_popup);
|
||
shell->nav_popup = NULL;
|
||
}
|
||
|
||
shell->gdisp = NULL;
|
||
|
||
GTK_OBJECT_CLASS (parent_class)->destroy (object);
|
||
}
|
||
|
||
static gboolean
|
||
gimp_display_shell_delete_event (GtkWidget *widget,
|
||
GdkEventAny *aevent)
|
||
{
|
||
GimpDisplayShell *shell;
|
||
|
||
shell = GIMP_DISPLAY_SHELL (widget);
|
||
|
||
gimp_display_shell_close (shell, FALSE);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
GtkWidget *
|
||
gimp_display_shell_new (GimpDisplay *gdisp,
|
||
guint scale)
|
||
{
|
||
GimpDisplayShell *shell;
|
||
GimpDisplayConfig *config;
|
||
GtkWidget *main_vbox;
|
||
GtkWidget *disp_vbox;
|
||
GtkWidget *upper_hbox;
|
||
GtkWidget *right_vbox;
|
||
GtkWidget *lower_hbox;
|
||
GtkWidget *inner_table;
|
||
GtkWidget *arrow;
|
||
GtkWidget *image;
|
||
GtkWidget *nav_ebox;
|
||
gint image_width, image_height;
|
||
gint n_width, n_height;
|
||
gint s_width, s_height;
|
||
gint scalesrc, scaledest;
|
||
|
||
g_return_val_if_fail (GIMP_IS_DISPLAY (gdisp), NULL);
|
||
|
||
/* the toplevel shell */
|
||
shell = g_object_new (GIMP_TYPE_DISPLAY_SHELL, NULL);
|
||
|
||
shell->gdisp = gdisp;
|
||
shell->scale = scale;
|
||
|
||
image_width = gdisp->gimage->width;
|
||
image_height = gdisp->gimage->height;
|
||
|
||
config = GIMP_DISPLAY_CONFIG (gdisp->gimage->gimp->config);
|
||
|
||
shell->dot_for_dot = config->default_dot_for_dot;
|
||
|
||
/* adjust the initial scale -- so that window fits on screen the 75%
|
||
* value is the same as in gimp_display_shell_shrink_wrap. It
|
||
* probably should be a user-configurable option.
|
||
*/
|
||
s_width = gdk_screen_width () * 0.75;
|
||
s_height = gdk_screen_height () * 0.75;
|
||
|
||
scalesrc = SCALESRC (shell);
|
||
scaledest = SCALEDEST (shell);
|
||
|
||
n_width = SCALEX (shell, image_width);
|
||
n_height = SCALEX (shell, image_height);
|
||
|
||
/* Limit to the size of the screen... */
|
||
while (n_width > s_width || n_height > s_height)
|
||
{
|
||
if (scaledest > 1)
|
||
scaledest--;
|
||
else
|
||
if (scalesrc < 0xff)
|
||
scalesrc++;
|
||
|
||
n_width = image_width *
|
||
(scaledest * SCREEN_XRES (shell)) / (scalesrc * gdisp->gimage->xresolution);
|
||
n_height = image_height *
|
||
(scaledest * SCREEN_XRES (shell)) / (scalesrc * gdisp->gimage->xresolution);
|
||
}
|
||
|
||
shell->scale = (scaledest << 8) + scalesrc;
|
||
|
||
shell->item_factory = gimp_item_factory_from_path ("<Image>");
|
||
|
||
/* The accelerator table for images */
|
||
gimp_window_add_accel_group (GTK_WINDOW (shell),
|
||
GTK_ITEM_FACTORY (shell->item_factory),
|
||
gimp_display_shell_get_accel_context,
|
||
shell);
|
||
|
||
/* GtkTable widgets are not able to shrink a row/column correctly if
|
||
* widgets are attached with GTK_EXPAND even if those widgets have
|
||
* other rows/columns in their rowspan/colspan where they could
|
||
* nicely expand without disturbing the row/column which is supposed
|
||
* to shrink. --Mitch
|
||
*
|
||
* Changed the packing to use hboxes and vboxes which behave nicer:
|
||
*
|
||
* main_vbox
|
||
* |
|
||
* +-- disp_vbox
|
||
* | |
|
||
* | +-- upper_hbox
|
||
* | | |
|
||
* | | +-- inner_table
|
||
* | | | |
|
||
* | | | +-- origin
|
||
* | | | +-- hruler
|
||
* | | | +-- vruler
|
||
* | | | +-- canvas
|
||
* | | |
|
||
* | | +-- right_vbox
|
||
* | | |
|
||
* | | +-- padding_button
|
||
* | | +-- vscrollbar
|
||
* | |
|
||
* | +-- lower_hbox
|
||
* | |
|
||
* | +-- qmask
|
||
* | +-- hscrollbar
|
||
* | +-- navbutton
|
||
* |
|
||
* +-- statusbar
|
||
*/
|
||
|
||
/* first, set up the container hierarchy *********************************/
|
||
|
||
/* the vbox containing all widgets */
|
||
main_vbox = gtk_vbox_new (FALSE, 2);
|
||
gtk_container_set_border_width (GTK_CONTAINER (main_vbox), 2);
|
||
gtk_container_add (GTK_CONTAINER (shell), main_vbox);
|
||
|
||
/* another vbox for everything except the statusbar */
|
||
disp_vbox = gtk_vbox_new (FALSE, 1);
|
||
gtk_box_pack_start (GTK_BOX (main_vbox), disp_vbox, TRUE, TRUE, 0);
|
||
gtk_widget_show (disp_vbox);
|
||
|
||
/* a hbox for the inner_table and the vertical scrollbar */
|
||
upper_hbox = gtk_hbox_new (FALSE, 1);
|
||
gtk_box_pack_start (GTK_BOX (disp_vbox), upper_hbox, TRUE, TRUE, 0);
|
||
gtk_widget_show (upper_hbox);
|
||
|
||
/* the table containing origin, rulers and the canvas */
|
||
inner_table = gtk_table_new (2, 2, FALSE);
|
||
gtk_table_set_col_spacing (GTK_TABLE (inner_table), 0, 1);
|
||
gtk_table_set_row_spacing (GTK_TABLE (inner_table), 0, 1);
|
||
gtk_box_pack_start (GTK_BOX (upper_hbox), inner_table, TRUE, TRUE, 0);
|
||
gtk_widget_show (inner_table);
|
||
|
||
/* the vbox containing the color button and the vertical scrollbar */
|
||
right_vbox = gtk_vbox_new (FALSE, 1);
|
||
gtk_box_pack_start (GTK_BOX (upper_hbox), right_vbox, FALSE, FALSE, 0);
|
||
gtk_widget_show (right_vbox);
|
||
|
||
/* the hbox containing qmask button, vertical scrollbar and nav button */
|
||
lower_hbox = gtk_hbox_new (FALSE, 1);
|
||
gtk_box_pack_start (GTK_BOX (disp_vbox), lower_hbox, FALSE, FALSE, 0);
|
||
gtk_widget_show (lower_hbox);
|
||
|
||
/* create the scrollbars *************************************************/
|
||
|
||
/* the horizontal scrollbar */
|
||
shell->hsbdata =
|
||
GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, image_width, 1, 1, image_width));
|
||
shell->hsb = gtk_hscrollbar_new (shell->hsbdata);
|
||
GTK_WIDGET_UNSET_FLAGS (shell->hsb, GTK_CAN_FOCUS);
|
||
|
||
/* the vertical scrollbar */
|
||
shell->vsbdata =
|
||
GTK_ADJUSTMENT (gtk_adjustment_new (0, 0, image_height, 1, 1, image_height));
|
||
shell->vsb = gtk_vscrollbar_new (shell->vsbdata);
|
||
GTK_WIDGET_UNSET_FLAGS (shell->vsb, GTK_CAN_FOCUS);
|
||
|
||
/* create the contents of the inner_table ********************************/
|
||
|
||
/* the menu popup button */
|
||
shell->origin = gtk_button_new ();
|
||
GTK_WIDGET_UNSET_FLAGS (shell->origin, GTK_CAN_FOCUS);
|
||
gtk_widget_set_events (GTK_WIDGET (shell->origin),
|
||
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
|
||
|
||
g_signal_connect (G_OBJECT (shell->origin), "button_press_event",
|
||
G_CALLBACK (gimp_display_shell_origin_button_press),
|
||
shell);
|
||
|
||
gimp_help_set_help_data (shell->origin, NULL, "#origin_button");
|
||
|
||
arrow = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_OUT);
|
||
gtk_container_set_border_width (GTK_CONTAINER (shell->origin), 0);
|
||
gtk_container_add (GTK_CONTAINER (shell->origin), arrow);
|
||
gtk_widget_show (arrow);
|
||
|
||
/* the horizontal ruler */
|
||
shell->hrule = gtk_hruler_new ();
|
||
gtk_widget_set_events (GTK_WIDGET (shell->hrule),
|
||
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
|
||
|
||
g_signal_connect_swapped (G_OBJECT (shell), "motion_notify_event",
|
||
G_CALLBACK (GTK_WIDGET_GET_CLASS (shell->hrule)->motion_notify_event),
|
||
shell->hrule);
|
||
g_signal_connect (G_OBJECT (shell->hrule), "button_press_event",
|
||
G_CALLBACK (gimp_display_shell_hruler_button_press),
|
||
shell);
|
||
|
||
gimp_help_set_help_data (shell->hrule, NULL, "#ruler");
|
||
|
||
/* the vertical ruler */
|
||
shell->vrule = gtk_vruler_new ();
|
||
gtk_widget_set_events (GTK_WIDGET (shell->vrule),
|
||
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
|
||
|
||
g_signal_connect_swapped (G_OBJECT (shell), "motion_notify_event",
|
||
G_CALLBACK (GTK_WIDGET_GET_CLASS (shell->vrule)->motion_notify_event),
|
||
shell->vrule);
|
||
g_signal_connect (G_OBJECT (shell->vrule), "button_press_event",
|
||
G_CALLBACK (gimp_display_shell_vruler_button_press),
|
||
shell);
|
||
|
||
gimp_help_set_help_data (shell->vrule, NULL, "#ruler");
|
||
|
||
/* the canvas */
|
||
shell->canvas = gtk_drawing_area_new ();
|
||
gtk_widget_set_name (shell->canvas, "gimp-canvas");
|
||
gtk_widget_set_size_request (shell->canvas, n_width, n_height);
|
||
gtk_widget_set_events (shell->canvas, GIMP_DISPLAY_SHELL_CANVAS_EVENT_MASK);
|
||
gtk_widget_set_extension_events (shell->canvas, GDK_EXTENSION_EVENTS_ALL);
|
||
GTK_WIDGET_SET_FLAGS (shell->canvas, GTK_CAN_FOCUS);
|
||
|
||
g_signal_connect (G_OBJECT (shell->canvas), "realize",
|
||
G_CALLBACK (gimp_display_shell_canvas_realize),
|
||
shell);
|
||
|
||
/* set the active display before doing any other canvas event processing */
|
||
g_signal_connect (G_OBJECT (shell->canvas), "event",
|
||
G_CALLBACK (gimp_display_shell_events),
|
||
shell);
|
||
|
||
g_signal_connect (G_OBJECT (shell->canvas), "expose_event",
|
||
G_CALLBACK (gimp_display_shell_canvas_expose),
|
||
shell);
|
||
g_signal_connect (G_OBJECT (shell->canvas), "configure_event",
|
||
G_CALLBACK (gimp_display_shell_canvas_configure),
|
||
shell);
|
||
g_signal_connect (G_OBJECT (shell->canvas), "event",
|
||
G_CALLBACK (gimp_display_shell_canvas_tool_events),
|
||
shell);
|
||
|
||
/* create the contents of the right_vbox *********************************/
|
||
shell->padding_button = gimp_color_panel_new (_("Set Canvas Padding Color"),
|
||
&shell->padding_color,
|
||
GIMP_COLOR_AREA_FLAT,
|
||
15, 15);
|
||
GTK_WIDGET_UNSET_FLAGS (shell->padding_button, GTK_CAN_FOCUS);
|
||
|
||
gimp_help_set_help_data (shell->padding_button,
|
||
_("Set canvas padding color"), "#padding_button");
|
||
|
||
g_signal_connect (G_OBJECT (shell->padding_button), "button_press_event",
|
||
G_CALLBACK (gimp_display_shell_color_button_press),
|
||
shell);
|
||
g_signal_connect (G_OBJECT (shell->padding_button), "color_changed",
|
||
G_CALLBACK (gimp_display_shell_color_button_changed),
|
||
shell);
|
||
|
||
{
|
||
static GtkItemFactoryEntry menu_items[] =
|
||
{
|
||
{ "/---", NULL, NULL, 0, "<Separator>"},
|
||
{ N_("/Default Color"), NULL,
|
||
gimp_display_shell_color_button_default, 0, NULL }
|
||
};
|
||
|
||
gtk_item_factory_create_items (GIMP_COLOR_BUTTON (shell->padding_button)->item_factory,
|
||
G_N_ELEMENTS (menu_items),
|
||
menu_items,
|
||
shell);
|
||
}
|
||
|
||
/* create the contents of the lower_hbox *********************************/
|
||
|
||
/* the qmask button */
|
||
shell->qmask = gtk_check_button_new ();
|
||
gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (shell->qmask), FALSE);
|
||
gtk_widget_set_size_request (GTK_WIDGET (shell->qmask), 16, 16);
|
||
GTK_WIDGET_UNSET_FLAGS (shell->qmask, GTK_CAN_FOCUS);
|
||
|
||
image = gtk_image_new_from_stock (GIMP_STOCK_QMASK_OFF, GTK_ICON_SIZE_MENU);
|
||
gtk_container_add (GTK_CONTAINER (shell->qmask), image);
|
||
gtk_widget_show (image);
|
||
|
||
gimp_help_set_help_data (shell->qmask,
|
||
_("Toggle QuickMask"), "#qmask_button");
|
||
|
||
g_signal_connect (G_OBJECT (shell->qmask), "toggled",
|
||
G_CALLBACK (gimp_display_shell_qmask_toggled),
|
||
shell);
|
||
g_signal_connect (G_OBJECT (shell->qmask), "button_press_event",
|
||
G_CALLBACK (gimp_display_shell_qmask_button_press),
|
||
shell);
|
||
|
||
/* the navigation window button */
|
||
nav_ebox = gtk_event_box_new ();
|
||
|
||
image = gtk_image_new_from_stock (GIMP_STOCK_NAVIGATION, GTK_ICON_SIZE_MENU);
|
||
gtk_container_add (GTK_CONTAINER (nav_ebox), image);
|
||
gtk_widget_show (image);
|
||
|
||
g_signal_connect (G_OBJECT (nav_ebox), "button_press_event",
|
||
G_CALLBACK (gimp_display_shell_nav_button_press),
|
||
shell);
|
||
|
||
gimp_help_set_help_data (nav_ebox, NULL, "#nav_window_button");
|
||
|
||
/* create the contents of the status area *********************************/
|
||
|
||
/* the statusbar */
|
||
shell->statusbar = gimp_statusbar_new (shell);
|
||
gtk_statusbar_set_has_resize_grip (GTK_STATUSBAR (shell->statusbar), FALSE);
|
||
gimp_help_set_help_data (shell->statusbar, NULL, "#status_area");
|
||
|
||
/* pack all the widgets **************************************************/
|
||
|
||
/* fill the inner_table */
|
||
gtk_table_attach (GTK_TABLE (inner_table), shell->origin, 0, 1, 0, 1,
|
||
GTK_FILL, GTK_FILL, 0, 0);
|
||
gtk_table_attach (GTK_TABLE (inner_table), shell->hrule, 1, 2, 0, 1,
|
||
GTK_EXPAND | GTK_SHRINK | GTK_FILL, GTK_FILL, 0, 0);
|
||
gtk_table_attach (GTK_TABLE (inner_table), shell->vrule, 0, 1, 1, 2,
|
||
GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
|
||
gtk_table_attach (GTK_TABLE (inner_table), shell->canvas, 1, 2, 1, 2,
|
||
GTK_EXPAND | GTK_SHRINK | GTK_FILL,
|
||
GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
|
||
|
||
/* fill the right_vbox */
|
||
gtk_box_pack_start (GTK_BOX (right_vbox), shell->padding_button,
|
||
FALSE, FALSE, 0);
|
||
gtk_box_pack_start (GTK_BOX (right_vbox), shell->vsb, TRUE, TRUE, 0);
|
||
|
||
/* fill the lower_hbox */
|
||
gtk_box_pack_start (GTK_BOX (lower_hbox), shell->qmask, FALSE, FALSE, 0);
|
||
gtk_box_pack_start (GTK_BOX (lower_hbox), shell->hsb, TRUE, TRUE, 0);
|
||
gtk_box_pack_start (GTK_BOX (lower_hbox), nav_ebox, FALSE, FALSE, 0);
|
||
|
||
gtk_box_pack_end (GTK_BOX (main_vbox), shell->statusbar, FALSE, FALSE, 0);
|
||
|
||
/* show everything *******************************************************/
|
||
|
||
if (config->show_rulers)
|
||
{
|
||
gtk_widget_show (shell->origin);
|
||
gtk_widget_show (shell->hrule);
|
||
gtk_widget_show (shell->vrule);
|
||
}
|
||
gtk_widget_show (shell->canvas);
|
||
|
||
gtk_widget_show (shell->vsb);
|
||
gtk_widget_show (shell->hsb);
|
||
|
||
gtk_widget_show (shell->padding_button);
|
||
|
||
gtk_widget_show (shell->qmask);
|
||
gtk_widget_show (nav_ebox);
|
||
|
||
if (config->show_statusbar)
|
||
{
|
||
gtk_widget_show (shell->statusbar);
|
||
}
|
||
|
||
gtk_widget_show (main_vbox);
|
||
|
||
gimp_display_shell_connect (shell);
|
||
|
||
return GTK_WIDGET (shell);
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_close (GimpDisplayShell *shell,
|
||
gboolean kill_it)
|
||
{
|
||
/* FIXME!! */
|
||
GimpDisplayConfig *config = GIMP_DISPLAY_CONFIG (the_gimp->config);
|
||
|
||
GimpImage *gimage;
|
||
|
||
gimage = shell->gdisp->gimage;
|
||
|
||
/* FIXME: gimp_busy HACK not really appropriate here because we only
|
||
* want to prevent the busy image and display to be closed. --Mitch
|
||
*/
|
||
if (gimage->gimp->busy)
|
||
return;
|
||
|
||
/* If the image has been modified, give the user a chance to save
|
||
* it before nuking it--this only applies if its the last view
|
||
* to an image canvas. (a gimage with disp_count = 1)
|
||
*/
|
||
if (! kill_it &&
|
||
gimage->disp_count == 1 &&
|
||
gimage->dirty &&
|
||
config->confirm_on_close)
|
||
{
|
||
gchar *basename;
|
||
|
||
basename = file_utils_uri_to_utf8_basename (gimp_image_get_uri (gimage));
|
||
|
||
gimp_display_shell_close_warning_dialog (shell, basename);
|
||
|
||
g_free (basename);
|
||
}
|
||
else
|
||
{
|
||
gimp_display_delete (shell->gdisp);
|
||
}
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_reconnect (GimpDisplayShell *shell)
|
||
{
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
g_return_if_fail (GIMP_IS_DISPLAY (shell->gdisp));
|
||
g_return_if_fail (GIMP_IS_IMAGE (shell->gdisp->gimage));
|
||
|
||
gimp_display_shell_connect (shell);
|
||
|
||
gimp_statusbar_resize_cursor (GIMP_STATUSBAR (shell->statusbar));
|
||
gimp_display_shell_shrink_wrap (shell);
|
||
|
||
g_signal_emit (G_OBJECT (shell), display_shell_signals[RECONNECT], 0);
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_scaled (GimpDisplayShell *shell)
|
||
{
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
|
||
g_signal_emit (G_OBJECT (shell), display_shell_signals[SCALED], 0);
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_scrolled (GimpDisplayShell *shell)
|
||
{
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
|
||
g_signal_emit (G_OBJECT (shell), display_shell_signals[SCROLLED], 0);
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_transform_coords (GimpDisplayShell *shell,
|
||
GimpCoords *image_coords,
|
||
GimpCoords *display_coords)
|
||
{
|
||
gdouble scalex;
|
||
gdouble scaley;
|
||
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
g_return_if_fail (image_coords != NULL);
|
||
g_return_if_fail (display_coords != NULL);
|
||
|
||
*display_coords = *image_coords;
|
||
|
||
scalex = SCALEFACTOR_X (shell);
|
||
scaley = SCALEFACTOR_Y (shell);
|
||
|
||
display_coords->x = scalex * image_coords->x;
|
||
display_coords->y = scaley * image_coords->y;
|
||
|
||
display_coords->x += - shell->offset_x + shell->disp_xoffset;
|
||
display_coords->y += - shell->offset_y + shell->disp_yoffset;
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_untransform_coords (GimpDisplayShell *shell,
|
||
GimpCoords *display_coords,
|
||
GimpCoords *image_coords)
|
||
{
|
||
gdouble scalex;
|
||
gdouble scaley;
|
||
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
g_return_if_fail (display_coords != NULL);
|
||
g_return_if_fail (image_coords != NULL);
|
||
|
||
*image_coords = *display_coords;
|
||
|
||
scalex = SCALEFACTOR_X (shell);
|
||
scaley = SCALEFACTOR_Y (shell);
|
||
|
||
image_coords->x = display_coords->x - shell->disp_xoffset + shell->offset_x;
|
||
image_coords->y = display_coords->y - shell->disp_yoffset + shell->offset_y;
|
||
|
||
image_coords->x /= scalex;
|
||
image_coords->y /= scaley;
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_transform_xy (GimpDisplayShell *shell,
|
||
gint x,
|
||
gint y,
|
||
gint *nx,
|
||
gint *ny,
|
||
gboolean use_offsets)
|
||
{
|
||
gdouble scalex;
|
||
gdouble scaley;
|
||
gint offset_x = 0;
|
||
gint offset_y = 0;
|
||
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
g_return_if_fail (nx != NULL);
|
||
g_return_if_fail (ny != NULL);
|
||
|
||
/* transform from image coordinates to screen coordinates */
|
||
scalex = SCALEFACTOR_X (shell);
|
||
scaley = SCALEFACTOR_Y (shell);
|
||
|
||
if (use_offsets)
|
||
gimp_drawable_offsets (gimp_image_active_drawable (shell->gdisp->gimage),
|
||
&offset_x, &offset_y);
|
||
|
||
*nx = (gint) (scalex * (x + offset_x) - shell->offset_x);
|
||
*ny = (gint) (scaley * (y + offset_y) - shell->offset_y);
|
||
|
||
*nx += shell->disp_xoffset;
|
||
*ny += shell->disp_yoffset;
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_untransform_xy (GimpDisplayShell *shell,
|
||
gint x,
|
||
gint y,
|
||
gint *nx,
|
||
gint *ny,
|
||
gboolean round,
|
||
gboolean use_offsets)
|
||
{
|
||
gdouble scalex;
|
||
gdouble scaley;
|
||
gint offset_x = 0;
|
||
gint offset_y = 0;
|
||
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
g_return_if_fail (nx != NULL);
|
||
g_return_if_fail (ny != NULL);
|
||
|
||
x -= shell->disp_xoffset;
|
||
y -= shell->disp_yoffset;
|
||
|
||
/* transform from screen coordinates to image coordinates */
|
||
scalex = SCALEFACTOR_X (shell);
|
||
scaley = SCALEFACTOR_Y (shell);
|
||
|
||
if (use_offsets)
|
||
gimp_drawable_offsets (gimp_image_active_drawable (shell->gdisp->gimage),
|
||
&offset_x, &offset_y);
|
||
|
||
if (round)
|
||
{
|
||
*nx = ROUND ((x + shell->offset_x) / scalex - offset_x);
|
||
*ny = ROUND ((y + shell->offset_y) / scaley - offset_y);
|
||
}
|
||
else
|
||
{
|
||
*nx = (gint) ((x + shell->offset_x) / scalex - offset_x);
|
||
*ny = (gint) ((y + shell->offset_y) / scaley - offset_y);
|
||
}
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_transform_xy_f (GimpDisplayShell *shell,
|
||
gdouble x,
|
||
gdouble y,
|
||
gdouble *nx,
|
||
gdouble *ny,
|
||
gboolean use_offsets)
|
||
{
|
||
gdouble scalex;
|
||
gdouble scaley;
|
||
gint offset_x = 0;
|
||
gint offset_y = 0;
|
||
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
g_return_if_fail (nx != NULL);
|
||
g_return_if_fail (ny != NULL);
|
||
|
||
/* transform from gimp coordinates to screen coordinates */
|
||
scalex = SCALEFACTOR_X (shell);
|
||
scaley = SCALEFACTOR_Y (shell);
|
||
|
||
if (use_offsets)
|
||
gimp_drawable_offsets (gimp_image_active_drawable (shell->gdisp->gimage),
|
||
&offset_x, &offset_y);
|
||
|
||
*nx = scalex * (x + offset_x) - shell->offset_x;
|
||
*ny = scaley * (y + offset_y) - shell->offset_y;
|
||
|
||
*nx += shell->disp_xoffset;
|
||
*ny += shell->disp_yoffset;
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_untransform_xy_f (GimpDisplayShell *shell,
|
||
gdouble x,
|
||
gdouble y,
|
||
gdouble *nx,
|
||
gdouble *ny,
|
||
gboolean use_offsets)
|
||
{
|
||
gdouble scalex;
|
||
gdouble scaley;
|
||
gint offset_x = 0;
|
||
gint offset_y = 0;
|
||
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
g_return_if_fail (nx != NULL);
|
||
g_return_if_fail (ny != NULL);
|
||
|
||
x -= shell->disp_xoffset;
|
||
y -= shell->disp_yoffset;
|
||
|
||
/* transform from screen coordinates to gimp coordinates */
|
||
scalex = SCALEFACTOR_X (shell);
|
||
scaley = SCALEFACTOR_Y (shell);
|
||
|
||
if (use_offsets)
|
||
gimp_drawable_offsets (gimp_image_active_drawable (shell->gdisp->gimage),
|
||
&offset_x, &offset_y);
|
||
|
||
*nx = (x + shell->offset_x) / scalex - offset_x;
|
||
*ny = (y + shell->offset_y) / scaley - offset_y;
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_set_menu_sensitivity (GimpDisplayShell *shell,
|
||
Gimp *gimp)
|
||
{
|
||
GtkItemFactory *item_factory;
|
||
GimpDisplay *gdisp = NULL;
|
||
GimpImage *gimage = NULL;
|
||
GimpImageType type = -1;
|
||
GimpDrawable *drawable = NULL;
|
||
GimpLayer *layer = NULL;
|
||
GimpRGB fg;
|
||
GimpRGB bg;
|
||
gboolean is_rgb = FALSE;
|
||
gboolean is_gray = FALSE;
|
||
gboolean is_indexed = FALSE;
|
||
gboolean fs = FALSE;
|
||
gboolean aux = FALSE;
|
||
gboolean lm = FALSE;
|
||
gboolean lp = FALSE;
|
||
gboolean sel = FALSE;
|
||
gboolean alpha = FALSE;
|
||
gint lind = -1;
|
||
gint lnum = -1;
|
||
|
||
g_return_if_fail (! shell || GIMP_IS_DISPLAY_SHELL (shell));
|
||
g_return_if_fail (GIMP_IS_GIMP (gimp));
|
||
|
||
if (shell)
|
||
gdisp = shell->gdisp;
|
||
|
||
if (gdisp)
|
||
{
|
||
GimpImageBaseType base_type;
|
||
|
||
gimage = gdisp->gimage;
|
||
|
||
base_type = gimp_image_base_type (gimage);
|
||
|
||
is_rgb = (base_type == GIMP_RGB);
|
||
is_gray = (base_type == GIMP_GRAY);
|
||
is_indexed = (base_type == GIMP_INDEXED);
|
||
|
||
fs = (gimp_image_floating_sel (gimage) != NULL);
|
||
aux = (gimp_image_get_active_channel (gimage) != NULL);
|
||
lp = ! gimp_image_is_empty (gimage);
|
||
sel = ! gimp_image_mask_is_empty (gimage);
|
||
|
||
drawable = gimp_image_active_drawable (gimage);
|
||
if (drawable)
|
||
type = gimp_drawable_type (drawable);
|
||
|
||
if (lp)
|
||
{
|
||
layer = gimp_image_get_active_layer (gimage);
|
||
|
||
if (layer)
|
||
{
|
||
lm = gimp_layer_get_mask (layer) ? TRUE : FALSE;
|
||
alpha = gimp_drawable_has_alpha (GIMP_DRAWABLE (layer));
|
||
lind = gimp_image_get_layer_index (gimage, layer);
|
||
}
|
||
|
||
lnum = gimp_container_num_children (gimage->layers);
|
||
}
|
||
|
||
}
|
||
|
||
gimp_context_get_foreground (gimp_get_user_context (gimp), &fg);
|
||
gimp_context_get_background (gimp_get_user_context (gimp), &bg);
|
||
|
||
item_factory = GTK_ITEM_FACTORY (gimp_item_factory_from_path ("<Image>"));
|
||
|
||
#define SET_ACTIVE(menu,condition) \
|
||
gimp_item_factory_set_active (item_factory, menu, (condition) != 0)
|
||
#define SET_LABEL(menu,label) \
|
||
gimp_item_factory_set_label (item_factory, menu, (label))
|
||
#define SET_SENSITIVE(menu,condition) \
|
||
gimp_item_factory_set_sensitive (item_factory, menu, (condition) != 0)
|
||
|
||
/* File */
|
||
|
||
SET_SENSITIVE ("/File/Save", gdisp && drawable);
|
||
SET_SENSITIVE ("/File/Save as...", gdisp && drawable);
|
||
SET_SENSITIVE ("/File/Save a Copy...", gdisp && drawable);
|
||
SET_SENSITIVE ("/File/Revert...", gdisp && GIMP_OBJECT (gimage)->name);
|
||
SET_SENSITIVE ("/File/Close", gdisp);
|
||
|
||
/* Edit */
|
||
|
||
{
|
||
gchar *undo_name = NULL;
|
||
gchar *redo_name = NULL;
|
||
|
||
if (gdisp && gimp_image_undo_is_enabled (gimage))
|
||
{
|
||
undo_name = (gchar *) undo_get_undo_name (gimage);
|
||
redo_name = (gchar *) undo_get_redo_name (gimage);
|
||
}
|
||
|
||
if (undo_name)
|
||
undo_name = g_strdup_printf (_("Undo %s"), gettext (undo_name));
|
||
|
||
if (redo_name)
|
||
redo_name = g_strdup_printf (_("Redo %s"), gettext (redo_name));
|
||
|
||
SET_LABEL ("/Edit/Undo", undo_name ? undo_name : _("Undo"));
|
||
SET_LABEL ("/Edit/Redo", redo_name ? redo_name : _("Redo"));
|
||
|
||
SET_SENSITIVE ("/Edit/Undo", undo_name);
|
||
SET_SENSITIVE ("/Edit/Redo", redo_name);
|
||
|
||
g_free (undo_name);
|
||
g_free (redo_name);
|
||
}
|
||
|
||
SET_SENSITIVE ("/Edit/Cut", lp);
|
||
SET_SENSITIVE ("/Edit/Copy", lp);
|
||
SET_SENSITIVE ("/Edit/Paste", gdisp && gimp->global_buffer);
|
||
SET_SENSITIVE ("/Edit/Paste Into", gdisp && gimp->global_buffer);
|
||
SET_SENSITIVE ("/Edit/Paste as New", gimp->global_buffer);
|
||
SET_SENSITIVE ("/Edit/Buffer/Cut Named...", lp);
|
||
SET_SENSITIVE ("/Edit/Buffer/Copy Named...", lp);
|
||
SET_SENSITIVE ("/Edit/Buffer/Paste Named...", lp);
|
||
SET_SENSITIVE ("/Edit/Clear", lp);
|
||
SET_SENSITIVE ("/Edit/Fill with FG Color", lp);
|
||
SET_SENSITIVE ("/Edit/Fill with BG Color", lp);
|
||
SET_SENSITIVE ("/Edit/Stroke", lp && sel);
|
||
|
||
/* Select */
|
||
|
||
SET_SENSITIVE ("/Select/Invert", lp && sel);
|
||
SET_SENSITIVE ("/Select/All", lp);
|
||
SET_SENSITIVE ("/Select/None", lp && sel);
|
||
SET_SENSITIVE ("/Select/Float", lp && sel);
|
||
SET_SENSITIVE ("/Select/Feather...", lp && sel);
|
||
SET_SENSITIVE ("/Select/Sharpen", lp && sel);
|
||
SET_SENSITIVE ("/Select/Shrink...", lp && sel);
|
||
SET_SENSITIVE ("/Select/Grow...", lp && sel);
|
||
SET_SENSITIVE ("/Select/Border...", lp && sel);
|
||
SET_SENSITIVE ("/Select/Toggle QuickMask", gdisp);
|
||
SET_SENSITIVE ("/Select/Save to Channel", lp && sel && !fs);
|
||
|
||
/* View */
|
||
|
||
SET_SENSITIVE ("/View/Zoom In", gdisp);
|
||
SET_SENSITIVE ("/View/Zoom Out", gdisp);
|
||
SET_SENSITIVE ("/View/Zoom to Fit Window", gdisp);
|
||
|
||
SET_SENSITIVE ("/View/Zoom/16:1", gdisp);
|
||
SET_SENSITIVE ("/View/Zoom/8:1", gdisp);
|
||
SET_SENSITIVE ("/View/Zoom/4:1", gdisp);
|
||
SET_SENSITIVE ("/View/Zoom/2:1", gdisp);
|
||
SET_SENSITIVE ("/View/Zoom/1:1", gdisp);
|
||
SET_SENSITIVE ("/View/Zoom/1:2", gdisp);
|
||
SET_SENSITIVE ("/View/Zoom/1:4", gdisp);
|
||
SET_SENSITIVE ("/View/Zoom/1:8", gdisp);
|
||
SET_SENSITIVE ("/View/Zoom/1:16", gdisp);
|
||
|
||
SET_SENSITIVE ("/View/Dot for Dot", gdisp);
|
||
SET_ACTIVE ("/View/Dot for Dot", gdisp && shell->dot_for_dot);
|
||
|
||
SET_SENSITIVE ("/View/Info Window...", gdisp);
|
||
SET_SENSITIVE ("/View/Navigation Window...", gdisp);
|
||
SET_SENSITIVE ("/View/Display Filters...", gdisp);
|
||
|
||
SET_SENSITIVE ("/View/Toggle Selection", gdisp);
|
||
SET_ACTIVE ("/View/Toggle Selection", gdisp && ! shell->select->hidden);
|
||
SET_SENSITIVE ("/View/Toggle Layer Boundary", gdisp);
|
||
SET_ACTIVE ("/View/Toggle Layer Boundary", gdisp && ! shell->select->layer_hidden);
|
||
|
||
SET_SENSITIVE ("/View/Toggle Guides", gdisp);
|
||
SET_ACTIVE ("/View/Toggle Guides", gdisp && gdisp->draw_guides);
|
||
SET_SENSITIVE ("/View/Snap to Guides", gdisp);
|
||
SET_ACTIVE ("/View/Snap to Guides", gdisp && gdisp->snap_to_guides);
|
||
|
||
SET_SENSITIVE ("/View/Toggle Rulers", gdisp);
|
||
SET_ACTIVE ("/View/Toggle Rulers",
|
||
gdisp && GTK_WIDGET_VISIBLE (shell->origin) ? 1 : 0);
|
||
|
||
SET_SENSITIVE ("/View/Toggle Statusbar", gdisp);
|
||
SET_ACTIVE ("/View/Toggle Statusbar",
|
||
gdisp && GTK_WIDGET_VISIBLE (shell->statusbar) ? 1 : 0);
|
||
|
||
SET_SENSITIVE ("/View/New View", gdisp);
|
||
SET_SENSITIVE ("/View/Shrink Wrap", gdisp);
|
||
|
||
/* Image */
|
||
|
||
SET_SENSITIVE ("/Image/Mode/RGB", gdisp && ! is_rgb);
|
||
SET_SENSITIVE ("/Image/Mode/Grayscale", gdisp && ! is_gray);
|
||
SET_SENSITIVE ("/Image/Mode/Indexed...", gdisp && ! is_indexed);
|
||
|
||
SET_SENSITIVE ("/Image/Canvas Size...", gdisp);
|
||
SET_SENSITIVE ("/Image/Scale Image...", gdisp);
|
||
SET_SENSITIVE ("/Image/Crop Image", gdisp && sel);
|
||
SET_SENSITIVE ("/Image/Duplicate", gdisp);
|
||
SET_SENSITIVE ("/Image/Merge Visible Layers...", gdisp && !fs && !aux && lp);
|
||
SET_SENSITIVE ("/Image/Flatten Image", gdisp && !fs && !aux && lp);
|
||
SET_SENSITIVE ("/Image/Undo History...", gdisp);
|
||
|
||
/* Layer */
|
||
|
||
SET_SENSITIVE ("/Layer/Stack/Previous Layer",
|
||
lp && !fs && !aux && lind > 0);
|
||
SET_SENSITIVE ("/Layer/Stack/Next Layer",
|
||
lp && !fs && !aux && lind < (lnum - 1));
|
||
SET_SENSITIVE ("/Layer/Stack/Raise Layer",
|
||
lp && !fs && !aux && alpha && lind > 0);
|
||
SET_SENSITIVE ("/Layer/Stack/Lower Layer",
|
||
lp && !fs && !aux && alpha && lind < (lnum - 1));
|
||
SET_SENSITIVE ("/Layer/Stack/Layer to Top",
|
||
lp && !fs && !aux && alpha && lind > 0);
|
||
SET_SENSITIVE ("/Layer/Stack/Layer to Bottom",
|
||
lp && !fs && !aux && alpha && lind < (lnum - 1));
|
||
|
||
SET_SENSITIVE ("/Layer/New Layer...", gdisp);
|
||
SET_SENSITIVE ("/Layer/Duplicate Layer", lp && !fs && !aux);
|
||
SET_SENSITIVE ("/Layer/Anchor Layer", lp && fs && !aux);
|
||
SET_SENSITIVE ("/Layer/Merge Down", lp && !fs && !aux);
|
||
SET_SENSITIVE ("/Layer/Delete Layer", lp && !aux);
|
||
|
||
SET_SENSITIVE ("/Layer/Layer Boundary Size...", lp && !aux);
|
||
SET_SENSITIVE ("/Layer/Layer to Imagesize", lp && !aux);
|
||
SET_SENSITIVE ("/Layer/Scale Layer...", lp && !aux);
|
||
SET_SENSITIVE ("/Layer/Crop Layer", lp && !aux && sel);
|
||
|
||
SET_SENSITIVE ("/Layer/Transform/Offset...", lp);
|
||
|
||
SET_SENSITIVE ("/Layer/Colors/Color Balance...", lp && is_rgb);
|
||
SET_SENSITIVE ("/Layer/Colors/Hue-Saturation...", lp && is_rgb);
|
||
SET_SENSITIVE ("/Layer/Colors/Brightness-Contrast...", lp && ! is_indexed);
|
||
SET_SENSITIVE ("/Layer/Colors/Threshold...", lp && ! is_indexed);
|
||
SET_SENSITIVE ("/Layer/Colors/Levels...", lp && ! is_indexed);
|
||
SET_SENSITIVE ("/Layer/Colors/Curves...", lp && ! is_indexed);
|
||
SET_SENSITIVE ("/Layer/Colors/Desaturate", lp && is_rgb);
|
||
SET_SENSITIVE ("/Layer/Colors/Posterize...", lp && ! is_indexed);
|
||
SET_SENSITIVE ("/Layer/Colors/Invert", lp && ! is_indexed);
|
||
SET_SENSITIVE ("/Layer/Colors/Auto/Equalize", lp && ! is_indexed);
|
||
SET_SENSITIVE ("/Layer/Colors/Histogram...", lp);
|
||
|
||
SET_SENSITIVE ("/Layer/Mask/Add Layer Mask...", lp && !aux && !lm && alpha && ! is_indexed);
|
||
SET_SENSITIVE ("/Layer/Mask/Apply Layer Mask", lp && !aux && lm);
|
||
SET_SENSITIVE ("/Layer/Mask/Delete Layer Mask", lp && !aux && lm);
|
||
SET_SENSITIVE ("/Layer/Mask/Mask to Selection", lp && !aux && lm);
|
||
|
||
SET_SENSITIVE ("/Layer/Alpha/Alpha to Selection", lp && !aux && alpha);
|
||
SET_SENSITIVE ("/Layer/Alpha/Add Alpha Channel", lp && !aux && !fs && !lm && !alpha);
|
||
|
||
#undef SET_ACTIVE
|
||
#undef SET_LABEL
|
||
#undef SET_SENSITIVE
|
||
|
||
plug_in_set_menu_sensitivity (type);
|
||
}
|
||
|
||
GimpGuide *
|
||
gimp_display_shell_find_guide (GimpDisplayShell *shell,
|
||
gdouble x,
|
||
gdouble y)
|
||
{
|
||
g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), NULL);
|
||
|
||
if (shell->gdisp->draw_guides)
|
||
{
|
||
gdouble image_x, image_y;
|
||
|
||
gimp_display_shell_untransform_xy_f (shell,
|
||
x, y,
|
||
&image_x, &image_y,
|
||
TRUE);
|
||
|
||
return gimp_image_find_guide (shell->gdisp->gimage,
|
||
(gint) image_x,
|
||
(gint) image_y);
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
gboolean
|
||
gimp_display_shell_snap_point (GimpDisplayShell *shell,
|
||
gdouble x,
|
||
gdouble y,
|
||
gdouble *tx,
|
||
gdouble *ty)
|
||
{
|
||
gboolean snapped = FALSE;
|
||
|
||
g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE);
|
||
g_return_val_if_fail (tx != NULL, FALSE);
|
||
g_return_val_if_fail (ty != NULL, FALSE);
|
||
|
||
*tx = x;
|
||
*ty = y;
|
||
|
||
if (shell->gdisp->draw_guides &&
|
||
shell->gdisp->snap_to_guides &&
|
||
shell->gdisp->gimage->guides)
|
||
{
|
||
gdouble image_x, image_y;
|
||
gint image_tx, image_ty;
|
||
|
||
gimp_display_shell_untransform_xy_f (shell,
|
||
x, y,
|
||
&image_x, &image_y,
|
||
TRUE);
|
||
|
||
snapped = gimp_image_snap_point (shell->gdisp->gimage,
|
||
(gint) image_x,
|
||
(gint) image_y,
|
||
&image_tx,
|
||
&image_ty);
|
||
|
||
if (snapped)
|
||
{
|
||
gimp_display_shell_transform_xy_f (shell,
|
||
(gdouble) image_tx,
|
||
(gdouble) image_ty,
|
||
tx, ty,
|
||
FALSE);
|
||
}
|
||
}
|
||
|
||
return snapped;
|
||
}
|
||
|
||
gboolean
|
||
gimp_display_shell_snap_rectangle (GimpDisplayShell *shell,
|
||
gdouble x1,
|
||
gdouble y1,
|
||
gdouble x2,
|
||
gdouble y2,
|
||
gdouble *tx1,
|
||
gdouble *ty1)
|
||
{
|
||
gdouble nx1, ny1;
|
||
gdouble nx2, ny2;
|
||
gboolean snap1, snap2;
|
||
|
||
g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE);
|
||
g_return_val_if_fail (tx1 != NULL, FALSE);
|
||
g_return_val_if_fail (ty1 != NULL, FALSE);
|
||
|
||
*tx1 = x1;
|
||
*ty1 = y1;
|
||
|
||
snap1 = gimp_display_shell_snap_point (shell, x1, y1, &nx1, &ny1);
|
||
snap2 = gimp_display_shell_snap_point (shell, x2, y2, &nx2, &ny2);
|
||
|
||
if (snap1 || snap2)
|
||
{
|
||
if (x1 != nx1)
|
||
*tx1 = nx1;
|
||
else if (x2 != nx2)
|
||
*tx1 = x1 + (nx2 - x2);
|
||
|
||
if (y1 != ny1)
|
||
*ty1 = ny1;
|
||
else if (y2 != ny2)
|
||
*ty1 = y1 + (ny2 - y2);
|
||
}
|
||
|
||
return snap1 || snap2;
|
||
}
|
||
|
||
gint
|
||
gimp_display_shell_mask_value (GimpDisplayShell *shell,
|
||
gint x,
|
||
gint y)
|
||
{
|
||
g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), 0);
|
||
|
||
/* move the coordinates from screen space to image space */
|
||
gimp_display_shell_untransform_xy (shell, x, y, &x, &y, FALSE, FALSE);
|
||
|
||
return gimp_image_mask_value (shell->gdisp->gimage, x, y);
|
||
}
|
||
|
||
gboolean
|
||
gimp_display_shell_mask_bounds (GimpDisplayShell *shell,
|
||
gint *x1,
|
||
gint *y1,
|
||
gint *x2,
|
||
gint *y2)
|
||
{
|
||
GimpLayer *layer;
|
||
gint off_x;
|
||
gint off_y;
|
||
|
||
g_return_val_if_fail (GIMP_IS_DISPLAY_SHELL (shell), FALSE);
|
||
g_return_val_if_fail (x1 != NULL, FALSE);
|
||
g_return_val_if_fail (y1 != NULL, FALSE);
|
||
g_return_val_if_fail (x2 != NULL, FALSE);
|
||
g_return_val_if_fail (y2 != NULL, FALSE);
|
||
|
||
/* If there is a floating selection, handle things differently */
|
||
if ((layer = gimp_image_floating_sel (shell->gdisp->gimage)))
|
||
{
|
||
gimp_drawable_offsets (GIMP_DRAWABLE (layer), &off_x, &off_y);
|
||
|
||
if (! gimp_channel_bounds (gimp_image_get_mask (shell->gdisp->gimage),
|
||
x1, y1, x2, y2))
|
||
{
|
||
*x1 = off_x;
|
||
*y1 = off_y;
|
||
*x2 = off_x + gimp_drawable_width (GIMP_DRAWABLE (layer));
|
||
*y2 = off_y + gimp_drawable_height (GIMP_DRAWABLE (layer));
|
||
}
|
||
else
|
||
{
|
||
*x1 = MIN (off_x, *x1);
|
||
*y1 = MIN (off_y, *y1);
|
||
*x2 = MAX (off_x + gimp_drawable_width (GIMP_DRAWABLE (layer)), *x2);
|
||
*y2 = MAX (off_y + gimp_drawable_height (GIMP_DRAWABLE (layer)), *y2);
|
||
}
|
||
}
|
||
else if (! gimp_channel_bounds (gimp_image_get_mask (shell->gdisp->gimage),
|
||
x1, y1, x2, y2))
|
||
{
|
||
return FALSE;
|
||
}
|
||
|
||
gimp_display_shell_transform_xy (shell, *x1, *y1, x1, y1, 0);
|
||
gimp_display_shell_transform_xy (shell, *x2, *y2, x2, y2, 0);
|
||
|
||
/* Make sure the extents are within bounds */
|
||
*x1 = CLAMP (*x1, 0, shell->disp_width);
|
||
*y1 = CLAMP (*y1, 0, shell->disp_height);
|
||
*x2 = CLAMP (*x2, 0, shell->disp_width);
|
||
*y2 = CLAMP (*y2, 0, shell->disp_height);
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_add_expose_area (GimpDisplayShell *shell,
|
||
gint x,
|
||
gint y,
|
||
gint w,
|
||
gint h)
|
||
{
|
||
GimpArea *area;
|
||
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
|
||
area = gimp_area_new (CLAMP (x, 0, shell->disp_width),
|
||
CLAMP (y, 0, shell->disp_height),
|
||
CLAMP (x + w, 0, shell->disp_width),
|
||
CLAMP (y + h, 0, shell->disp_height));
|
||
|
||
shell->display_areas = gimp_display_area_list_process (shell->display_areas,
|
||
area);
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_expose_guide (GimpDisplayShell *shell,
|
||
GimpGuide *guide)
|
||
{
|
||
gint x;
|
||
gint y;
|
||
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
g_return_if_fail (guide != NULL);
|
||
|
||
if (guide->position < 0)
|
||
return;
|
||
|
||
gimp_display_shell_transform_xy (shell,
|
||
guide->position,
|
||
guide->position,
|
||
&x, &y,
|
||
FALSE);
|
||
|
||
switch (guide->orientation)
|
||
{
|
||
case ORIENTATION_HORIZONTAL:
|
||
gimp_display_shell_add_expose_area (shell, 0, y, shell->disp_width, 1);
|
||
break;
|
||
|
||
case ORIENTATION_VERTICAL:
|
||
gimp_display_shell_add_expose_area (shell, x, 0, 1, shell->disp_height);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_expose_full (GimpDisplayShell *shell)
|
||
{
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
|
||
gimp_display_shell_add_expose_area (shell,
|
||
0, 0,
|
||
shell->disp_width,
|
||
shell->disp_height);
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_flush (GimpDisplayShell *shell)
|
||
{
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
|
||
if (shell->title_dirty)
|
||
{
|
||
gimp_display_shell_update_title (shell);
|
||
|
||
shell->title_dirty = FALSE;
|
||
}
|
||
|
||
/* update the gdisplay's info dialog */
|
||
info_window_update (shell->gdisp);
|
||
|
||
if (shell->display_areas)
|
||
{
|
||
GSList *list;
|
||
GimpArea *area;
|
||
|
||
/* stop the currently active tool */
|
||
tool_manager_control_active (shell->gdisp->gimage->gimp, PAUSE,
|
||
shell->gdisp);
|
||
|
||
for (list = shell->display_areas; list; list = g_slist_next (list))
|
||
{
|
||
/* Paint the area specified by the GimpArea */
|
||
|
||
area = (GimpArea *) list->data;
|
||
|
||
gimp_display_shell_display_area (shell,
|
||
area->x1,
|
||
area->y1,
|
||
(area->x2 - area->x1),
|
||
(area->y2 - area->y1));
|
||
}
|
||
|
||
/* Free the update lists */
|
||
shell->display_areas = gimp_display_area_list_free (shell->display_areas);
|
||
|
||
/* draw the guides */
|
||
gimp_display_shell_draw_guides (shell);
|
||
|
||
/* and the cursor (if we have a software cursor) */
|
||
if (shell->have_cursor)
|
||
gimp_display_shell_draw_cursor (shell);
|
||
|
||
/* restart (and recalculate) the selection boundaries */
|
||
gimp_display_shell_selection_start (shell->select, TRUE);
|
||
|
||
/* start the currently active tool */
|
||
tool_manager_control_active (shell->gdisp->gimage->gimp, RESUME,
|
||
shell->gdisp);
|
||
}
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_set_cursor (GimpDisplayShell *shell,
|
||
GdkCursorType cursor_type,
|
||
GimpToolCursorType tool_cursor,
|
||
GimpCursorModifier modifier)
|
||
{
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
|
||
if (! shell->using_override_cursor)
|
||
{
|
||
gimp_display_shell_real_set_cursor (shell,
|
||
cursor_type,
|
||
tool_cursor,
|
||
modifier,
|
||
FALSE);
|
||
}
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_set_override_cursor (GimpDisplayShell *shell,
|
||
GdkCursorType cursor_type)
|
||
{
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
|
||
if (! shell->using_override_cursor ||
|
||
(shell->using_override_cursor &&
|
||
shell->override_cursor != cursor_type))
|
||
{
|
||
GdkCursor *cursor;
|
||
|
||
shell->override_cursor = cursor_type;
|
||
shell->using_override_cursor = TRUE;
|
||
|
||
cursor = gimp_cursor_new (cursor_type,
|
||
GIMP_TOOL_CURSOR_NONE,
|
||
GIMP_CURSOR_MODIFIER_NONE);
|
||
gdk_window_set_cursor (shell->canvas->window, cursor);
|
||
gdk_cursor_unref (cursor);
|
||
}
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_unset_override_cursor (GimpDisplayShell *shell)
|
||
{
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
|
||
if (shell->using_override_cursor)
|
||
{
|
||
shell->using_override_cursor = FALSE;
|
||
|
||
gimp_display_shell_real_set_cursor (shell,
|
||
shell->current_cursor,
|
||
shell->tool_cursor,
|
||
shell->cursor_modifier,
|
||
TRUE);
|
||
}
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_update_cursor (GimpDisplayShell *shell,
|
||
gint x,
|
||
gint y)
|
||
{
|
||
GimpImage *gimage;
|
||
gboolean new_cursor;
|
||
gboolean flush = FALSE;
|
||
gint t_x = -1;
|
||
gint t_y = -1;
|
||
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
|
||
gimage = shell->gdisp->gimage;
|
||
|
||
new_cursor = (shell->draw_cursor &&
|
||
shell->proximity &&
|
||
x > 0 &&
|
||
y > 0);
|
||
|
||
/* Erase old cursor, if necessary */
|
||
|
||
if (shell->have_cursor && (! new_cursor ||
|
||
x != shell->cursor_x ||
|
||
y != shell->cursor_y))
|
||
{
|
||
gimp_display_shell_add_expose_area (shell,
|
||
shell->cursor_x - 7,
|
||
shell->cursor_y - 7,
|
||
15, 15);
|
||
if (! new_cursor)
|
||
{
|
||
shell->have_cursor = FALSE;
|
||
flush = TRUE;
|
||
}
|
||
}
|
||
|
||
shell->have_cursor = new_cursor;
|
||
shell->cursor_x = x;
|
||
shell->cursor_y = y;
|
||
|
||
if (new_cursor || flush)
|
||
{
|
||
gimp_display_shell_flush (shell);
|
||
}
|
||
|
||
if (x > 0 && y > 0)
|
||
{
|
||
gimp_display_shell_untransform_xy (shell, x, y, &t_x, &t_y, FALSE, FALSE);
|
||
}
|
||
|
||
gimp_statusbar_update_cursor (GIMP_STATUSBAR (shell->statusbar), t_x, t_y);
|
||
|
||
if (t_x < 0 ||
|
||
t_y < 0 ||
|
||
t_x >= gimage->width ||
|
||
t_y >= gimage->height)
|
||
{
|
||
info_window_update_extended (shell->gdisp, -1, -1);
|
||
}
|
||
else
|
||
{
|
||
info_window_update_extended (shell->gdisp, t_x, t_y);
|
||
}
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_update_title (GimpDisplayShell *shell)
|
||
{
|
||
/* FIXME!! */
|
||
GimpDisplayConfig *config = GIMP_DISPLAY_CONFIG (the_gimp->config);
|
||
|
||
gchar title[MAX_TITLE_BUF];
|
||
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
|
||
/* format the title */
|
||
gimp_display_shell_format_title (shell, title, sizeof (title),
|
||
config->image_title_format);
|
||
gdk_window_set_title (GTK_WIDGET (shell)->window, title);
|
||
|
||
/* format the statusbar */
|
||
if (strcmp (config->image_title_format, config->image_status_format))
|
||
{
|
||
gimp_display_shell_format_title (shell, title, sizeof (title),
|
||
config->image_status_format);
|
||
}
|
||
|
||
gimp_statusbar_pop (GIMP_STATUSBAR (shell->statusbar), "title");
|
||
gimp_statusbar_push (GIMP_STATUSBAR (shell->statusbar), "title", title);
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_update_icon (GimpDisplayShell *shell)
|
||
{
|
||
GdkPixbuf *pixbuf;
|
||
gint width, height;
|
||
gdouble factor;
|
||
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
|
||
factor = ((gdouble) gimp_image_get_height (shell->gdisp->gimage) /
|
||
(gdouble) gimp_image_get_width (shell->gdisp->gimage));
|
||
|
||
if (factor >= 1)
|
||
{
|
||
height = MAX (shell->icon_size, 1);
|
||
width = MAX (((gdouble) shell->icon_size) / factor, 1);
|
||
}
|
||
else
|
||
{
|
||
height = MAX (((gdouble) shell->icon_size) * factor, 1);
|
||
width = MAX (shell->icon_size, 1);
|
||
}
|
||
|
||
pixbuf = gimp_viewable_get_new_preview_pixbuf (GIMP_VIEWABLE (shell->gdisp->gimage),
|
||
width, height);
|
||
|
||
gtk_window_set_icon (GTK_WINDOW (shell), pixbuf);
|
||
|
||
g_object_unref (G_OBJECT (pixbuf));
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_draw_guide (GimpDisplayShell *shell,
|
||
GimpGuide *guide,
|
||
gboolean active)
|
||
{
|
||
static GdkGC *normal_hgc = NULL;
|
||
static GdkGC *active_hgc = NULL;
|
||
static GdkGC *normal_vgc = NULL;
|
||
static GdkGC *active_vgc = NULL;
|
||
static gboolean initialized = FALSE;
|
||
gint x1, x2;
|
||
gint y1, y2;
|
||
gint w, h;
|
||
gint x, y;
|
||
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
g_return_if_fail (guide != NULL);
|
||
|
||
if (guide->position < 0)
|
||
return;
|
||
|
||
if (! initialized)
|
||
{
|
||
GdkGCValues values;
|
||
GdkColor fg;
|
||
GdkColor bg;
|
||
|
||
const gchar stipple[] =
|
||
{
|
||
0xF0, /* ####---- */
|
||
0xE1, /* ###----# */
|
||
0xC3, /* ##----## */
|
||
0x87, /* #----### */
|
||
0x0F, /* ----#### */
|
||
0x1E, /* ---####- */
|
||
0x3C, /* --####-- */
|
||
0x78, /* -####--- */
|
||
};
|
||
|
||
initialized = TRUE;
|
||
|
||
{
|
||
fg.red = 0x0;
|
||
fg.green = 0x0;
|
||
fg.blue = 0x0;
|
||
|
||
bg.red = 0x0;
|
||
bg.green = 0x7f7f;
|
||
bg.blue = 0xffff;
|
||
|
||
values.fill = GDK_OPAQUE_STIPPLED;
|
||
values.stipple = gdk_bitmap_create_from_data (shell->canvas->window,
|
||
(gchar *) stipple, 8, 1);
|
||
normal_hgc = gdk_gc_new_with_values (shell->canvas->window, &values,
|
||
GDK_GC_FILL |
|
||
GDK_GC_STIPPLE);
|
||
|
||
gdk_gc_set_rgb_fg_color (normal_hgc, &fg);
|
||
gdk_gc_set_rgb_bg_color (normal_hgc, &bg);
|
||
|
||
values.fill = GDK_OPAQUE_STIPPLED;
|
||
values.stipple = gdk_bitmap_create_from_data (shell->canvas->window,
|
||
(gchar *) stipple, 1, 8);
|
||
normal_vgc = gdk_gc_new_with_values (shell->canvas->window, &values,
|
||
GDK_GC_FILL |
|
||
GDK_GC_STIPPLE);
|
||
|
||
gdk_gc_set_rgb_fg_color (normal_vgc, &fg);
|
||
gdk_gc_set_rgb_bg_color (normal_vgc, &bg);
|
||
}
|
||
|
||
{
|
||
fg.red = 0x0;
|
||
fg.green = 0x0;
|
||
fg.blue = 0x0;
|
||
|
||
bg.red = 0xffff;
|
||
bg.green = 0x0;
|
||
bg.blue = 0x0;
|
||
|
||
values.fill = GDK_OPAQUE_STIPPLED;
|
||
values.stipple = gdk_bitmap_create_from_data (shell->canvas->window,
|
||
(gchar *) stipple, 8, 1);
|
||
active_hgc = gdk_gc_new_with_values (shell->canvas->window, &values,
|
||
GDK_GC_FILL |
|
||
GDK_GC_STIPPLE);
|
||
|
||
gdk_gc_set_rgb_fg_color (active_hgc, &fg);
|
||
gdk_gc_set_rgb_bg_color (active_hgc, &bg);
|
||
|
||
values.fill = GDK_OPAQUE_STIPPLED;
|
||
values.stipple = gdk_bitmap_create_from_data (shell->canvas->window,
|
||
(gchar *) stipple, 1, 8);
|
||
active_vgc = gdk_gc_new_with_values (shell->canvas->window, &values,
|
||
GDK_GC_FILL |
|
||
GDK_GC_STIPPLE);
|
||
|
||
gdk_gc_set_rgb_fg_color (active_vgc, &fg);
|
||
gdk_gc_set_rgb_bg_color (active_vgc, &bg);
|
||
}
|
||
}
|
||
|
||
gimp_display_shell_transform_xy (shell, 0, 0, &x1, &y1, FALSE);
|
||
gimp_display_shell_transform_xy (shell,
|
||
shell->gdisp->gimage->width,
|
||
shell->gdisp->gimage->height,
|
||
&x2, &y2, FALSE);
|
||
gdk_drawable_get_size (shell->canvas->window, &w, &h);
|
||
|
||
if (x1 < 0) x1 = 0;
|
||
if (y1 < 0) y1 = 0;
|
||
if (x2 > w) x2 = w;
|
||
if (y2 > h) y2 = h;
|
||
|
||
if (guide->orientation == ORIENTATION_HORIZONTAL)
|
||
{
|
||
gimp_display_shell_transform_xy (shell,
|
||
0, guide->position, &x, &y, FALSE);
|
||
|
||
if (active)
|
||
gdk_draw_line (shell->canvas->window, active_hgc, x1, y, x2, y);
|
||
else
|
||
gdk_draw_line (shell->canvas->window, normal_hgc, x1, y, x2, y);
|
||
}
|
||
else if (guide->orientation == ORIENTATION_VERTICAL)
|
||
{
|
||
gimp_display_shell_transform_xy (shell,
|
||
guide->position, 0, &x, &y, FALSE);
|
||
|
||
if (active)
|
||
gdk_draw_line (shell->canvas->window, active_vgc, x, y1, x, y2);
|
||
else
|
||
gdk_draw_line (shell->canvas->window, normal_vgc, x, y1, x, y2);
|
||
}
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_draw_guides (GimpDisplayShell *shell)
|
||
{
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
|
||
if (shell->gdisp->draw_guides)
|
||
{
|
||
GList *list;
|
||
GimpGuide *guide;
|
||
|
||
for (list = shell->gdisp->gimage->guides; list; list = g_list_next (list))
|
||
{
|
||
guide = (GimpGuide *) list->data;
|
||
|
||
gimp_display_shell_draw_guide (shell, guide, FALSE);
|
||
}
|
||
}
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_shrink_wrap (GimpDisplayShell *shell)
|
||
{
|
||
/*
|
||
* I'm pretty sure this assumes that the current size is < display size
|
||
* Is this a valid assumption?
|
||
*/
|
||
GtkAllocation allocation;
|
||
gint disp_width, disp_height;
|
||
gint width, height;
|
||
gint shell_x, shell_y;
|
||
gint shell_width, shell_height;
|
||
gint max_auto_width, max_auto_height;
|
||
gint border_x, border_y;
|
||
gint s_width, s_height;
|
||
gboolean resize = FALSE;
|
||
|
||
s_width = gdk_screen_width ();
|
||
s_height = gdk_screen_height ();
|
||
|
||
width = SCALEX (shell, shell->gdisp->gimage->width);
|
||
height = SCALEY (shell, shell->gdisp->gimage->height);
|
||
|
||
disp_width = shell->disp_width;
|
||
disp_height = shell->disp_height;
|
||
|
||
shell_width = GTK_WIDGET (shell)->allocation.width;
|
||
shell_height = GTK_WIDGET (shell)->allocation.height;
|
||
|
||
border_x = shell_width - disp_width;
|
||
border_y = shell_height - disp_height;
|
||
|
||
max_auto_width = (s_width - border_x) * 0.75;
|
||
max_auto_height = (s_height - border_y) * 0.75;
|
||
|
||
allocation.x = 0;
|
||
allocation.y = 0;
|
||
|
||
/* If one of the display dimensions has changed and one of the
|
||
* dimensions fits inside the screen
|
||
*/
|
||
if (((width + border_x) < s_width || (height + border_y) < s_height) &&
|
||
(width != disp_width || height != disp_height))
|
||
{
|
||
width = ((width + border_x) < s_width) ? width : max_auto_width;
|
||
height = ((height + border_y) < s_height) ? height : max_auto_height;
|
||
|
||
resize = TRUE;
|
||
}
|
||
/* If the projected dimension is greater than current, but less than
|
||
* 3/4 of the screen size, expand automagically
|
||
*/
|
||
else if ((width > disp_width || height > disp_height) &&
|
||
(disp_width < max_auto_width || disp_height < max_auto_height))
|
||
{
|
||
width = MIN (max_auto_width, width);
|
||
height = MIN (max_auto_height, height);
|
||
|
||
resize = TRUE;
|
||
}
|
||
|
||
if (resize)
|
||
{
|
||
if (width < shell->statusbar->requisition.width)
|
||
{
|
||
width = shell->statusbar->requisition.width;
|
||
}
|
||
|
||
#undef RESIZE_DEBUG
|
||
#ifdef RESIZE_DEBUG
|
||
g_print ("1w:%d/%d d:%d/%d s:%d/%d b:%d/%d\n",
|
||
width, height,
|
||
disp_width, disp_height,
|
||
shell_width, shell_height,
|
||
border_x, border_y);
|
||
#endif /* RESIZE_DEBUG */
|
||
|
||
shell->disp_width = width;
|
||
shell->disp_height = height;
|
||
|
||
allocation.width = width + border_x;
|
||
allocation.height = height + border_y;
|
||
|
||
/* block the resulting expose event on any of the following
|
||
* changes because our caller has to do a full display update anyway
|
||
*/
|
||
g_signal_handlers_block_by_func (G_OBJECT (shell->canvas),
|
||
gimp_display_shell_canvas_expose,
|
||
shell);
|
||
|
||
gtk_widget_size_allocate (GTK_WIDGET (shell), &allocation);
|
||
|
||
gdk_window_resize (GTK_WIDGET (shell)->window,
|
||
allocation.width,
|
||
allocation.height);
|
||
|
||
/* let Gtk/X/WM position the window */
|
||
while (gtk_events_pending ())
|
||
gtk_main_iteration ();
|
||
|
||
gdk_window_get_origin (GTK_WIDGET (shell)->window, &shell_x, &shell_y);
|
||
|
||
/* if the window is offscreen, center it... */
|
||
if (shell_x > s_width || shell_y > s_height ||
|
||
(shell_x + width + border_x) < 0 || (shell_y + height + border_y) < 0)
|
||
{
|
||
shell_x = (s_width - width - border_x) >> 1;
|
||
shell_y = (s_height - height - border_y) >> 1;
|
||
|
||
gdk_window_move (GTK_WIDGET (shell)->window, shell_x, shell_y);
|
||
}
|
||
|
||
g_signal_handlers_unblock_by_func (G_OBJECT (shell->canvas),
|
||
gimp_display_shell_canvas_expose,
|
||
shell);
|
||
}
|
||
|
||
/* If the width or height of the display has changed, recalculate
|
||
* the display offsets...
|
||
*/
|
||
if (disp_width != shell->disp_width ||
|
||
disp_height != shell->disp_height)
|
||
{
|
||
shell->offset_x += (disp_width - shell->disp_width) / 2;
|
||
shell->offset_y += (disp_height - shell->disp_height) / 2;
|
||
}
|
||
}
|
||
|
||
void
|
||
gimp_display_shell_selection_visibility (GimpDisplayShell *shell,
|
||
GimpSelectionControl control)
|
||
{
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
|
||
if (shell->select)
|
||
{
|
||
switch (control)
|
||
{
|
||
case GIMP_SELECTION_OFF:
|
||
gimp_display_shell_selection_invis (shell->select);
|
||
break;
|
||
case GIMP_SELECTION_LAYER_OFF:
|
||
gimp_display_shell_selection_layer_invis (shell->select);
|
||
break;
|
||
case GIMP_SELECTION_ON:
|
||
gimp_display_shell_selection_start (shell->select, TRUE);
|
||
break;
|
||
case GIMP_SELECTION_PAUSE:
|
||
gimp_display_shell_selection_pause (shell->select);
|
||
break;
|
||
case GIMP_SELECTION_RESUME:
|
||
gimp_display_shell_selection_resume (shell->select);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/* private functions */
|
||
|
||
static gpointer
|
||
gimp_display_shell_get_accel_context (gpointer data)
|
||
{
|
||
GimpDisplayShell *shell;
|
||
|
||
shell = (GimpDisplayShell *) data;
|
||
|
||
if (shell)
|
||
return shell->gdisp->gimage;
|
||
|
||
return NULL;
|
||
}
|
||
|
||
static void
|
||
gimp_display_shell_display_area (GimpDisplayShell *shell,
|
||
gint x,
|
||
gint y,
|
||
gint w,
|
||
gint h)
|
||
{
|
||
gint sx, sy;
|
||
gint x1, y1;
|
||
gint x2, y2;
|
||
gint dx, dy;
|
||
gint i, j;
|
||
|
||
sx = SCALEX (shell, shell->gdisp->gimage->width);
|
||
sy = SCALEY (shell, shell->gdisp->gimage->height);
|
||
|
||
/* Bounds check */
|
||
x1 = CLAMP (x, 0, shell->disp_width);
|
||
y1 = CLAMP (y, 0, shell->disp_height);
|
||
x2 = CLAMP (x + w, 0, shell->disp_width);
|
||
y2 = CLAMP (y + h, 0, shell->disp_height);
|
||
|
||
if (y1 < shell->disp_yoffset)
|
||
{
|
||
gdk_draw_rectangle (shell->canvas->window,
|
||
shell->padding_gc,
|
||
TRUE,
|
||
x, y,
|
||
w, shell->disp_yoffset - y);
|
||
/* X X X
|
||
. # .
|
||
. . . */
|
||
|
||
y1 = shell->disp_yoffset;
|
||
}
|
||
|
||
if (x1 < shell->disp_xoffset)
|
||
{
|
||
gdk_draw_rectangle (shell->canvas->window,
|
||
shell->padding_gc,
|
||
TRUE,
|
||
x, y1,
|
||
shell->disp_xoffset - x, h);
|
||
/* . . .
|
||
X # .
|
||
X . . */
|
||
|
||
x1 = shell->disp_xoffset;
|
||
}
|
||
|
||
if (x2 > (shell->disp_xoffset + sx))
|
||
{
|
||
gdk_draw_rectangle (shell->canvas->window,
|
||
shell->padding_gc,
|
||
TRUE,
|
||
shell->disp_xoffset + sx, y1,
|
||
x2 - (shell->disp_xoffset + sx), h - (y1 - y));
|
||
/* . . .
|
||
. # X
|
||
. . X */
|
||
|
||
x2 = shell->disp_xoffset + sx;
|
||
}
|
||
|
||
if (y2 > (shell->disp_yoffset + sy))
|
||
{
|
||
gdk_draw_rectangle (shell->canvas->window,
|
||
shell->padding_gc,
|
||
TRUE,
|
||
x1, shell->disp_yoffset + sy,
|
||
x2 - x1, y2 - (shell->disp_yoffset + sy));
|
||
/* . . .
|
||
. # .
|
||
. X . */
|
||
|
||
y2 = shell->disp_yoffset + sy;
|
||
}
|
||
|
||
/* display the image in RENDER_BUF_WIDTH x RENDER_BUF_HEIGHT sized chunks */
|
||
for (i = y1; i < y2; i += GIMP_DISPLAY_SHELL_RENDER_BUF_HEIGHT)
|
||
{
|
||
for (j = x1; j < x2; j += GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH)
|
||
{
|
||
dx = MIN (x2 - j, GIMP_DISPLAY_SHELL_RENDER_BUF_WIDTH);
|
||
dy = MIN (y2 - i, GIMP_DISPLAY_SHELL_RENDER_BUF_HEIGHT);
|
||
|
||
gimp_display_shell_render (shell,
|
||
j - shell->disp_xoffset,
|
||
i - shell->disp_yoffset,
|
||
dx, dy);
|
||
|
||
#if 0
|
||
/* Invalidate the projection just after we render it! */
|
||
gimp_image_invalidate_without_render (shell->gdisp->gimage,
|
||
j - shell->disp_xoffset,
|
||
i - shell->disp_yoffset,
|
||
dx, dy,
|
||
0, 0, 0, 0);
|
||
#endif
|
||
}
|
||
}
|
||
}
|
||
|
||
static void
|
||
gimp_display_shell_real_set_cursor (GimpDisplayShell *shell,
|
||
GdkCursorType cursor_type,
|
||
GimpToolCursorType tool_cursor,
|
||
GimpCursorModifier modifier,
|
||
gboolean always_install)
|
||
{
|
||
/* FIXME!! */
|
||
GimpDisplayConfig *config = GIMP_DISPLAY_CONFIG (the_gimp->config);
|
||
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
|
||
if (cursor_type != GIMP_BAD_CURSOR)
|
||
{
|
||
switch (config->cursor_mode)
|
||
{
|
||
case GIMP_CURSOR_MODE_TOOL_ICON:
|
||
break;
|
||
|
||
case GIMP_CURSOR_MODE_TOOL_CROSSHAIR:
|
||
cursor_type = GIMP_CROSSHAIR_SMALL_CURSOR;
|
||
break;
|
||
|
||
case GIMP_CURSOR_MODE_CROSSHAIR:
|
||
cursor_type = GIMP_CROSSHAIR_CURSOR;
|
||
tool_cursor = GIMP_TOOL_CURSOR_NONE;
|
||
modifier = GIMP_CURSOR_MODIFIER_NONE;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if (shell->current_cursor != cursor_type ||
|
||
shell->tool_cursor != tool_cursor ||
|
||
shell->cursor_modifier != modifier ||
|
||
always_install)
|
||
{
|
||
GdkCursor *cursor;
|
||
|
||
shell->current_cursor = cursor_type;
|
||
shell->tool_cursor = tool_cursor;
|
||
shell->cursor_modifier = modifier;
|
||
|
||
cursor = gimp_cursor_new (cursor_type,
|
||
tool_cursor,
|
||
modifier);
|
||
gdk_window_set_cursor (shell->canvas->window, cursor);
|
||
gdk_cursor_unref (cursor);
|
||
}
|
||
}
|
||
|
||
static void
|
||
gimp_display_shell_draw_cursor (GimpDisplayShell *shell)
|
||
{
|
||
gint x, y;
|
||
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
|
||
x = shell->cursor_x;
|
||
y = shell->cursor_y;
|
||
|
||
gdk_draw_line (shell->canvas->window,
|
||
shell->canvas->style->white_gc,
|
||
x - 7, y-1, x + 7, y-1);
|
||
gdk_draw_line (shell->canvas->window,
|
||
shell->canvas->style->black_gc,
|
||
x - 7, y, x + 7, y);
|
||
gdk_draw_line (shell->canvas->window,
|
||
shell->canvas->style->white_gc,
|
||
x - 7, y+1, x + 7, y+1);
|
||
gdk_draw_line (shell->canvas->window,
|
||
shell->canvas->style->white_gc,
|
||
x-1, y - 7, x-1, y + 7);
|
||
gdk_draw_line (shell->canvas->window,
|
||
shell->canvas->style->black_gc,
|
||
x, y - 7, x, y + 7);
|
||
gdk_draw_line (shell->canvas->window,
|
||
shell->canvas->style->white_gc,
|
||
x+1, y - 7, x+1, y + 7);
|
||
}
|
||
|
||
static gint print (gchar *buf,
|
||
gint len,
|
||
gint start,
|
||
const gchar *fmt,
|
||
...) G_GNUC_PRINTF (4, 5);
|
||
|
||
static gint
|
||
print (gchar *buf,
|
||
gint len,
|
||
gint start,
|
||
const gchar *fmt,
|
||
...)
|
||
{
|
||
va_list args;
|
||
gint printed;
|
||
|
||
va_start (args, fmt);
|
||
|
||
printed = g_vsnprintf (buf + start, len - start, fmt, args);
|
||
if (printed < 0)
|
||
printed = len - start;
|
||
|
||
va_end (args);
|
||
|
||
return printed;
|
||
}
|
||
|
||
static void
|
||
gimp_display_shell_format_title (GimpDisplayShell *shell,
|
||
gchar *title,
|
||
gint title_len,
|
||
const gchar *format)
|
||
{
|
||
GimpImage *gimage;
|
||
gchar *image_type_str = NULL;
|
||
gboolean empty;
|
||
gint i;
|
||
gchar unit_format[8];
|
||
|
||
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
|
||
|
||
gimage = shell->gdisp->gimage;
|
||
|
||
empty = gimp_image_is_empty (gimage);
|
||
|
||
switch (gimp_image_base_type (gimage))
|
||
{
|
||
case GIMP_RGB:
|
||
image_type_str = empty ? _("RGB-empty") : _("RGB");
|
||
break;
|
||
case GIMP_GRAY:
|
||
image_type_str = empty ? _("grayscale-empty") : _("grayscale");
|
||
break;
|
||
case GIMP_INDEXED:
|
||
image_type_str = empty ? _("indexed-empty") : _("indexed");
|
||
break;
|
||
default:
|
||
g_assert_not_reached ();
|
||
break;
|
||
}
|
||
|
||
i = 0;
|
||
|
||
while (i < title_len && *format)
|
||
{
|
||
switch (*format)
|
||
{
|
||
case '%':
|
||
format++;
|
||
switch (*format)
|
||
{
|
||
case 0:
|
||
g_warning ("image-title-format string ended within %%-sequence");
|
||
break;
|
||
|
||
case '%':
|
||
title[i++] = '%';
|
||
break;
|
||
|
||
case 'f': /* pruned filename */
|
||
{
|
||
gchar *basename;
|
||
|
||
basename = file_utils_uri_to_utf8_basename (gimp_image_get_uri (gimage));
|
||
|
||
i += print (title, title_len, i, "%s", basename);
|
||
|
||
g_free (basename);
|
||
}
|
||
break;
|
||
|
||
case 'F': /* full filename */
|
||
{
|
||
gchar *filename;
|
||
|
||
filename = file_utils_uri_to_utf8_filename (gimp_image_get_uri (gimage));
|
||
|
||
i += print (title, title_len, i, "%s", filename);
|
||
|
||
g_free (filename);
|
||
}
|
||
break;
|
||
|
||
case 'p': /* PDB id */
|
||
i += print (title, title_len, i, "%d", gimp_image_get_ID (gimage));
|
||
break;
|
||
|
||
case 'i': /* instance */
|
||
i += print (title, title_len, i, "%d", shell->gdisp->instance);
|
||
break;
|
||
|
||
case 't': /* type */
|
||
i += print (title, title_len, i, "%s", image_type_str);
|
||
break;
|
||
|
||
case 's': /* user source zoom factor */
|
||
i += print (title, title_len, i, "%d", SCALESRC (shell));
|
||
break;
|
||
|
||
case 'd': /* user destination zoom factor */
|
||
i += print (title, title_len, i, "%d", SCALEDEST (shell));
|
||
break;
|
||
|
||
case 'z': /* user zoom factor (percentage) */
|
||
i += print (title, title_len, i, "%d",
|
||
100 * SCALEDEST (shell) / SCALESRC (shell));
|
||
break;
|
||
|
||
case 'D': /* dirty flag */
|
||
if (format[1] == 0)
|
||
{
|
||
g_warning ("image-title-format string ended within "
|
||
"%%D-sequence");
|
||
break;
|
||
}
|
||
if (gimage->dirty)
|
||
title[i++] = format[1];
|
||
format++;
|
||
break;
|
||
|
||
case 'C': /* clean flag */
|
||
if (format[1] == 0)
|
||
{
|
||
g_warning ("image-title-format string ended within "
|
||
"%%C-sequence");
|
||
break;
|
||
}
|
||
if (! gimage->dirty)
|
||
title[i++] = format[1];
|
||
format++;
|
||
break;
|
||
|
||
case 'm': /* memory used by image */
|
||
{
|
||
gsize memsize;
|
||
gchar *size_str;
|
||
|
||
memsize = gimp_object_get_memsize (GIMP_OBJECT (gimage));
|
||
|
||
size_str = gimp_image_new_get_memsize_string (memsize);
|
||
|
||
i += print (title, title_len, i, "%s", size_str);
|
||
|
||
g_free (size_str);
|
||
}
|
||
break;
|
||
|
||
case 'l': /* number of layers */
|
||
i += print (title, title_len, i, "%d",
|
||
gimp_container_num_children (gimage->layers));
|
||
break;
|
||
|
||
case 'L': /* active drawable name */
|
||
{
|
||
GimpDrawable *drawable;
|
||
|
||
drawable = gimp_image_active_drawable (gimage);
|
||
|
||
if (drawable)
|
||
i += print (title, title_len, i, "%s",
|
||
gimp_object_get_name (GIMP_OBJECT (drawable)));
|
||
else
|
||
i += print (title, title_len, i, "%s", "(none)");
|
||
}
|
||
break;
|
||
|
||
case 'w': /* width in pixels */
|
||
i += print (title, title_len, i, "%d", gimage->width);
|
||
break;
|
||
|
||
case 'W': /* width in real-world units */
|
||
g_snprintf (unit_format, sizeof (unit_format), "%%.%df",
|
||
gimp_unit_get_digits (gimage->unit) + 1);
|
||
i += print (title, title_len, i, unit_format,
|
||
(gimage->width *
|
||
gimp_unit_get_factor (gimage->unit) /
|
||
gimage->xresolution));
|
||
break;
|
||
|
||
case 'h': /* height in pixels */
|
||
i += print (title, title_len, i, "%d", gimage->height);
|
||
break;
|
||
|
||
case 'H': /* height in real-world units */
|
||
g_snprintf (unit_format, sizeof (unit_format), "%%.%df",
|
||
gimp_unit_get_digits (gimage->unit) + 1);
|
||
i += print (title, title_len, i, unit_format,
|
||
(gimage->height *
|
||
gimp_unit_get_factor (gimage->unit) /
|
||
gimage->yresolution));
|
||
break;
|
||
|
||
case 'u': /* unit symbol */
|
||
i += print (title, title_len, i, "%s",
|
||
gimp_unit_get_symbol (gimage->unit));
|
||
break;
|
||
|
||
case 'U': /* unit abbreviation */
|
||
i += print (title, title_len, i, "%s",
|
||
gimp_unit_get_abbreviation (gimage->unit));
|
||
break;
|
||
|
||
/* Other cool things to be added:
|
||
* %r = xresolution
|
||
* %R = yresolution
|
||
* %<25> = image's fractal dimension
|
||
* %<25> = the answer to everything
|
||
*/
|
||
|
||
default:
|
||
g_warning ("image-title-format contains unknown "
|
||
"format sequence '%%%c'", *format);
|
||
break;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
title[i++] = *format;
|
||
break;
|
||
}
|
||
|
||
format++;
|
||
}
|
||
|
||
title[MIN (i, title_len - 1)] = '\0';
|
||
}
|
||
|
||
static void
|
||
gimp_display_shell_close_warning_dialog (GimpDisplayShell *shell,
|
||
const gchar *image_name)
|
||
{
|
||
GtkWidget *mbox;
|
||
gchar *title;
|
||
gchar *warning;
|
||
|
||
if (shell->warning_dialog)
|
||
{
|
||
gtk_window_present (GTK_WINDOW (shell->warning_dialog));
|
||
return;
|
||
}
|
||
|
||
title = g_strdup_printf (_("Close %s?"), image_name);
|
||
|
||
warning = g_strdup_printf (_("Changes were made to %s.\n"
|
||
"Close anyway?"), image_name);
|
||
|
||
shell->warning_dialog = mbox =
|
||
gimp_query_boolean_box (title,
|
||
gimp_standard_help_func,
|
||
"dialogs/really_close.html",
|
||
GTK_STOCK_DIALOG_QUESTION,
|
||
warning,
|
||
GTK_STOCK_CLOSE, GTK_STOCK_CANCEL,
|
||
NULL, NULL,
|
||
gimp_display_shell_close_warning_callback,
|
||
shell);
|
||
|
||
g_free (title);
|
||
g_free (warning);
|
||
|
||
gtk_widget_show (mbox);
|
||
}
|
||
|
||
static void
|
||
gimp_display_shell_close_warning_callback (GtkWidget *widget,
|
||
gboolean close,
|
||
gpointer data)
|
||
{
|
||
GimpDisplayShell *shell;
|
||
|
||
shell = GIMP_DISPLAY_SHELL (data);
|
||
|
||
shell->warning_dialog = NULL;
|
||
|
||
if (close)
|
||
gimp_display_delete (shell->gdisp);
|
||
}
|