1999-08-13 06:21:04 +08:00
|
|
|
/* 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.
|
|
|
|
*/
|
1999-09-06 08:07:03 +08:00
|
|
|
#include "config.h"
|
|
|
|
|
1999-08-24 06:47:36 +08:00
|
|
|
#include <stdlib.h>
|
1999-10-27 02:27:27 +08:00
|
|
|
|
1999-08-24 06:47:36 +08:00
|
|
|
#include "gdk/gdkkeysyms.h"
|
1999-08-13 06:21:04 +08:00
|
|
|
#include "appenv.h"
|
|
|
|
#include "colormaps.h"
|
1999-08-21 07:20:23 +08:00
|
|
|
#include "cursorutil.h"
|
1999-08-24 06:47:36 +08:00
|
|
|
#include "dialog_handler.h"
|
1999-08-13 06:21:04 +08:00
|
|
|
#include "info_dialog.h"
|
|
|
|
#include "info_window.h"
|
|
|
|
#include "gdisplay.h"
|
1999-09-05 06:27:20 +08:00
|
|
|
#include "gimprc.h"
|
1999-10-27 02:27:27 +08:00
|
|
|
#include "gimpui.h"
|
1999-08-13 06:21:04 +08:00
|
|
|
#include "gximage.h"
|
|
|
|
#include "interface.h"
|
1999-11-06 11:03:26 +08:00
|
|
|
#include "nav_window.h"
|
1999-08-13 06:21:04 +08:00
|
|
|
#include "scroll.h"
|
1999-08-24 06:47:36 +08:00
|
|
|
#include "scale.h"
|
1999-08-13 06:21:04 +08:00
|
|
|
|
|
|
|
#include "libgimp/gimpintl.h"
|
|
|
|
#include "libgimp/gimpunit.h"
|
|
|
|
|
1999-08-28 03:07:21 +08:00
|
|
|
#include "pixmaps/zoom_in.xpm"
|
|
|
|
#include "pixmaps/zoom_out.xpm"
|
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
|
|
|
|
#define MAX_BUF 256
|
|
|
|
|
1999-10-22 03:35:35 +08:00
|
|
|
#define PREVIEW_MASK GDK_EXPOSURE_MASK | \
|
|
|
|
GDK_BUTTON_PRESS_MASK | \
|
|
|
|
GDK_KEY_PRESS_MASK | \
|
|
|
|
GDK_KEY_RELEASE_MASK | \
|
|
|
|
GDK_POINTER_MOTION_MASK
|
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
|
|
|
|
/* Navigation preview sizes */
|
|
|
|
#define NAV_PREVIEW_WIDTH 112
|
|
|
|
#define NAV_PREVIEW_HEIGHT 112
|
|
|
|
#define BORDER_PEN_WIDTH 3
|
|
|
|
|
1999-08-28 03:07:21 +08:00
|
|
|
#define MAX_SCALE_BUF 20
|
|
|
|
|
1999-09-02 06:39:44 +08:00
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
NAV_WINDOW,
|
|
|
|
NAV_POPUP
|
|
|
|
} NavWinType;
|
1999-08-28 03:07:21 +08:00
|
|
|
|
|
|
|
/* Timeout before preview is updated */
|
|
|
|
#define PREVIEW_UPDATE_TIMEOUT 1100
|
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
typedef struct _NavWinData NavWinData;
|
|
|
|
struct _NavWinData
|
|
|
|
{
|
1999-09-02 06:39:44 +08:00
|
|
|
NavWinType ptype;
|
1999-08-13 06:21:04 +08:00
|
|
|
gboolean showingPreview;
|
1999-08-25 05:59:32 +08:00
|
|
|
gboolean installedDirtyTimer;
|
1999-08-24 06:47:36 +08:00
|
|
|
InfoDialog *info_win;
|
1999-08-13 06:21:04 +08:00
|
|
|
GtkWidget *previewBox;
|
|
|
|
GtkWidget *previewAlign;
|
1999-08-28 03:07:21 +08:00
|
|
|
GtkWidget *zoom_label;
|
|
|
|
GtkObject *zoom_adjustment;
|
1999-09-02 06:39:44 +08:00
|
|
|
GtkWidget *preview;
|
|
|
|
void *gdisp_ptr; /* I'm not happy 'bout this one */
|
1999-08-13 06:21:04 +08:00
|
|
|
GdkGC *gc;
|
|
|
|
gint dispx; /* x pos of top left corner of display area */
|
|
|
|
gint dispy; /* y pos of top left corner of display area */
|
|
|
|
gint dispwidth; /* width of display area */
|
1999-08-21 07:20:23 +08:00
|
|
|
gint dispheight; /* height of display area */
|
1999-08-13 06:21:04 +08:00
|
|
|
gint sig_hand_id;
|
|
|
|
gboolean sq_grabbed; /* In the process of moving the preview square */
|
|
|
|
gint motion_offsetx;
|
|
|
|
gint motion_offsety;
|
|
|
|
gint pwidth; /* real preview width */
|
|
|
|
gint pheight; /* real preview height */
|
|
|
|
gint imagewidth; /* width of the real image */
|
|
|
|
gint imageheight; /* height of real image */
|
1999-09-02 06:39:44 +08:00
|
|
|
gdouble ratio;
|
1999-08-13 06:21:04 +08:00
|
|
|
gboolean block_window_marker; /* Block redraws of window marker */
|
|
|
|
gint nav_preview_width;
|
|
|
|
gint nav_preview_height;
|
1999-08-28 03:07:21 +08:00
|
|
|
gboolean block_adj_sig;
|
1999-08-13 06:21:04 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
1999-11-06 11:03:26 +08:00
|
|
|
static gint nav_window_preview_events (GtkWidget *, GdkEvent *, gpointer *);
|
|
|
|
static gint nav_window_expose_events (GtkWidget *, GdkEvent *, gpointer *);
|
|
|
|
static void nav_window_update_preview (NavWinData *);
|
|
|
|
static void nav_window_update_preview_blank (NavWinData *iwd);
|
|
|
|
static void destroy_preview_widget (NavWinData *);
|
|
|
|
static void create_preview_widget (NavWinData *);
|
|
|
|
static void nav_window_draw_sqr (NavWinData *, gboolean,
|
|
|
|
gint, gint, gint, gint );
|
|
|
|
static void set_size_data (NavWinData *);
|
|
|
|
static gint nav_preview_update_do_timer (NavWinData *);
|
1999-08-13 06:21:04 +08:00
|
|
|
|
1999-08-28 03:07:21 +08:00
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
|
|
|
|
static void
|
1999-08-24 06:47:36 +08:00
|
|
|
nav_window_destroy_callback (GtkWidget *widget,
|
|
|
|
gpointer client_data)
|
|
|
|
{
|
|
|
|
InfoDialog *info_win;
|
|
|
|
|
|
|
|
info_win = (InfoDialog *)client_data;
|
|
|
|
dialog_unregister(info_win->shell);
|
|
|
|
}
|
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
static void
|
|
|
|
nav_window_close_callback (GtkWidget *widget,
|
|
|
|
gpointer client_data)
|
|
|
|
{
|
|
|
|
InfoDialog *info_win;
|
|
|
|
NavWinData *iwd;
|
|
|
|
|
|
|
|
info_win = (InfoDialog *)client_data;
|
|
|
|
iwd = (NavWinData *)info_win->user_data;
|
|
|
|
|
1999-08-28 03:07:21 +08:00
|
|
|
iwd->showingPreview = FALSE;
|
1999-08-13 06:21:04 +08:00
|
|
|
info_dialog_popdown ((InfoDialog *) client_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1999-10-16 21:07:15 +08:00
|
|
|
nav_window_disp_area (NavWinData *iwd,
|
|
|
|
GDisplay *gdisp)
|
1999-08-13 06:21:04 +08:00
|
|
|
{
|
|
|
|
GimpImage *gimage;
|
|
|
|
gint newwidth;
|
|
|
|
gint newheight;
|
Honest, guv, it's not a feature - it's a tightly integrated package of
Mon Sep 20 12:51:30 EDT 1999 Austin Donnelly <austin@gimp.org>
Honest, guv, it's not a feature - it's a tightly integrated
package of undo system cleanups and fixes.
NEW FILES:
* app/undo_history.c: window showing recent undo (and redo) steps
available.
* app/undo_types.h: broken out of undo.h to fix circular includes.
MODIFIED FILES:
* app/Makefile.am: compile undo_history.c
* app/channel.h: use enum for channel undo type, not just magic
numbers.
* app/layer.h: same for layer undos.
* app/commands.c: edit_show_undo_history_cmd_callback() function to
pull up undo history window.
* app/commands.h: prototype for above.
* app/gdisplay.c: make undo / redo menu items sensitive according
to whether they would do anything. Would be easy to change
the text to say what would be undone/redone, but I don't know
the GTK.
* app/gimpimage.c: new signal emitted by gimage:
UNDO_EVENT. gimp_image_undo_event() function to emit it.
* app/gimpimage.h: prototype for above.
* app/gimpimageP.h: pushing_undo_group member is now an undo_type,
not an int. Keep undo history widget here too (if created).
* app/menus.c: add "Edit/Undo history..." to image menu.
* app/undo.c: new types: enums undo_type and undo_state rather than
ints and magic numbers. All undo_pop_* and undo_free_*
functions made static. New static function
undo_type_to_name(). Issue undo event signals on various
important events (eg undo pushed, undo popped etc).
undo_push() now takes a "dirties_image" arg to say whether
image should be dirtied. Layer moves now dirty the image. A
couple of g_return_if_fails () on undo_pop and undo_redo to
assert we're not in the middle of an undo group.
undo_get_{undo,redo}_name() to peek at names of top items on
undo and redo stacks resp. undo_map_over_{undo,redo}_stack()
to run a function for each item or group on stack. Layer and
channel undos use symbolic names rather than 0 or 1. Array
mapping undo types to names.
* app/undo.h: split out undo types to undo_types.h. Prototypes
for functions described above. undo_event_t enum.
undo_history_new() prototype lives here too.
Random other fixes:
* app/gimpdrawable.c
* app/image_render.c: default labels in switches to keep egcs happy.
* app/nav_window.c: some fixes to (sort of) cope with image res !=
screen res. Still needs work to handle non-square pixels
properly.
* app/paths_dialog.c: bad idea to call gimp_image_dirty()
directly. Even though it's currently commented out.
1999-09-21 01:15:20 +08:00
|
|
|
gdouble xratio;
|
|
|
|
gdouble yratio; /* Screen res ratio */
|
1999-08-13 06:21:04 +08:00
|
|
|
gboolean need_update = FALSE;
|
|
|
|
|
|
|
|
/* Calculate preview size */
|
|
|
|
gimage = gdisp->gimage;
|
|
|
|
|
Honest, guv, it's not a feature - it's a tightly integrated package of
Mon Sep 20 12:51:30 EDT 1999 Austin Donnelly <austin@gimp.org>
Honest, guv, it's not a feature - it's a tightly integrated
package of undo system cleanups and fixes.
NEW FILES:
* app/undo_history.c: window showing recent undo (and redo) steps
available.
* app/undo_types.h: broken out of undo.h to fix circular includes.
MODIFIED FILES:
* app/Makefile.am: compile undo_history.c
* app/channel.h: use enum for channel undo type, not just magic
numbers.
* app/layer.h: same for layer undos.
* app/commands.c: edit_show_undo_history_cmd_callback() function to
pull up undo history window.
* app/commands.h: prototype for above.
* app/gdisplay.c: make undo / redo menu items sensitive according
to whether they would do anything. Would be easy to change
the text to say what would be undone/redone, but I don't know
the GTK.
* app/gimpimage.c: new signal emitted by gimage:
UNDO_EVENT. gimp_image_undo_event() function to emit it.
* app/gimpimage.h: prototype for above.
* app/gimpimageP.h: pushing_undo_group member is now an undo_type,
not an int. Keep undo history widget here too (if created).
* app/menus.c: add "Edit/Undo history..." to image menu.
* app/undo.c: new types: enums undo_type and undo_state rather than
ints and magic numbers. All undo_pop_* and undo_free_*
functions made static. New static function
undo_type_to_name(). Issue undo event signals on various
important events (eg undo pushed, undo popped etc).
undo_push() now takes a "dirties_image" arg to say whether
image should be dirtied. Layer moves now dirty the image. A
couple of g_return_if_fails () on undo_pop and undo_redo to
assert we're not in the middle of an undo group.
undo_get_{undo,redo}_name() to peek at names of top items on
undo and redo stacks resp. undo_map_over_{undo,redo}_stack()
to run a function for each item or group on stack. Layer and
channel undos use symbolic names rather than 0 or 1. Array
mapping undo types to names.
* app/undo.h: split out undo types to undo_types.h. Prototypes
for functions described above. undo_event_t enum.
undo_history_new() prototype lives here too.
Random other fixes:
* app/gimpdrawable.c
* app/image_render.c: default labels in switches to keep egcs happy.
* app/nav_window.c: some fixes to (sort of) cope with image res !=
screen res. Still needs work to handle non-square pixels
properly.
* app/paths_dialog.c: bad idea to call gimp_image_dirty()
directly. Even though it's currently commented out.
1999-09-21 01:15:20 +08:00
|
|
|
xratio = SCALEFACTOR_X(gdisp);
|
|
|
|
yratio = SCALEFACTOR_Y(gdisp);
|
1999-08-13 06:21:04 +08:00
|
|
|
|
1999-10-22 03:35:35 +08:00
|
|
|
iwd->dispx = gdisp->offset_x * iwd->ratio / xratio + 0.5;
|
|
|
|
iwd->dispy = gdisp->offset_y * iwd->ratio/yratio + 0.5;
|
|
|
|
iwd->dispwidth = (gdisp->disp_width * iwd->ratio) / xratio + 0.5;
|
|
|
|
iwd->dispheight = (gdisp->disp_height * iwd->ratio) / yratio + 0.5;
|
1999-08-13 06:21:04 +08:00
|
|
|
|
|
|
|
newwidth = gimage->width;
|
|
|
|
newheight = gimage->height;
|
|
|
|
|
1999-11-11 07:22:23 +08:00
|
|
|
if(!gdisp->dot_for_dot)
|
1999-10-21 06:15:13 +08:00
|
|
|
{
|
1999-11-11 07:22:23 +08:00
|
|
|
newwidth = (newwidth * gdisp->gimage->yresolution)/ gdisp->gimage->xresolution;
|
|
|
|
iwd->dispx = ((gdisp->offset_x * gdisp->gimage->yresolution * iwd->ratio)/ (gdisp->gimage->xresolution * xratio)) + 0.5; /* here */
|
|
|
|
iwd->dispwidth = ((gdisp->disp_width * gdisp->gimage->yresolution * iwd->ratio)/ (gdisp->gimage->xresolution * xratio)) + 0.5; /* here */
|
1999-10-21 06:15:13 +08:00
|
|
|
}
|
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
if((iwd->imagewidth > 0 && newwidth != iwd->imagewidth) ||
|
|
|
|
(iwd->imageheight > 0 && newheight != iwd->imageheight))
|
|
|
|
{
|
|
|
|
/* Must change the preview size */
|
1999-09-02 06:39:44 +08:00
|
|
|
if(iwd->ptype != NAV_POPUP)
|
|
|
|
{
|
|
|
|
gtk_window_set_focus(GTK_WINDOW (iwd->info_win->shell),NULL);
|
|
|
|
}
|
1999-08-13 06:21:04 +08:00
|
|
|
destroy_preview_widget(iwd);
|
|
|
|
create_preview_widget(iwd);
|
|
|
|
need_update = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
iwd->imagewidth = newwidth;
|
|
|
|
iwd->imageheight = newheight;
|
|
|
|
|
|
|
|
/* Normalise */
|
1999-08-28 03:07:21 +08:00
|
|
|
iwd->dispwidth = MAX(iwd->dispwidth, 2);
|
|
|
|
iwd->dispheight = MAX(iwd->dispheight, 2);
|
|
|
|
|
1999-08-24 06:47:36 +08:00
|
|
|
iwd->dispwidth = MIN(iwd->dispwidth, iwd->pwidth/*-BORDER_PEN_WIDTH*/);
|
|
|
|
iwd->dispheight = MIN(iwd->dispheight, iwd->pheight/*-BORDER_PEN_WIDTH*/);
|
1999-08-13 06:21:04 +08:00
|
|
|
|
|
|
|
if(need_update == TRUE)
|
|
|
|
{
|
|
|
|
gtk_widget_hide(iwd->previewAlign);
|
1999-08-28 03:07:21 +08:00
|
|
|
nav_window_update_preview_blank(iwd);
|
1999-08-13 06:21:04 +08:00
|
|
|
gtk_widget_show(iwd->preview);
|
|
|
|
gtk_widget_draw(iwd->preview, NULL);
|
|
|
|
gtk_widget_show(iwd->previewAlign);
|
|
|
|
nav_window_draw_sqr(iwd,FALSE,
|
|
|
|
iwd->dispx,iwd->dispy,
|
|
|
|
iwd->dispwidth,iwd->dispheight);
|
1999-09-02 06:39:44 +08:00
|
|
|
if(iwd->ptype != NAV_POPUP)
|
|
|
|
{
|
|
|
|
gtk_window_set_focus(GTK_WINDOW (iwd->info_win->shell),iwd->preview);
|
|
|
|
gtk_timeout_add(PREVIEW_UPDATE_TIMEOUT,(GtkFunction)nav_preview_update_do_timer,(gpointer)iwd);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nav_window_update_preview(iwd);
|
|
|
|
gtk_widget_draw(iwd->preview, NULL);
|
|
|
|
}
|
1999-08-13 06:21:04 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1999-10-16 21:07:15 +08:00
|
|
|
nav_window_draw_sqr (NavWinData *iwd,
|
|
|
|
gboolean undraw,
|
|
|
|
gint x,
|
|
|
|
gint y,
|
|
|
|
gint w,
|
|
|
|
gint h)
|
1999-08-13 06:21:04 +08:00
|
|
|
{
|
|
|
|
GDisplay *gdisp;
|
|
|
|
|
|
|
|
gdisp = (GDisplay *) iwd->gdisp_ptr;
|
|
|
|
|
|
|
|
gdk_gc_set_function (iwd->gc, GDK_INVERT);
|
1999-10-22 03:35:35 +08:00
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
if(undraw)
|
|
|
|
{
|
|
|
|
/* first undraw from last co-ords */
|
|
|
|
gdk_draw_rectangle (iwd->preview->window, iwd->gc, FALSE,
|
1999-10-22 03:35:35 +08:00
|
|
|
iwd->dispx, iwd->dispy,
|
1999-08-24 06:47:36 +08:00
|
|
|
iwd->dispwidth-BORDER_PEN_WIDTH+1,
|
|
|
|
iwd->dispheight-BORDER_PEN_WIDTH+1);
|
1999-08-13 06:21:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
gdk_draw_rectangle (iwd->preview->window, iwd->gc, FALSE,
|
|
|
|
x,y,
|
1999-08-24 06:47:36 +08:00
|
|
|
w-BORDER_PEN_WIDTH+1,
|
|
|
|
h-BORDER_PEN_WIDTH+1);
|
1999-08-13 06:21:04 +08:00
|
|
|
|
|
|
|
iwd->dispx = x;
|
|
|
|
iwd->dispy = y;
|
|
|
|
iwd->dispwidth = w;
|
|
|
|
iwd->dispheight = h;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1999-10-16 21:07:15 +08:00
|
|
|
destroy_preview_widget (NavWinData *iwd)
|
1999-08-13 06:21:04 +08:00
|
|
|
{
|
|
|
|
if(!iwd->preview)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gtk_widget_hide(iwd->previewBox);
|
|
|
|
gtk_widget_destroy(iwd->previewBox);
|
|
|
|
iwd->previewBox = NULL;
|
|
|
|
iwd->preview = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1999-10-16 21:07:15 +08:00
|
|
|
set_size_data (NavWinData *iwd)
|
1999-08-13 06:21:04 +08:00
|
|
|
{
|
|
|
|
gint sel_width, sel_height;
|
|
|
|
gint pwidth, pheight;
|
|
|
|
GDisplay *gdisp;
|
|
|
|
GimpImage *gimage;
|
|
|
|
|
|
|
|
gdisp = (GDisplay *)(iwd->gdisp_ptr);
|
|
|
|
gimage = gdisp->gimage;
|
|
|
|
|
|
|
|
sel_width = gimage->width;
|
|
|
|
sel_height = gimage->height;
|
|
|
|
|
1999-11-11 07:22:23 +08:00
|
|
|
if(!gdisp->dot_for_dot)
|
|
|
|
sel_width = (sel_width * gdisp->gimage->yresolution)/ gdisp->gimage->xresolution;
|
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
if (sel_width > sel_height) {
|
1999-11-11 07:22:23 +08:00
|
|
|
pwidth = iwd->nav_preview_width;
|
1999-09-02 06:39:44 +08:00
|
|
|
/* pheight = sel_height * pwidth / sel_width; */
|
1999-08-13 06:21:04 +08:00
|
|
|
iwd->ratio = (gdouble)pwidth / ((gdouble)sel_width);
|
1999-11-10 05:25:03 +08:00
|
|
|
pheight = sel_height * iwd->ratio + 0.5;
|
1999-09-02 06:39:44 +08:00
|
|
|
iwd->ratio = (gdouble)pheight/(gdouble)sel_height;
|
1999-11-10 05:25:03 +08:00
|
|
|
pwidth = sel_width * iwd->ratio + 0.5;
|
1999-08-13 06:21:04 +08:00
|
|
|
} else {
|
1999-11-11 07:22:23 +08:00
|
|
|
pheight = iwd->nav_preview_height;
|
1999-09-02 06:39:44 +08:00
|
|
|
/* pwidth = sel_width * pheight / sel_height; */
|
1999-08-13 06:21:04 +08:00
|
|
|
iwd->ratio = (gdouble)pheight / ((gdouble)sel_height);
|
1999-11-10 05:25:03 +08:00
|
|
|
pwidth = sel_width * iwd->ratio + 0.5;
|
1999-09-02 06:39:44 +08:00
|
|
|
iwd->ratio = (gdouble)pwidth/(gdouble)sel_width;
|
1999-11-10 05:25:03 +08:00
|
|
|
pheight = sel_height * iwd->ratio + 0.5;
|
1999-08-13 06:21:04 +08:00
|
|
|
}
|
|
|
|
|
1999-11-11 07:22:23 +08:00
|
|
|
iwd->pwidth = pwidth;
|
|
|
|
iwd->pheight = pheight;
|
1999-08-13 06:21:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1999-10-16 21:07:15 +08:00
|
|
|
create_preview_widget (NavWinData *iwd)
|
1999-08-13 06:21:04 +08:00
|
|
|
{
|
|
|
|
GtkWidget *hbox;
|
|
|
|
GtkWidget *image;
|
|
|
|
GtkWidget *frame;
|
|
|
|
GDisplay *gdisp;
|
|
|
|
|
|
|
|
gdisp = (GDisplay *)(iwd->gdisp_ptr);
|
|
|
|
|
|
|
|
hbox = gtk_hbox_new(FALSE,0);
|
|
|
|
iwd->previewBox = hbox;
|
|
|
|
gtk_widget_show(hbox);
|
|
|
|
gtk_container_add(GTK_CONTAINER (iwd->previewAlign),hbox);
|
|
|
|
|
|
|
|
image = gtk_preview_new (GTK_PREVIEW_COLOR);
|
1999-08-24 06:47:36 +08:00
|
|
|
gtk_widget_set_events( GTK_WIDGET(image), PREVIEW_MASK );
|
1999-08-13 06:21:04 +08:00
|
|
|
iwd->preview = image;
|
|
|
|
gtk_widget_show (image);
|
|
|
|
|
|
|
|
gtk_preview_set_dither (GTK_PREVIEW (image), GDK_RGB_DITHER_MAX);
|
|
|
|
|
|
|
|
set_size_data(iwd);
|
|
|
|
|
|
|
|
gtk_preview_size (GTK_PREVIEW (iwd->preview),
|
|
|
|
iwd->pwidth,
|
|
|
|
iwd->pheight);
|
|
|
|
|
|
|
|
gtk_widget_set_usize (iwd->preview,
|
|
|
|
iwd->pwidth,
|
|
|
|
iwd->pheight);
|
|
|
|
|
|
|
|
frame = gtk_frame_new(NULL);
|
|
|
|
gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_IN);
|
|
|
|
gtk_container_add(GTK_CONTAINER (iwd->previewBox),frame);
|
|
|
|
gtk_container_add (GTK_CONTAINER (frame), iwd->preview);
|
|
|
|
gtk_widget_show(frame);
|
|
|
|
|
|
|
|
iwd->sig_hand_id = gtk_signal_connect_after (GTK_OBJECT (image), "expose_event",
|
|
|
|
(GtkSignalFunc) nav_window_expose_events,
|
|
|
|
iwd);
|
|
|
|
|
|
|
|
gtk_signal_connect (GTK_OBJECT (image), "event",
|
|
|
|
(GtkSignalFunc) nav_window_preview_events,
|
|
|
|
iwd);
|
|
|
|
|
|
|
|
/* gtk_signal_connect (GTK_OBJECT (image), "size_allocate", */
|
|
|
|
/* (GtkSignalFunc) nav_window_preview_resized, */
|
|
|
|
/* iwd); */
|
|
|
|
|
1999-08-24 06:47:36 +08:00
|
|
|
GTK_WIDGET_SET_FLAGS (image, GTK_CAN_FOCUS);
|
1999-08-13 06:21:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
1999-10-16 21:07:15 +08:00
|
|
|
update_real_view (NavWinData *iwd,
|
|
|
|
gint tx,
|
|
|
|
gint ty)
|
1999-08-13 06:21:04 +08:00
|
|
|
{
|
|
|
|
GDisplay *gdisp;
|
Honest, guv, it's not a feature - it's a tightly integrated package of
Mon Sep 20 12:51:30 EDT 1999 Austin Donnelly <austin@gimp.org>
Honest, guv, it's not a feature - it's a tightly integrated
package of undo system cleanups and fixes.
NEW FILES:
* app/undo_history.c: window showing recent undo (and redo) steps
available.
* app/undo_types.h: broken out of undo.h to fix circular includes.
MODIFIED FILES:
* app/Makefile.am: compile undo_history.c
* app/channel.h: use enum for channel undo type, not just magic
numbers.
* app/layer.h: same for layer undos.
* app/commands.c: edit_show_undo_history_cmd_callback() function to
pull up undo history window.
* app/commands.h: prototype for above.
* app/gdisplay.c: make undo / redo menu items sensitive according
to whether they would do anything. Would be easy to change
the text to say what would be undone/redone, but I don't know
the GTK.
* app/gimpimage.c: new signal emitted by gimage:
UNDO_EVENT. gimp_image_undo_event() function to emit it.
* app/gimpimage.h: prototype for above.
* app/gimpimageP.h: pushing_undo_group member is now an undo_type,
not an int. Keep undo history widget here too (if created).
* app/menus.c: add "Edit/Undo history..." to image menu.
* app/undo.c: new types: enums undo_type and undo_state rather than
ints and magic numbers. All undo_pop_* and undo_free_*
functions made static. New static function
undo_type_to_name(). Issue undo event signals on various
important events (eg undo pushed, undo popped etc).
undo_push() now takes a "dirties_image" arg to say whether
image should be dirtied. Layer moves now dirty the image. A
couple of g_return_if_fails () on undo_pop and undo_redo to
assert we're not in the middle of an undo group.
undo_get_{undo,redo}_name() to peek at names of top items on
undo and redo stacks resp. undo_map_over_{undo,redo}_stack()
to run a function for each item or group on stack. Layer and
channel undos use symbolic names rather than 0 or 1. Array
mapping undo types to names.
* app/undo.h: split out undo types to undo_types.h. Prototypes
for functions described above. undo_event_t enum.
undo_history_new() prototype lives here too.
Random other fixes:
* app/gimpdrawable.c
* app/image_render.c: default labels in switches to keep egcs happy.
* app/nav_window.c: some fixes to (sort of) cope with image res !=
screen res. Still needs work to handle non-square pixels
properly.
* app/paths_dialog.c: bad idea to call gimp_image_dirty()
directly. Even though it's currently commented out.
1999-09-21 01:15:20 +08:00
|
|
|
gdouble xratio;
|
|
|
|
gdouble yratio;
|
1999-08-13 06:21:04 +08:00
|
|
|
gint xoffset;
|
|
|
|
gint yoffset;
|
1999-08-24 06:47:36 +08:00
|
|
|
gint xpnt;
|
|
|
|
gint ypnt;
|
1999-08-13 06:21:04 +08:00
|
|
|
|
|
|
|
gdisp = (GDisplay *) iwd->gdisp_ptr;
|
Honest, guv, it's not a feature - it's a tightly integrated package of
Mon Sep 20 12:51:30 EDT 1999 Austin Donnelly <austin@gimp.org>
Honest, guv, it's not a feature - it's a tightly integrated
package of undo system cleanups and fixes.
NEW FILES:
* app/undo_history.c: window showing recent undo (and redo) steps
available.
* app/undo_types.h: broken out of undo.h to fix circular includes.
MODIFIED FILES:
* app/Makefile.am: compile undo_history.c
* app/channel.h: use enum for channel undo type, not just magic
numbers.
* app/layer.h: same for layer undos.
* app/commands.c: edit_show_undo_history_cmd_callback() function to
pull up undo history window.
* app/commands.h: prototype for above.
* app/gdisplay.c: make undo / redo menu items sensitive according
to whether they would do anything. Would be easy to change
the text to say what would be undone/redone, but I don't know
the GTK.
* app/gimpimage.c: new signal emitted by gimage:
UNDO_EVENT. gimp_image_undo_event() function to emit it.
* app/gimpimage.h: prototype for above.
* app/gimpimageP.h: pushing_undo_group member is now an undo_type,
not an int. Keep undo history widget here too (if created).
* app/menus.c: add "Edit/Undo history..." to image menu.
* app/undo.c: new types: enums undo_type and undo_state rather than
ints and magic numbers. All undo_pop_* and undo_free_*
functions made static. New static function
undo_type_to_name(). Issue undo event signals on various
important events (eg undo pushed, undo popped etc).
undo_push() now takes a "dirties_image" arg to say whether
image should be dirtied. Layer moves now dirty the image. A
couple of g_return_if_fails () on undo_pop and undo_redo to
assert we're not in the middle of an undo group.
undo_get_{undo,redo}_name() to peek at names of top items on
undo and redo stacks resp. undo_map_over_{undo,redo}_stack()
to run a function for each item or group on stack. Layer and
channel undos use symbolic names rather than 0 or 1. Array
mapping undo types to names.
* app/undo.h: split out undo types to undo_types.h. Prototypes
for functions described above. undo_event_t enum.
undo_history_new() prototype lives here too.
Random other fixes:
* app/gimpdrawable.c
* app/image_render.c: default labels in switches to keep egcs happy.
* app/nav_window.c: some fixes to (sort of) cope with image res !=
screen res. Still needs work to handle non-square pixels
properly.
* app/paths_dialog.c: bad idea to call gimp_image_dirty()
directly. Even though it's currently commented out.
1999-09-21 01:15:20 +08:00
|
|
|
|
|
|
|
xratio = SCALEFACTOR_X(gdisp);
|
|
|
|
yratio = SCALEFACTOR_Y(gdisp);
|
1999-08-13 06:21:04 +08:00
|
|
|
|
1999-08-24 06:47:36 +08:00
|
|
|
if((tx + iwd->dispwidth) >= iwd->pwidth)
|
|
|
|
{
|
|
|
|
tx = iwd->pwidth; /* Actually should be less...
|
|
|
|
* but bound check will save us.
|
|
|
|
*/
|
|
|
|
}
|
1999-08-13 06:21:04 +08:00
|
|
|
|
1999-11-11 07:22:23 +08:00
|
|
|
xpnt = (gint)(((gdouble)(tx)*xratio)/iwd->ratio+0.5);
|
1999-08-24 06:47:36 +08:00
|
|
|
|
|
|
|
if((ty + iwd->dispheight) >= iwd->pheight)
|
|
|
|
ty = iwd->pheight; /* Same comment as for xpnt above. */
|
|
|
|
|
1999-11-11 07:22:23 +08:00
|
|
|
ypnt = (gint)(((gdouble)(ty)*yratio)/iwd->ratio+0.5);
|
1999-08-24 06:47:36 +08:00
|
|
|
|
1999-11-11 07:22:23 +08:00
|
|
|
if (!gdisp->dot_for_dot) /* here */
|
1999-10-21 06:15:13 +08:00
|
|
|
{
|
|
|
|
gdouble unit_factor = gimp_unit_get_factor (gdisp->gimage->unit);
|
1999-11-11 07:22:23 +08:00
|
|
|
xpnt = ((gdouble)xpnt * gdisp->gimage->xresolution) / gdisp->gimage->yresolution + 0.5;
|
1999-10-21 06:15:13 +08:00
|
|
|
}
|
|
|
|
|
1999-08-24 06:47:36 +08:00
|
|
|
xoffset = xpnt - gdisp->offset_x;
|
|
|
|
yoffset = ypnt - gdisp->offset_y;
|
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
iwd->block_window_marker = TRUE;
|
|
|
|
scroll_display(iwd->gdisp_ptr,xoffset,yoffset);
|
|
|
|
iwd->block_window_marker = FALSE;
|
|
|
|
}
|
|
|
|
|
1999-09-02 06:39:44 +08:00
|
|
|
static void
|
1999-10-16 21:07:15 +08:00
|
|
|
nav_window_update_preview (NavWinData *iwd)
|
1999-08-13 06:21:04 +08:00
|
|
|
{
|
|
|
|
GDisplay *gdisp;
|
|
|
|
TempBuf * preview_buf;
|
1999-10-21 06:15:13 +08:00
|
|
|
TempBuf * preview_buf_ptr;
|
|
|
|
TempBuf * preview_buf_notdot = NULL;
|
1999-08-25 05:59:32 +08:00
|
|
|
guchar *src, *buf, *dest;
|
1999-08-13 06:21:04 +08:00
|
|
|
gint x,y,has_alpha;
|
|
|
|
gint pwidth, pheight;
|
|
|
|
GimpImage *gimage;
|
1999-08-25 05:59:32 +08:00
|
|
|
gdouble r,g,b,a,chk;
|
1999-08-28 03:07:21 +08:00
|
|
|
gint xoff = 0;
|
|
|
|
gint yoff = 0;
|
1999-08-21 07:20:23 +08:00
|
|
|
|
1999-09-05 06:27:20 +08:00
|
|
|
gimp_add_busy_cursors();
|
1999-08-21 07:20:23 +08:00
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
gdisp = (GDisplay *) iwd->gdisp_ptr;
|
|
|
|
|
|
|
|
/* Calculate preview size */
|
|
|
|
gimage = ((GDisplay *)(iwd->gdisp_ptr))->gimage;
|
1999-08-28 03:07:21 +08:00
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
/* Min size is 2 */
|
|
|
|
pwidth = iwd->pwidth;
|
|
|
|
pheight = iwd->pheight;
|
|
|
|
|
1999-10-21 06:15:13 +08:00
|
|
|
/* we need a large normal preview which we will cut down later.
|
|
|
|
* gimp_image_construct_composite_preview() can't cope with
|
|
|
|
* dot_for_dot not been set.
|
|
|
|
*/
|
1999-11-11 07:22:23 +08:00
|
|
|
if (!gdisp->dot_for_dot) /* ALT */
|
1999-10-21 06:15:13 +08:00
|
|
|
{
|
1999-11-11 07:22:23 +08:00
|
|
|
gint sel_width = gimage->width;
|
|
|
|
gint sel_height = gimage->height;
|
|
|
|
gdouble tratio;
|
|
|
|
|
|
|
|
if (sel_width > sel_height) {
|
|
|
|
pwidth = iwd->nav_preview_width;
|
|
|
|
tratio = (gdouble)pwidth / ((gdouble)sel_width);
|
|
|
|
pheight = sel_height * tratio + 0.5;
|
|
|
|
tratio = (gdouble)pheight/(gdouble)sel_height;
|
|
|
|
pwidth = sel_width * tratio + 0.5;
|
|
|
|
} else {
|
|
|
|
pheight = iwd->nav_preview_height;
|
|
|
|
tratio = (gdouble)pheight / ((gdouble)sel_height);
|
|
|
|
pwidth = sel_width * tratio + 0.5;
|
|
|
|
tratio = (gdouble)pwidth/(gdouble)sel_width;
|
|
|
|
pheight = sel_height * tratio + 0.5;
|
|
|
|
}
|
1999-10-21 06:15:13 +08:00
|
|
|
}
|
1999-08-28 03:07:21 +08:00
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
preview_buf = gimp_image_construct_composite_preview (gimage,
|
|
|
|
MAX (pwidth, 2),
|
|
|
|
MAX (pheight, 2));
|
1999-10-21 06:15:13 +08:00
|
|
|
/* reset & get new preview */
|
|
|
|
if (!gdisp->dot_for_dot)
|
|
|
|
{
|
|
|
|
int loop1,loop2;
|
|
|
|
gdouble x_ratio,y_ratio;
|
|
|
|
guchar *src_data;
|
|
|
|
guchar *dest_data;
|
|
|
|
|
|
|
|
preview_buf_notdot = temp_buf_new(iwd->pwidth,
|
|
|
|
iwd->pheight,
|
|
|
|
preview_buf->bytes,0,0,NULL);
|
|
|
|
|
|
|
|
x_ratio = (gdouble)pwidth/(gdouble)iwd->pwidth;
|
|
|
|
y_ratio = (gdouble)pheight/(gdouble)iwd->pheight;
|
|
|
|
src_data = temp_buf_data(preview_buf);
|
|
|
|
dest_data = temp_buf_data(preview_buf_notdot);
|
|
|
|
|
|
|
|
for(loop1 = 0 ; loop1 < iwd->pheight ; loop1++)
|
|
|
|
for(loop2 = 0 ; loop2 < iwd->pwidth ; loop2++)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
guchar *src_pixel = src_data +
|
|
|
|
((gint)(loop2*x_ratio))*preview_buf->bytes +
|
|
|
|
((gint)(loop1*y_ratio))*pwidth*preview_buf->bytes;
|
|
|
|
guchar *dest_pixel = dest_data +
|
|
|
|
(loop2+loop1*iwd->pwidth)*preview_buf->bytes;
|
|
|
|
|
|
|
|
for(i = 0 ; i < preview_buf->bytes; i++)
|
|
|
|
*dest_pixel++ = *src_pixel++;
|
|
|
|
}
|
|
|
|
|
|
|
|
pwidth = iwd->pwidth;
|
|
|
|
pheight = iwd->pheight;
|
|
|
|
src = (gchar *) temp_buf_data (preview_buf_notdot);
|
|
|
|
preview_buf_ptr = preview_buf_notdot;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
src = (gchar *) temp_buf_data (preview_buf);
|
|
|
|
preview_buf_ptr = preview_buf;
|
|
|
|
}
|
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
buf = g_new (gchar, iwd->nav_preview_width * 3);
|
1999-10-21 06:15:13 +08:00
|
|
|
has_alpha = (preview_buf_ptr->bytes == 2 || preview_buf_ptr->bytes == 4);
|
1999-08-21 08:18:58 +08:00
|
|
|
|
1999-08-28 03:07:21 +08:00
|
|
|
for (y = 0; y <pheight ; y++)
|
1999-08-13 06:21:04 +08:00
|
|
|
{
|
1999-08-21 08:18:58 +08:00
|
|
|
dest = buf;
|
1999-10-21 06:15:13 +08:00
|
|
|
switch (preview_buf_ptr->bytes)
|
1999-08-21 08:18:58 +08:00
|
|
|
{
|
|
|
|
case 4:
|
1999-09-02 06:39:44 +08:00
|
|
|
for (x = 0; x < pwidth; x++)
|
|
|
|
{
|
|
|
|
r = ((gdouble)(*(src++)))/255.0;
|
|
|
|
g = ((gdouble)(*(src++)))/255.0;
|
|
|
|
b = ((gdouble)(*(src++)))/255.0;
|
|
|
|
a = ((gdouble)(*(src++)))/255.0;
|
|
|
|
chk = ((gdouble)((( (x^y) & 4 ) << 4) | 128))/255.0;
|
|
|
|
*(dest++) = (guchar)((chk + (r - chk)*a)*255.0);
|
|
|
|
*(dest++) = (guchar)((chk + (g - chk)*a)*255.0);
|
|
|
|
*(dest++) = (guchar)((chk + (b - chk)*a)*255.0);
|
|
|
|
}
|
|
|
|
break;
|
1999-08-21 08:18:58 +08:00
|
|
|
case 2:
|
1999-08-28 03:07:21 +08:00
|
|
|
for (x = 0; x < pwidth; x++)
|
1999-08-21 08:18:58 +08:00
|
|
|
{
|
1999-08-28 03:07:21 +08:00
|
|
|
r = ((gdouble)(*(src++)))/255.0;
|
|
|
|
a = ((gdouble)(*(src++)))/255.0;
|
1999-08-25 05:59:32 +08:00
|
|
|
chk = ((gdouble)((( (x^y) & 4 ) << 4) | 128))/255.0;
|
1999-08-28 03:07:21 +08:00
|
|
|
*(dest++) = (guchar)((chk + (r - chk)*a)*255.0);
|
|
|
|
*(dest++) = (guchar)((chk + (r - chk)*a)*255.0);
|
|
|
|
*(dest++) = (guchar)((chk + (r - chk)*a)*255.0);
|
1999-08-21 08:18:58 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_warning("UNKNOWN TempBuf bpp in nav_window_update_preview()");
|
|
|
|
}
|
1999-08-28 03:07:21 +08:00
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
gtk_preview_draw_row (GTK_PREVIEW (iwd->preview),
|
1999-10-21 06:15:13 +08:00
|
|
|
(guchar *)buf, xoff, yoff+y, preview_buf_ptr->width);
|
1999-08-13 06:21:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
g_free (buf);
|
|
|
|
temp_buf_free (preview_buf);
|
|
|
|
|
1999-10-21 06:15:13 +08:00
|
|
|
if(preview_buf_notdot)
|
|
|
|
temp_buf_free(preview_buf_notdot);
|
|
|
|
|
1999-08-21 07:20:23 +08:00
|
|
|
gimp_remove_busy_cursors (NULL);
|
1999-08-13 06:21:04 +08:00
|
|
|
}
|
|
|
|
|
1999-09-02 06:39:44 +08:00
|
|
|
static void
|
1999-10-16 21:07:15 +08:00
|
|
|
nav_window_update_preview_blank (NavWinData *iwd)
|
1999-08-28 03:07:21 +08:00
|
|
|
{
|
|
|
|
GDisplay *gdisp;
|
|
|
|
guchar *buf, *dest;
|
|
|
|
gint x,y;
|
|
|
|
GimpImage *gimage;
|
|
|
|
gdouble chk;
|
|
|
|
|
|
|
|
gdisp = (GDisplay *) iwd->gdisp_ptr;
|
|
|
|
|
|
|
|
/* Calculate preview size */
|
|
|
|
gimage = ((GDisplay *)(iwd->gdisp_ptr))->gimage;
|
|
|
|
|
|
|
|
buf = g_new (gchar, iwd->pwidth * 3);
|
|
|
|
|
|
|
|
for (y = 0; y < iwd->pheight ; y++)
|
|
|
|
{
|
|
|
|
dest = buf;
|
|
|
|
for (x = 0; x < iwd->pwidth; x++)
|
|
|
|
{
|
|
|
|
chk = ((gdouble)((( (x^y) & 4 ) << 4) | 128))/255.0;
|
|
|
|
chk *= 128.0;
|
|
|
|
*(dest++) = (guchar)chk;
|
|
|
|
*(dest++) = (guchar)chk;
|
|
|
|
*(dest++) = (guchar)chk;
|
|
|
|
}
|
|
|
|
|
|
|
|
gtk_preview_draw_row (GTK_PREVIEW (iwd->preview),
|
|
|
|
(guchar *)buf, 0, y, iwd->pwidth);
|
|
|
|
}
|
|
|
|
|
|
|
|
g_free (buf);
|
|
|
|
|
|
|
|
gdk_flush();
|
|
|
|
}
|
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
static gint
|
1999-10-16 21:07:15 +08:00
|
|
|
inside_preview_square (NavWinData *iwd,
|
|
|
|
gint x,
|
|
|
|
gint y)
|
1999-08-13 06:21:04 +08:00
|
|
|
{
|
|
|
|
if(x > iwd->dispx &&
|
|
|
|
x < (iwd->dispx + iwd->dispwidth) &&
|
|
|
|
y > iwd->dispy &&
|
|
|
|
y < iwd->dispy + iwd->dispheight)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
1999-08-28 03:07:21 +08:00
|
|
|
static void
|
1999-10-16 21:07:15 +08:00
|
|
|
update_zoom_label (NavWinData *iwd)
|
1999-08-13 06:21:04 +08:00
|
|
|
{
|
1999-08-28 03:07:21 +08:00
|
|
|
gchar scale_str[MAX_SCALE_BUF];
|
1999-08-13 06:21:04 +08:00
|
|
|
|
1999-09-02 06:39:44 +08:00
|
|
|
if(!iwd->zoom_label)
|
|
|
|
return;
|
|
|
|
|
1999-08-28 03:07:21 +08:00
|
|
|
/* Update the zoom scale string */
|
|
|
|
g_snprintf (scale_str, MAX_SCALE_BUF, "%d:%d",
|
|
|
|
SCALEDEST (((GDisplay *)iwd->gdisp_ptr)),
|
|
|
|
SCALESRC (((GDisplay *)iwd->gdisp_ptr)));
|
|
|
|
|
|
|
|
gtk_label_set_text(GTK_LABEL(iwd->zoom_label),scale_str);
|
|
|
|
}
|
1999-08-13 06:21:04 +08:00
|
|
|
|
1999-08-28 03:07:21 +08:00
|
|
|
static void
|
1999-10-16 21:07:15 +08:00
|
|
|
update_zoom_adjustment (NavWinData *iwd)
|
1999-08-28 03:07:21 +08:00
|
|
|
{
|
1999-09-02 06:39:44 +08:00
|
|
|
GtkAdjustment *adj;
|
|
|
|
gdouble f;
|
1999-08-28 03:07:21 +08:00
|
|
|
gdouble val;
|
1999-09-02 06:39:44 +08:00
|
|
|
|
|
|
|
if(!iwd->zoom_adjustment)
|
|
|
|
return;
|
|
|
|
|
|
|
|
adj = GTK_ADJUSTMENT(iwd->zoom_adjustment);
|
|
|
|
f = ((gdouble)SCALEDEST (((GDisplay *)iwd->gdisp_ptr)))/((gdouble)SCALESRC (((GDisplay *)iwd->gdisp_ptr)));
|
1999-08-28 03:07:21 +08:00
|
|
|
|
|
|
|
if(f < 1.0)
|
|
|
|
{
|
|
|
|
val = -1/f;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
val = f;
|
|
|
|
}
|
1999-08-13 06:21:04 +08:00
|
|
|
|
1999-08-28 03:07:21 +08:00
|
|
|
if(abs((gint)adj->value) != (gint)(val - 1) && iwd->block_adj_sig != TRUE)
|
|
|
|
{
|
|
|
|
adj->value = val;
|
|
|
|
gtk_signal_emit_by_name (GTK_OBJECT (iwd->zoom_adjustment), "changed");
|
|
|
|
}
|
1999-08-13 06:21:04 +08:00
|
|
|
}
|
|
|
|
|
1999-08-24 06:47:36 +08:00
|
|
|
static void
|
1999-10-16 21:07:15 +08:00
|
|
|
move_to_point (NavWinData *iwd,
|
|
|
|
gint tx,
|
|
|
|
gint ty)
|
1999-08-24 06:47:36 +08:00
|
|
|
{
|
1999-10-22 03:35:35 +08:00
|
|
|
tx = CLAMP (tx, 0, iwd->pwidth);
|
|
|
|
ty = CLAMP (ty, 0, iwd->pheight);
|
1999-08-24 06:47:36 +08:00
|
|
|
|
1999-10-27 02:27:27 +08:00
|
|
|
if ((tx + iwd->dispwidth) >= iwd->pwidth)
|
1999-08-24 06:47:36 +08:00
|
|
|
{
|
|
|
|
tx = iwd->pwidth - iwd->dispwidth;
|
|
|
|
}
|
|
|
|
|
1999-10-27 02:27:27 +08:00
|
|
|
if ((ty + iwd->dispheight) >= iwd->pheight)
|
1999-08-24 06:47:36 +08:00
|
|
|
{
|
|
|
|
ty = iwd->pheight - iwd->dispheight;
|
|
|
|
}
|
|
|
|
|
1999-10-22 03:35:35 +08:00
|
|
|
if (iwd->dispx == tx && iwd->dispy == ty)
|
|
|
|
return;
|
|
|
|
|
1999-08-24 06:47:36 +08:00
|
|
|
/* Update the real display */
|
1999-10-27 02:27:27 +08:00
|
|
|
update_real_view (iwd, tx, ty);
|
1999-08-24 06:47:36 +08:00
|
|
|
|
1999-10-27 02:27:27 +08:00
|
|
|
nav_window_draw_sqr (iwd,
|
|
|
|
TRUE,
|
|
|
|
tx, ty,
|
|
|
|
iwd->dispwidth, iwd->dispheight);
|
1999-08-24 06:47:36 +08:00
|
|
|
|
|
|
|
}
|
1999-08-13 06:21:04 +08:00
|
|
|
|
1999-09-02 06:39:44 +08:00
|
|
|
static void
|
1999-10-16 21:07:15 +08:00
|
|
|
nav_window_grab_pointer (NavWinData *iwd,
|
|
|
|
GtkWidget *widget)
|
1999-09-02 06:39:44 +08:00
|
|
|
{
|
|
|
|
GdkCursor *cursor;
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
iwd->sq_grabbed = TRUE;
|
1999-10-27 02:27:27 +08:00
|
|
|
gtk_grab_add (widget);
|
|
|
|
cursor = gdk_cursor_new (GDK_CROSSHAIR);
|
1999-09-02 06:39:44 +08:00
|
|
|
ret = gdk_pointer_grab (widget->window, TRUE,
|
1999-10-27 02:27:27 +08:00
|
|
|
GDK_BUTTON_RELEASE_MASK |
|
|
|
|
GDK_POINTER_MOTION_HINT_MASK |
|
|
|
|
GDK_BUTTON_MOTION_MASK |
|
|
|
|
GDK_EXTENSION_EVENTS_ALL,
|
|
|
|
widget->window, cursor, 0);
|
1999-09-02 06:39:44 +08:00
|
|
|
|
1999-10-27 02:27:27 +08:00
|
|
|
gdk_cursor_destroy (cursor);
|
1999-09-02 06:39:44 +08:00
|
|
|
}
|
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
static gint
|
|
|
|
nav_window_preview_events (GtkWidget *widget,
|
|
|
|
GdkEvent *event,
|
|
|
|
gpointer *data)
|
|
|
|
{
|
|
|
|
NavWinData *iwd;
|
|
|
|
GDisplay *gdisp;
|
|
|
|
GdkEventButton *bevent;
|
|
|
|
GdkEventMotion *mevent;
|
1999-08-24 06:47:36 +08:00
|
|
|
GdkEventKey *kevent;
|
1999-08-21 07:20:23 +08:00
|
|
|
GdkModifierType mask;
|
1999-08-24 06:47:36 +08:00
|
|
|
gint tx = 0,ty = 0; /* So compiler complaints */
|
1999-08-21 07:20:23 +08:00
|
|
|
gint mx,my;
|
1999-08-24 06:47:36 +08:00
|
|
|
gboolean arrowKey = FALSE;
|
1999-08-13 06:21:04 +08:00
|
|
|
|
|
|
|
iwd = (NavWinData *)data;
|
|
|
|
|
|
|
|
if(!iwd)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
gdisp = (GDisplay *) iwd->gdisp_ptr;
|
|
|
|
|
|
|
|
switch (event->type)
|
|
|
|
{
|
|
|
|
case GDK_EXPOSE:
|
|
|
|
break;
|
|
|
|
case GDK_MAP:
|
1999-09-02 06:39:44 +08:00
|
|
|
if(iwd->ptype == NAV_POPUP)
|
|
|
|
{
|
|
|
|
nav_window_update_preview(iwd);
|
|
|
|
/* First time displayed.... get the pointer! */
|
|
|
|
nav_window_grab_pointer(iwd,iwd->preview);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
nav_window_update_preview_blank(iwd);
|
|
|
|
gtk_timeout_add(PREVIEW_UPDATE_TIMEOUT,(GtkFunction)nav_preview_update_do_timer,(gpointer)iwd);
|
|
|
|
}
|
1999-08-13 06:21:04 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case GDK_BUTTON_PRESS:
|
|
|
|
bevent = (GdkEventButton *) event;
|
|
|
|
tx = bevent->x;
|
|
|
|
ty = bevent->y;
|
|
|
|
|
|
|
|
/* Must start the move */
|
|
|
|
switch (bevent->button)
|
|
|
|
{
|
|
|
|
case 1:
|
1999-09-02 06:39:44 +08:00
|
|
|
if(!inside_preview_square(iwd,tx,ty))
|
1999-08-13 06:21:04 +08:00
|
|
|
{
|
|
|
|
/* Direct scroll to the location */
|
|
|
|
/* view scrolled to the center or nearest possible point */
|
|
|
|
|
|
|
|
tx -= iwd->dispwidth/2;
|
|
|
|
ty -= iwd->dispheight/2;
|
|
|
|
|
|
|
|
if(tx < 0)
|
|
|
|
tx = 0;
|
|
|
|
|
|
|
|
if((tx + iwd->dispwidth) > iwd->pwidth)
|
|
|
|
tx = iwd->pwidth - iwd->dispwidth;
|
|
|
|
|
|
|
|
if(ty < 0)
|
|
|
|
ty = 0;
|
|
|
|
|
|
|
|
if((ty + iwd->dispheight) > iwd->pheight)
|
|
|
|
ty = iwd->pheight - iwd->dispheight;
|
|
|
|
|
|
|
|
update_real_view(iwd,tx,ty);
|
|
|
|
|
|
|
|
nav_window_draw_sqr(iwd,
|
|
|
|
TRUE,
|
1999-10-16 21:07:15 +08:00
|
|
|
tx, ty,
|
1999-08-13 06:21:04 +08:00
|
|
|
iwd->dispwidth,iwd->dispheight);
|
1999-09-02 06:39:44 +08:00
|
|
|
iwd->motion_offsetx = iwd->dispwidth/2;
|
|
|
|
iwd->motion_offsety = iwd->dispheight/2;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
iwd->motion_offsetx = tx - iwd->dispx;
|
|
|
|
iwd->motion_offsety = ty - iwd->dispy;
|
1999-08-13 06:21:04 +08:00
|
|
|
}
|
1999-09-02 06:39:44 +08:00
|
|
|
|
1999-10-16 21:07:15 +08:00
|
|
|
nav_window_grab_pointer (iwd, widget);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* wheelmouse support */
|
|
|
|
case 4:
|
|
|
|
if (bevent->state & GDK_SHIFT_MASK)
|
|
|
|
{
|
|
|
|
change_scale (gdisp, ZOOMIN);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GtkAdjustment *adj =
|
|
|
|
(bevent->state & GDK_CONTROL_MASK) ?
|
|
|
|
gdisp->hsbdata : gdisp->vsbdata;
|
|
|
|
gfloat new_value = adj->value - adj->page_increment / 2;
|
|
|
|
new_value =
|
|
|
|
CLAMP (new_value, adj->lower, adj->upper - adj->page_size);
|
|
|
|
gtk_adjustment_set_value (adj, new_value);
|
|
|
|
}
|
|
|
|
break;
|
1999-09-05 06:27:20 +08:00
|
|
|
|
1999-10-16 21:07:15 +08:00
|
|
|
case 5:
|
|
|
|
if (bevent->state & GDK_SHIFT_MASK)
|
|
|
|
{
|
|
|
|
change_scale (gdisp, ZOOMOUT);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GtkAdjustment *adj =
|
|
|
|
(bevent->state & GDK_CONTROL_MASK) ?
|
|
|
|
gdisp->hsbdata : gdisp->vsbdata;
|
|
|
|
gfloat new_value = adj->value + adj->page_increment / 2;
|
|
|
|
new_value = CLAMP (new_value,
|
|
|
|
adj->lower, adj->upper - adj->page_size);
|
|
|
|
gtk_adjustment_set_value (adj, new_value);
|
|
|
|
}
|
1999-08-13 06:21:04 +08:00
|
|
|
break;
|
1999-10-16 21:07:15 +08:00
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
default:
|
Actually use the enum types GimpImageType, GimpImageBaseType,
* app/*.[ch]: Actually use the enum types GimpImageType,
GimpImageBaseType, LayerModeEffects, PaintApplicationMode,
BrushApplicationMode, GimpFillType and ConvertPaletteType, instead
of just int or gint. Hopefully I catched most of the places
where these should be used.
Add an enum ConvolutionType, suffix the too general constants
NORMAL, ABSOLUTE and NEGATIVE with _CONVOL. Use NORMAL_MODE
instead of NORMAL in some places (this was what was intended). Fix
some minor gccisms.
* app/apptypes.h: New file. This file contains the above
enumeration types, and some opaque struct typedefs. It was
necessary to collect these in one header that doesn't include
other headers, because when we started using the above mentioned
types in the headers, all hell broke loose because of the
spaghetti-like cross-inclusion mess between headers.
(An example: Header A includes header B, which includes header C
which includes A. B uses a type defined in A. This is not defined,
because A hasn't defined it yet at the point where it includes B,
and A included from B of course is skipped as we already are
reading A.)
1999-08-19 07:41:39 +08:00
|
|
|
break;
|
1999-08-13 06:21:04 +08:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case GDK_BUTTON_RELEASE:
|
|
|
|
bevent = (GdkEventButton *) event;
|
|
|
|
tx = bevent->x;
|
|
|
|
ty = bevent->y;
|
|
|
|
|
|
|
|
switch (bevent->button)
|
|
|
|
{
|
|
|
|
case 1:
|
|
|
|
iwd->sq_grabbed = FALSE;
|
|
|
|
gtk_grab_remove(widget);
|
1999-08-21 07:20:23 +08:00
|
|
|
gdk_pointer_ungrab (0);
|
1999-09-02 06:39:44 +08:00
|
|
|
if(iwd->ptype == NAV_POPUP)
|
|
|
|
{
|
|
|
|
gtk_widget_hide(gdisp->nav_popup);
|
|
|
|
}
|
1999-08-21 07:20:23 +08:00
|
|
|
gdk_flush();
|
1999-08-13 06:21:04 +08:00
|
|
|
break;
|
|
|
|
default:
|
Actually use the enum types GimpImageType, GimpImageBaseType,
* app/*.[ch]: Actually use the enum types GimpImageType,
GimpImageBaseType, LayerModeEffects, PaintApplicationMode,
BrushApplicationMode, GimpFillType and ConvertPaletteType, instead
of just int or gint. Hopefully I catched most of the places
where these should be used.
Add an enum ConvolutionType, suffix the too general constants
NORMAL, ABSOLUTE and NEGATIVE with _CONVOL. Use NORMAL_MODE
instead of NORMAL in some places (this was what was intended). Fix
some minor gccisms.
* app/apptypes.h: New file. This file contains the above
enumeration types, and some opaque struct typedefs. It was
necessary to collect these in one header that doesn't include
other headers, because when we started using the above mentioned
types in the headers, all hell broke loose because of the
spaghetti-like cross-inclusion mess between headers.
(An example: Header A includes header B, which includes header C
which includes A. B uses a type defined in A. This is not defined,
because A hasn't defined it yet at the point where it includes B,
and A included from B of course is skipped as we already are
reading A.)
1999-08-19 07:41:39 +08:00
|
|
|
break;
|
1999-08-13 06:21:04 +08:00
|
|
|
}
|
|
|
|
break;
|
1999-10-16 21:07:15 +08:00
|
|
|
|
1999-08-24 06:47:36 +08:00
|
|
|
case GDK_KEY_PRESS:
|
|
|
|
/* hack for the update preview... needs to be fixed */
|
|
|
|
kevent = (GdkEventKey *) event;
|
|
|
|
|
|
|
|
switch (kevent->keyval)
|
|
|
|
{
|
|
|
|
case GDK_space:
|
|
|
|
gdk_window_raise(gdisp->shell->window);
|
|
|
|
break;
|
|
|
|
case GDK_Up:
|
|
|
|
arrowKey = TRUE;
|
|
|
|
tx = iwd->dispx;
|
|
|
|
ty = iwd->dispy - 1;
|
|
|
|
break;
|
|
|
|
case GDK_Left:
|
|
|
|
arrowKey = TRUE;
|
|
|
|
tx = iwd->dispx - 1;
|
|
|
|
ty = iwd->dispy;
|
|
|
|
break;
|
|
|
|
case GDK_Right:
|
|
|
|
arrowKey = TRUE;
|
|
|
|
tx = iwd->dispx + 1;
|
|
|
|
ty = iwd->dispy;
|
|
|
|
break;
|
|
|
|
case GDK_Down:
|
|
|
|
arrowKey = TRUE;
|
|
|
|
tx = iwd->dispx;
|
|
|
|
ty = iwd->dispy + 1;
|
|
|
|
break;
|
|
|
|
case GDK_equal:
|
|
|
|
change_scale(gdisp,ZOOMIN);
|
|
|
|
break;
|
|
|
|
case GDK_minus:
|
|
|
|
change_scale(gdisp,ZOOMOUT);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
1999-08-13 06:21:04 +08:00
|
|
|
|
1999-08-24 06:47:36 +08:00
|
|
|
if(arrowKey)
|
|
|
|
{
|
|
|
|
move_to_point(iwd,tx,ty);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
break;
|
1999-10-16 21:07:15 +08:00
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
case GDK_MOTION_NOTIFY:
|
|
|
|
mevent = (GdkEventMotion *) event;
|
|
|
|
|
|
|
|
if(!iwd->sq_grabbed)
|
|
|
|
break;
|
|
|
|
|
1999-08-21 07:20:23 +08:00
|
|
|
gdk_window_get_pointer (widget->window, &mx, &my, &mask);
|
|
|
|
tx = mx;
|
|
|
|
ty = my;
|
|
|
|
|
|
|
|
tx = tx - iwd->motion_offsetx;
|
|
|
|
ty = ty - iwd->motion_offsety;
|
1999-08-13 06:21:04 +08:00
|
|
|
|
1999-08-24 06:47:36 +08:00
|
|
|
move_to_point(iwd,tx,ty);
|
1999-08-13 06:21:04 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
nav_window_expose_events (GtkWidget *widget,
|
|
|
|
GdkEvent *event,
|
|
|
|
gpointer *data)
|
|
|
|
{
|
|
|
|
NavWinData *iwd;
|
|
|
|
GDisplay *gdisp;
|
|
|
|
|
|
|
|
iwd = (NavWinData *)data;
|
|
|
|
|
|
|
|
if(!iwd)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
gdisp = (GDisplay *) iwd->gdisp_ptr;
|
|
|
|
|
|
|
|
switch (event->type)
|
|
|
|
{
|
|
|
|
case GDK_EXPOSE:
|
1999-09-02 06:39:44 +08:00
|
|
|
/* we must have the grab if in nav_popup*/
|
1999-08-13 06:21:04 +08:00
|
|
|
gtk_signal_handler_block(GTK_OBJECT(widget),iwd->sig_hand_id);
|
|
|
|
gtk_widget_draw(iwd->preview, NULL);
|
|
|
|
gtk_signal_handler_unblock(GTK_OBJECT(widget),iwd->sig_hand_id );
|
|
|
|
|
|
|
|
nav_window_draw_sqr(iwd,FALSE,
|
|
|
|
iwd->dispx,iwd->dispy,
|
|
|
|
iwd->dispwidth,iwd->dispheight);
|
1999-09-02 06:39:44 +08:00
|
|
|
if(!gtk_grab_get_current() && iwd->ptype == NAV_POPUP)
|
|
|
|
nav_window_grab_pointer(iwd,iwd->preview);
|
1999-08-13 06:21:04 +08:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
1999-08-25 05:59:32 +08:00
|
|
|
static gint
|
1999-10-16 21:07:15 +08:00
|
|
|
nav_preview_update_do (NavWinData *iwd)
|
1999-08-25 05:59:32 +08:00
|
|
|
{
|
1999-08-28 03:07:21 +08:00
|
|
|
nav_window_update_preview(iwd);
|
|
|
|
nav_window_disp_area(iwd,iwd->gdisp_ptr);
|
1999-11-06 11:03:26 +08:00
|
|
|
gtk_widget_queue_draw(iwd->preview);
|
1999-08-25 05:59:32 +08:00
|
|
|
iwd->installedDirtyTimer = FALSE;
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gint
|
|
|
|
nav_preview_update_do_timer(NavWinData *iwd)
|
|
|
|
{
|
|
|
|
gtk_idle_add((GtkFunction)nav_preview_update_do,(gpointer)iwd);
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
nav_image_need_update (GtkObject *obj,
|
|
|
|
gpointer client_data)
|
|
|
|
{
|
|
|
|
NavWinData *iwd;
|
|
|
|
|
|
|
|
iwd = (NavWinData *)client_data;
|
|
|
|
|
|
|
|
if(!iwd || !iwd->showingPreview || iwd->installedDirtyTimer == TRUE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
iwd->installedDirtyTimer = TRUE;
|
|
|
|
|
|
|
|
/* Update preview at a less busy time */
|
1999-08-28 03:07:21 +08:00
|
|
|
nav_window_update_preview_blank(iwd);
|
1999-08-25 05:59:32 +08:00
|
|
|
gtk_widget_draw(iwd->preview, NULL);
|
1999-08-28 03:07:21 +08:00
|
|
|
gtk_timeout_add(PREVIEW_UPDATE_TIMEOUT,(GtkFunction)nav_preview_update_do_timer,(gpointer)iwd);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
navwindow_zoomin (GtkWidget *widget,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
NavWinData *iwd;
|
|
|
|
GDisplay *gdisp;
|
|
|
|
|
|
|
|
iwd = (NavWinData *)data;
|
|
|
|
|
|
|
|
if(!iwd)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gdisp = (GDisplay *) iwd->gdisp_ptr;
|
|
|
|
|
|
|
|
change_scale(gdisp,ZOOMIN);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
navwindow_zoomout (GtkWidget *widget,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
NavWinData *iwd;
|
|
|
|
GDisplay *gdisp;
|
|
|
|
|
|
|
|
iwd = (NavWinData *)data;
|
|
|
|
|
|
|
|
if(!iwd)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gdisp = (GDisplay *) iwd->gdisp_ptr;
|
|
|
|
|
|
|
|
change_scale(gdisp,ZOOMOUT);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
zoom_adj_changed (GtkAdjustment *adj,
|
|
|
|
gpointer data)
|
|
|
|
{
|
|
|
|
NavWinData *iwd;
|
|
|
|
GDisplay *gdisp;
|
|
|
|
gint scalesrc, scaledest;
|
|
|
|
|
|
|
|
iwd = (NavWinData *)data;
|
|
|
|
|
|
|
|
if(!iwd)
|
|
|
|
return;
|
|
|
|
|
|
|
|
gdisp = (GDisplay *) iwd->gdisp_ptr;
|
|
|
|
|
|
|
|
if(adj->value < 0.0)
|
|
|
|
{
|
|
|
|
scalesrc = abs((gint)adj->value-1);
|
|
|
|
scaledest = 1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
scaledest = abs((gint)adj->value+1);
|
|
|
|
scalesrc = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
iwd->block_adj_sig = TRUE;
|
|
|
|
change_scale(gdisp,(scaledest*100)+scalesrc);
|
|
|
|
iwd->block_adj_sig = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GtkWidget *
|
1999-10-16 21:07:15 +08:00
|
|
|
nav_create_button_area (InfoDialog *info_win)
|
1999-08-28 03:07:21 +08:00
|
|
|
{
|
|
|
|
GtkWidget *hbox1;
|
|
|
|
GtkWidget *vbox1;
|
|
|
|
GtkWidget *button;
|
|
|
|
GtkWidget *hscale1;
|
|
|
|
GtkWidget *label1;
|
|
|
|
GtkObject *adjustment;
|
|
|
|
GdkPixmap *pixmap;
|
|
|
|
GtkWidget *pixmapwid;
|
|
|
|
GdkBitmap *mask;
|
|
|
|
GtkStyle *style;
|
|
|
|
NavWinData *iwd;
|
|
|
|
gchar scale_str[MAX_SCALE_BUF];
|
|
|
|
|
|
|
|
iwd = (NavWinData *)info_win->user_data;
|
|
|
|
|
|
|
|
hbox1 = gtk_hbox_new (FALSE, 0);
|
|
|
|
gtk_widget_show (hbox1);
|
|
|
|
|
|
|
|
style = gtk_widget_get_style (info_win->shell);
|
|
|
|
|
|
|
|
button = gtk_button_new ();
|
|
|
|
GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
|
|
|
|
gtk_signal_connect (GTK_OBJECT (button), "clicked",
|
|
|
|
GTK_SIGNAL_FUNC (navwindow_zoomout), (gpointer) info_win->user_data);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox1), button, FALSE, FALSE, 0);
|
|
|
|
|
|
|
|
pixmap = gdk_pixmap_create_from_xpm_d (info_win->shell->window, &mask,
|
|
|
|
&style->bg[GTK_STATE_NORMAL],
|
|
|
|
zoom_out_xpm);
|
|
|
|
pixmapwid = gtk_pixmap_new (pixmap, mask);
|
|
|
|
gtk_container_add (GTK_CONTAINER (button), pixmapwid);
|
|
|
|
gtk_widget_show (pixmapwid);
|
|
|
|
gtk_widget_show (button);
|
|
|
|
|
|
|
|
vbox1 = gtk_vbox_new (FALSE, 0);
|
|
|
|
gtk_widget_show (vbox1);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);
|
|
|
|
|
|
|
|
/* user zoom ratio */
|
|
|
|
g_snprintf (scale_str, MAX_SCALE_BUF, "%d:%d",
|
|
|
|
SCALEDEST (((GDisplay *)iwd->gdisp_ptr)),
|
|
|
|
SCALESRC (((GDisplay *)iwd->gdisp_ptr)));
|
|
|
|
|
|
|
|
label1 = gtk_label_new (scale_str);
|
|
|
|
gtk_widget_show (label1);
|
|
|
|
iwd->zoom_label = label1;
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox1), label1, TRUE, TRUE, 0);
|
|
|
|
|
|
|
|
adjustment = gtk_adjustment_new (0.0, -15.0, 16.0, 1.0, 1.0, 1.0);
|
|
|
|
hscale1 = gtk_hscale_new (GTK_ADJUSTMENT (adjustment));
|
|
|
|
gtk_scale_set_digits (GTK_SCALE (hscale1), 0);
|
|
|
|
iwd->zoom_adjustment = adjustment;
|
|
|
|
gtk_widget_show (hscale1);
|
|
|
|
|
|
|
|
gtk_signal_connect (GTK_OBJECT (adjustment), "value_changed",
|
|
|
|
GTK_SIGNAL_FUNC (zoom_adj_changed),
|
|
|
|
iwd);
|
|
|
|
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox1), hscale1, TRUE, TRUE, 0);
|
|
|
|
gtk_scale_set_draw_value (GTK_SCALE (hscale1), FALSE);
|
|
|
|
|
|
|
|
button = gtk_button_new ();
|
|
|
|
GTK_WIDGET_UNSET_FLAGS (button, GTK_RECEIVES_DEFAULT);
|
|
|
|
gtk_signal_connect (GTK_OBJECT (button), "clicked",
|
|
|
|
GTK_SIGNAL_FUNC (navwindow_zoomin), (gpointer) info_win->user_data);
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox1), button, FALSE, FALSE, 0);
|
|
|
|
|
|
|
|
pixmap = gdk_pixmap_create_from_xpm_d (info_win->shell->window, &mask,
|
|
|
|
&style->bg[GTK_STATE_NORMAL],
|
|
|
|
zoom_in_xpm);
|
|
|
|
pixmapwid = gtk_pixmap_new (pixmap, mask);
|
|
|
|
gtk_container_add (GTK_CONTAINER (button), pixmapwid);
|
|
|
|
gtk_widget_show (pixmapwid);
|
|
|
|
gtk_widget_show (button);
|
|
|
|
|
|
|
|
return vbox1;
|
1999-08-25 05:59:32 +08:00
|
|
|
}
|
1999-08-13 06:21:04 +08:00
|
|
|
|
|
|
|
static GtkWidget *
|
1999-10-16 21:07:15 +08:00
|
|
|
create_preview_containers (NavWinData *iwd,
|
|
|
|
GtkWidget *shell)
|
1999-08-13 06:21:04 +08:00
|
|
|
{
|
|
|
|
GtkWidget *hbox1;
|
1999-08-28 03:07:21 +08:00
|
|
|
GtkWidget *vbox1;
|
1999-08-13 06:21:04 +08:00
|
|
|
GtkWidget *alignment;
|
|
|
|
|
|
|
|
hbox1 = gtk_hbox_new (FALSE, 0);
|
|
|
|
gtk_widget_show (hbox1);
|
|
|
|
|
1999-08-28 03:07:21 +08:00
|
|
|
vbox1 = gtk_vbox_new (FALSE, 0);
|
|
|
|
gtk_widget_show (vbox1);
|
|
|
|
|
1999-09-02 06:39:44 +08:00
|
|
|
gtk_widget_realize(shell);
|
1999-08-13 06:21:04 +08:00
|
|
|
|
|
|
|
/* need gc to draw the preview sqr with */
|
1999-09-02 06:39:44 +08:00
|
|
|
iwd->gc = gdk_gc_new(shell->window);
|
1999-08-13 06:21:04 +08:00
|
|
|
gdk_gc_set_function (iwd->gc, GDK_INVERT);
|
|
|
|
gdk_gc_set_line_attributes (iwd->gc, BORDER_PEN_WIDTH, GDK_LINE_SOLID,
|
|
|
|
GDK_CAP_BUTT, GDK_JOIN_ROUND);
|
|
|
|
|
|
|
|
alignment = gtk_alignment_new(0.5,0.5,0.0,0.0);
|
|
|
|
iwd->previewAlign = alignment;
|
|
|
|
gtk_widget_show (alignment);
|
|
|
|
|
|
|
|
/* Create the preview in which to draw the thumbnail image */
|
|
|
|
|
|
|
|
create_preview_widget(iwd);
|
|
|
|
|
|
|
|
gtk_box_pack_start (GTK_BOX (hbox1), alignment, TRUE, TRUE, 0);
|
1999-08-28 03:07:21 +08:00
|
|
|
gtk_box_pack_start (GTK_BOX (vbox1), hbox1, TRUE, TRUE, 0);
|
1999-08-13 06:21:04 +08:00
|
|
|
|
1999-09-02 06:39:44 +08:00
|
|
|
return vbox1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GtkWidget *
|
1999-10-16 21:07:15 +08:00
|
|
|
info_window_image_preview_new (InfoDialog *info_win)
|
1999-09-02 06:39:44 +08:00
|
|
|
{
|
|
|
|
GtkWidget *button_area;
|
|
|
|
GtkWidget *vbox1;
|
|
|
|
|
|
|
|
NavWinData *iwd;
|
|
|
|
|
|
|
|
iwd = (NavWinData *)info_win->user_data;
|
|
|
|
|
|
|
|
vbox1 = create_preview_containers(iwd,info_win->shell);
|
|
|
|
|
|
|
|
/* This one has (may) have the buttons in */
|
1999-08-28 03:07:21 +08:00
|
|
|
button_area = nav_create_button_area(info_win);
|
|
|
|
gtk_box_pack_start (GTK_BOX (vbox1), button_area, TRUE, TRUE, 0);
|
|
|
|
|
|
|
|
return vbox1;
|
1999-08-13 06:21:04 +08:00
|
|
|
}
|
|
|
|
|
1999-09-02 06:39:44 +08:00
|
|
|
NavWinData *
|
1999-10-16 21:07:15 +08:00
|
|
|
create_dummy_iwd (void *gdisp_ptr,
|
|
|
|
NavWinType ptype)
|
1999-09-02 06:39:44 +08:00
|
|
|
{
|
|
|
|
NavWinData *iwd;
|
|
|
|
iwd = (NavWinData *) g_malloc (sizeof (NavWinData));
|
|
|
|
iwd->ptype = ptype;
|
|
|
|
iwd->info_win = NULL;
|
|
|
|
iwd->showingPreview = TRUE;
|
|
|
|
iwd->installedDirtyTimer = FALSE;
|
|
|
|
iwd->preview = NULL;
|
|
|
|
iwd->zoom_label = NULL;
|
|
|
|
iwd->zoom_adjustment = NULL;
|
|
|
|
iwd->gdisp_ptr = gdisp_ptr;
|
|
|
|
iwd->dispx = -1;
|
|
|
|
iwd->dispy = -1;
|
|
|
|
iwd->dispwidth = -1;
|
|
|
|
iwd->dispheight = -1;
|
|
|
|
iwd->imagewidth = -1;
|
|
|
|
iwd->imageheight = -1;
|
|
|
|
iwd->sq_grabbed = FALSE;
|
|
|
|
iwd->ratio = 1.0;
|
|
|
|
iwd->block_window_marker = FALSE;
|
1999-09-05 06:27:20 +08:00
|
|
|
iwd->nav_preview_width =
|
|
|
|
(nav_preview_size < 0 || nav_preview_size > 256)?NAV_PREVIEW_WIDTH:nav_preview_size;
|
|
|
|
iwd->nav_preview_height =
|
|
|
|
(nav_preview_size < 0 || nav_preview_size > 256)?NAV_PREVIEW_HEIGHT:nav_preview_size;
|
1999-09-02 06:39:44 +08:00
|
|
|
iwd->block_adj_sig = FALSE;
|
|
|
|
|
|
|
|
return(iwd);
|
|
|
|
}
|
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
InfoDialog *
|
|
|
|
nav_window_create (void *gdisp_ptr)
|
|
|
|
{
|
|
|
|
InfoDialog *info_win;
|
|
|
|
GDisplay *gdisp;
|
|
|
|
NavWinData *iwd;
|
|
|
|
GtkWidget *container;
|
|
|
|
char *title;
|
|
|
|
char *title_buf;
|
|
|
|
int type;
|
|
|
|
|
|
|
|
gdisp = (GDisplay *) gdisp_ptr;
|
|
|
|
|
|
|
|
title = g_basename (gimage_filename (gdisp->gimage));
|
|
|
|
type = gimage_base_type (gdisp->gimage);
|
|
|
|
|
|
|
|
/* create the info dialog */
|
|
|
|
title_buf = g_strdup_printf (_("%s: Window Navigation"), title);
|
1999-09-28 01:58:10 +08:00
|
|
|
info_win = info_dialog_new (title_buf,
|
|
|
|
gimp_standard_help_func,
|
|
|
|
"dialogs/navigation_window.html");
|
1999-10-27 02:27:27 +08:00
|
|
|
g_free (title_buf);
|
|
|
|
|
1999-09-28 01:58:10 +08:00
|
|
|
dialog_register (info_win->shell);
|
1999-10-27 02:27:27 +08:00
|
|
|
|
|
|
|
/* create the action area */
|
|
|
|
gimp_dialog_create_action_area (GTK_DIALOG (info_win->shell),
|
|
|
|
|
|
|
|
_("Close"), nav_window_close_callback,
|
|
|
|
info_win, NULL, TRUE, FALSE,
|
|
|
|
|
|
|
|
NULL);
|
|
|
|
|
1999-08-24 06:47:36 +08:00
|
|
|
gtk_signal_connect (GTK_OBJECT (info_win->shell), "destroy",
|
|
|
|
(GtkSignalFunc) nav_window_destroy_callback,
|
|
|
|
info_win);
|
1999-09-28 01:58:10 +08:00
|
|
|
|
|
|
|
iwd = create_dummy_iwd (gdisp_ptr, NAV_WINDOW);
|
1999-08-13 06:21:04 +08:00
|
|
|
info_win->user_data = iwd;
|
1999-08-24 06:47:36 +08:00
|
|
|
iwd->info_win = info_win;
|
1999-08-13 06:21:04 +08:00
|
|
|
|
|
|
|
/* Add preview */
|
1999-09-28 01:58:10 +08:00
|
|
|
container = info_window_image_preview_new (info_win);
|
1999-08-13 06:21:04 +08:00
|
|
|
gtk_table_attach_defaults (GTK_TABLE (info_win->info_table), container,
|
|
|
|
0, 2, 0, 1);
|
|
|
|
|
1999-08-25 05:59:32 +08:00
|
|
|
/* Tie into the dirty signal so we can update the preview */
|
|
|
|
gtk_signal_connect_after (GTK_OBJECT (gdisp->gimage), "dirty",
|
|
|
|
GTK_SIGNAL_FUNC(nav_image_need_update),iwd);
|
|
|
|
|
|
|
|
/* Also clean signal so undos get caught as well..*/
|
|
|
|
gtk_signal_connect_after (GTK_OBJECT (gdisp->gimage), "clean",
|
|
|
|
GTK_SIGNAL_FUNC(nav_image_need_update),iwd);
|
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
return info_win;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-10-16 21:07:15 +08:00
|
|
|
nav_window_update_window_marker (InfoDialog *info_win)
|
1999-08-13 06:21:04 +08:00
|
|
|
{
|
|
|
|
NavWinData *iwd;
|
|
|
|
|
|
|
|
if(!info_win)
|
|
|
|
return;
|
|
|
|
|
|
|
|
iwd = (NavWinData *)info_win->user_data;
|
|
|
|
|
|
|
|
if(!iwd ||
|
|
|
|
iwd->showingPreview == FALSE ||
|
|
|
|
iwd->block_window_marker == TRUE)
|
|
|
|
return;
|
|
|
|
|
1999-11-06 11:03:26 +08:00
|
|
|
update_zoom_label (iwd);
|
|
|
|
update_zoom_adjustment (iwd);
|
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
/* Undraw old size */
|
1999-11-06 11:03:26 +08:00
|
|
|
nav_window_draw_sqr (iwd,
|
|
|
|
FALSE,
|
|
|
|
iwd->dispx,
|
|
|
|
iwd->dispy,
|
|
|
|
iwd->dispwidth, iwd->dispheight);
|
1999-08-13 06:21:04 +08:00
|
|
|
|
|
|
|
/* Update to new size */
|
1999-11-06 11:03:26 +08:00
|
|
|
nav_window_disp_area (iwd,iwd->gdisp_ptr);
|
1999-09-02 06:39:44 +08:00
|
|
|
|
1999-08-13 06:21:04 +08:00
|
|
|
/* and redraw */
|
1999-11-06 11:03:26 +08:00
|
|
|
nav_window_draw_sqr (iwd,
|
1999-08-13 06:21:04 +08:00
|
|
|
FALSE,
|
|
|
|
iwd->dispx,
|
|
|
|
iwd->dispy,
|
1999-11-06 11:03:26 +08:00
|
|
|
iwd->dispwidth, iwd->dispheight);
|
1999-08-28 03:07:21 +08:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nav_dialog_popup (InfoDialog *idialog)
|
|
|
|
{
|
|
|
|
NavWinData *iwd;
|
|
|
|
|
|
|
|
if (!idialog)
|
|
|
|
return;
|
|
|
|
|
|
|
|
iwd = (NavWinData *)idialog->user_data;
|
|
|
|
iwd->showingPreview = TRUE;
|
|
|
|
|
|
|
|
if (! GTK_WIDGET_VISIBLE (idialog->shell))
|
|
|
|
{
|
|
|
|
gtk_widget_show (idialog->shell);
|
|
|
|
nav_window_update_preview_blank(iwd);
|
|
|
|
nav_window_update_window_marker(idialog);
|
1999-10-16 21:07:15 +08:00
|
|
|
gtk_timeout_add (PREVIEW_UPDATE_TIMEOUT,
|
|
|
|
(GtkFunction) nav_preview_update_do_timer,
|
|
|
|
(gpointer) iwd);
|
1999-08-28 03:07:21 +08:00
|
|
|
}
|
1999-08-13 06:21:04 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nav_window_free (InfoDialog *info_win)
|
|
|
|
{
|
|
|
|
g_free (info_win->user_data);
|
|
|
|
info_dialog_free (info_win);
|
|
|
|
}
|
1999-09-02 06:39:44 +08:00
|
|
|
|
|
|
|
|
|
|
|
/* nav popup ...
|
|
|
|
* should share code with the nav_window dialog since they are
|
|
|
|
* essentially the same.
|
|
|
|
*/
|
|
|
|
|
|
|
|
void
|
1999-10-16 21:07:15 +08:00
|
|
|
nav_popup_click_handler (GtkWidget *widget,
|
|
|
|
GdkEventButton *event,
|
|
|
|
gpointer data)
|
1999-09-02 06:39:44 +08:00
|
|
|
{
|
|
|
|
GdkEventButton *bevent;
|
|
|
|
GDisplay *gdisp = data;
|
|
|
|
NavWinData *iwp; /* dummy shorter version for the popups */
|
|
|
|
gint x, y;
|
|
|
|
gint x_org, y_org;
|
|
|
|
gint scr_w, scr_h;
|
|
|
|
|
|
|
|
bevent = (GdkEventButton *)event;
|
|
|
|
|
|
|
|
if(!gdisp->nav_popup)
|
|
|
|
{
|
|
|
|
/* popup a simplfied window with the nav box in it */
|
|
|
|
GtkWidget *frame;
|
|
|
|
GtkWidget *vbox;
|
|
|
|
|
|
|
|
iwp = create_dummy_iwd(gdisp,NAV_POPUP);
|
|
|
|
gdisp->nav_popup = gtk_window_new (GTK_WINDOW_POPUP);
|
|
|
|
gtk_widget_set_events (gdisp->nav_popup,
|
|
|
|
PREVIEW_MASK);
|
|
|
|
|
|
|
|
gtk_window_set_policy (GTK_WINDOW (gdisp->nav_popup),
|
|
|
|
FALSE, FALSE, TRUE);
|
|
|
|
frame = gtk_frame_new (NULL);
|
|
|
|
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
|
|
|
|
gtk_container_add (GTK_CONTAINER (gdisp->nav_popup), frame);
|
|
|
|
gtk_widget_show (frame);
|
|
|
|
|
|
|
|
vbox = create_preview_containers(iwp,gdisp->nav_popup);
|
|
|
|
gtk_widget_set_extension_events (iwp->preview, GDK_EXTENSION_EVENTS_ALL);
|
|
|
|
|
|
|
|
gtk_container_add (GTK_CONTAINER (frame), vbox);
|
|
|
|
gtk_object_set_data(GTK_OBJECT(gdisp->nav_popup),"navpop_prt",
|
|
|
|
(gpointer)iwp);
|
|
|
|
nav_window_disp_area(iwp,iwp->gdisp_ptr);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gtk_widget_hide (gdisp->nav_popup);
|
|
|
|
iwp = (NavWinData *)gtk_object_get_data(GTK_OBJECT(gdisp->nav_popup),"navpop_prt");
|
|
|
|
nav_window_disp_area(iwp,iwp->gdisp_ptr);
|
|
|
|
nav_window_update_preview(iwp);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* decide where to put the popup */
|
|
|
|
gdk_window_get_origin (widget->window, &x_org, &y_org);
|
|
|
|
scr_w = gdk_screen_width ();
|
|
|
|
scr_h = gdk_screen_height ();
|
|
|
|
x = x_org + bevent->x - iwp->dispx - ((iwp->dispwidth - BORDER_PEN_WIDTH+1) * 0.5) - 2;
|
|
|
|
y = y_org + bevent->y - iwp->dispy - ((iwp->dispheight - BORDER_PEN_WIDTH+1)* 0.5) - 2;
|
|
|
|
/* If we leave this in we need to warp the pointer so it still fits in
|
|
|
|
* in the square representing the viewable area.
|
|
|
|
* However warping is probably frowned upon.
|
|
|
|
*/
|
|
|
|
#if 0
|
|
|
|
x = (x < 0) ? 0 : x;
|
|
|
|
y = (y < 0) ? 0 : y;
|
|
|
|
x = (x + NAV_PREVIEW_WIDTH > scr_w) ? scr_w - NAV_PREVIEW_WIDTH : x;
|
|
|
|
y = (y + NAV_PREVIEW_HEIGHT > scr_h) ? scr_h - NAV_PREVIEW_HEIGHT : y;
|
|
|
|
#endif /* 0 */
|
|
|
|
|
|
|
|
gtk_widget_popup (gdisp->nav_popup, x, y);
|
|
|
|
gdk_flush();
|
|
|
|
|
|
|
|
/* fill in then set up handlers for mouse motion etc */
|
|
|
|
iwp->motion_offsetx = (iwp->dispwidth - BORDER_PEN_WIDTH+1) * 0.5;
|
|
|
|
iwp->motion_offsety = (iwp->dispheight - BORDER_PEN_WIDTH+1)* 0.5;
|
|
|
|
if(GTK_WIDGET_VISIBLE(iwp->preview))
|
|
|
|
nav_window_grab_pointer(iwp,iwp->preview);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
1999-10-16 21:07:15 +08:00
|
|
|
nav_popup_free (GtkWidget *nav_popup)
|
1999-09-02 06:39:44 +08:00
|
|
|
{
|
1999-10-16 21:07:15 +08:00
|
|
|
gtk_widget_destroy (nav_popup);
|
1999-09-02 06:39:44 +08:00
|
|
|
}
|
1999-09-05 06:27:20 +08:00
|
|
|
|
|
|
|
void
|
1999-10-16 21:07:15 +08:00
|
|
|
nav_window_preview_resized (InfoDialog *idialog)
|
1999-09-05 06:27:20 +08:00
|
|
|
{
|
|
|
|
NavWinData *iwd;
|
|
|
|
|
|
|
|
if (!idialog)
|
|
|
|
return;
|
|
|
|
|
|
|
|
iwd = (NavWinData *)idialog->user_data;
|
|
|
|
|
|
|
|
/* force regeneration of the widgets */
|
|
|
|
/* bit of a fiddle... could cause if the image really is 1x1
|
|
|
|
* but the preview would not really matter in that case.
|
|
|
|
*/
|
|
|
|
iwd->imagewidth = 1;
|
|
|
|
iwd->imageheight = 1;
|
|
|
|
|
|
|
|
iwd->nav_preview_width =
|
|
|
|
(nav_preview_size < 0 || nav_preview_size > 256)?NAV_PREVIEW_WIDTH:nav_preview_size;
|
|
|
|
iwd->nav_preview_height =
|
|
|
|
(nav_preview_size < 0 || nav_preview_size > 256)?NAV_PREVIEW_HEIGHT:nav_preview_size;
|
|
|
|
|
|
|
|
nav_window_update_window_marker(idialog);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nav_window_popup_preview_resized (GtkWidget **widget)
|
|
|
|
{
|
|
|
|
NavWinData *iwp; /* dummy shorter version for the popups */
|
|
|
|
|
1999-10-16 21:07:15 +08:00
|
|
|
iwp = (NavWinData *)gtk_object_get_data (GTK_OBJECT (*widget),"navpop_prt");
|
1999-09-05 06:27:20 +08:00
|
|
|
|
1999-10-16 21:07:15 +08:00
|
|
|
g_free (iwp);
|
1999-09-05 06:27:20 +08:00
|
|
|
|
1999-10-16 21:07:15 +08:00
|
|
|
gtk_widget_destroy (*widget);
|
1999-09-05 06:27:20 +08:00
|
|
|
|
|
|
|
*widget = NULL;
|
|
|
|
}
|