gimp/plug-ins/imagemap/imap_preview.c

390 lines
12 KiB
C
Raw Normal View History

1999-09-07 00:03:20 +00:00
/*
* This is a plug-in for GIMP.
1999-09-07 00:03:20 +00:00
*
* Generates clickable image maps.
*
* Copyright (C) 1998-2005 Maurits Rijk m.rijk@chello.nl
1999-09-07 00:03:20 +00:00
*
* This program is free software: you can redistribute it and/or modify
1999-09-07 00:03:20 +00:00
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
1999-09-07 00:03:20 +00:00
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
1999-09-07 00:03:20 +00:00
*
*/
app/gimpprogress.c app/nav_window.c app/ops_buttons.c app/undo_history.c 2001-12-29 Michael Natterer <mitch@gimp.org> * app/gimpprogress.c * app/nav_window.c * app/ops_buttons.c * app/undo_history.c * app/display/gimpdisplayshell.c * app/gui/about-dialog.c * app/gui/brush-editor.c * app/gui/channels-commands.c * app/gui/color-area.c * app/gui/color-notebook.c * app/gui/color-select.c * app/gui/colormap-dialog.c * app/gui/convert-dialog.c * app/gui/device-status-dialog.c * app/gui/file-new-dialog.c * app/gui/file-open-dialog.c * app/gui/file-save-dialog.c * app/gui/gradient-editor.c * app/gui/info-dialog.c * app/gui/layers-commands.c * app/gui/module-browser.c * app/gui/offset-dialog.c * app/gui/palette-editor.c * app/gui/palettes-commands.c * app/gui/paths-dialog.c * app/gui/qmask-commands.c * app/gui/resize-dialog.c * app/gui/resolution-calibrate-dialog.c * app/gui/splash.c * app/gui/tips-dialog.c * app/gui/toolbox.c * app/gui/user-install-dialog.c * app/tools/gimpbrightnesscontrasttool.c * app/tools/gimpbycolorselecttool.c * app/tools/gimpcolorbalancetool.c * app/tools/gimpcolorpickertool.c * app/tools/gimpcroptool.c * app/tools/gimpcurvestool.c * app/tools/gimphuesaturationtool.c * app/tools/gimpinktool.c * app/tools/gimplevelstool.c * app/tools/gimpposterizetool.c * app/tools/gimprotatetool.c * app/tools/gimpthresholdtool.c * app/tools/paint_options.c * app/tools/selection_options.c * app/widgets/gimpchannellistview.c * app/widgets/gimpcolorpanel.c * app/widgets/gimpcomponentlistitem.c * app/widgets/gimpconstrainedhwrapbox.c * app/widgets/gimpcontainergridview.c * app/widgets/gimpcontainerlistview.c * app/widgets/gimpcontainermenuimpl.c * app/widgets/gimpdialogfactory.c * app/widgets/gimpdnd.c * app/widgets/gimpdock.c * app/widgets/gimpdockbook.c * app/widgets/gimpdrawablelistitem.c * app/widgets/gimpdrawablelistview.c * app/widgets/gimpfontselection-dialog.c * app/widgets/gimphistogramview.c * app/widgets/gimpitemfactory.c * app/widgets/gimplayerlistitem.c * app/widgets/gimplistitem.[ch] * app/widgets/gimpmenuitem.c * app/widgets/gimppreview.[ch] * app/widgets/gtkhwrapbox.c * app/widgets/gtkvwrapbox.c * app/widgets/gtkwrapbox.c * libgimp/gimpbrushmenu.c * libgimp/gimpexport.c * libgimp/gimpgradientmenu.c * libgimp/gimpmenu.c * libgimp/gimppatternmenu.c * libgimpwidgets/gimpbutton.c * libgimpwidgets/gimpchainbutton.[ch] * libgimpwidgets/gimpcolorarea.h * libgimpwidgets/gimpcolorbutton.c * libgimpwidgets/gimpfileselection.c * libgimpwidgets/gimphelpui.c * libgimpwidgets/gimpoffsetarea.c * libgimpwidgets/gimppatheditor.c * libgimpwidgets/gimppixmap.h * libgimpwidgets/gimpquerybox.c * libgimpwidgets/gimpstock.[ch] * libgimpwidgets/gimpwidgets.h * plug-ins/FractalExplorer/Dialogs.c * plug-ins/FractalExplorer/Events.c * plug-ins/FractalExplorer/FractalExplorer.c * plug-ins/Lighting/lighting_ui.c * plug-ins/MapObject/mapobject_ui.c * plug-ins/bmp/bmpwrite.c * plug-ins/dbbrowser/dbbrowser_utils.c * plug-ins/fits/fits.c * plug-ins/flame/flame.c * plug-ins/fp/fp_gtk.c * plug-ins/fp/fp_misc.c * plug-ins/gfig/gfig.c * plug-ins/gflare/gflare.c * plug-ins/gfli/gfli.c * plug-ins/gimpressionist/*.c * plug-ins/imagemap/*.[ch] * plug-ins/maze/maze_face.c * plug-ins/mosaic/mosaic.c * plug-ins/pagecurl/pagecurl.c * plug-ins/print/print_gimp.h * plug-ins/rcm/rcm_callback.c * plug-ins/rcm/rcm_dialog.c * plug-ins/rcm/rcm_misc.c * plug-ins/script-fu/script-fu-console.c * plug-ins/script-fu/script-fu-scripts.c * plug-ins/script-fu/script-fu-server.c * plug-ins/sel2path/sel2path.c * plug-ins/sel2path/sel2path_adv_dialog.c * plug-ins/sgi/sgi.c * plug-ins/webbrowser/webbrowser.c * plug-ins/xjt/xjt.c * plug-ins/common/[A-n]*.c: compile with GTK_DISABLE_DEPRECATED defined. Not everything is fully ported yet, had to #undef GTK_DISABLE_DEPRECATED in many places and added #warnings when doing so. * pixmaps/Makefile.am * pixmaps/chain.xpm: removed. * themes/Default/Makefile.am * themes/Default/images/Makefile.am * themes/Default/images/stock-button-hchain-broken.png * themes/Default/images/stock-button-hchain.png * themes/Default/images/stock-button-vchain-broken.png * themes/Default/images/stock-button-vchain.png: new stock icons.
2001-12-29 13:26:29 +00:00
#include "config.h"
#include <libgimp/gimp.h>
#include <libgimp/gimpui.h>
#include "imap_commands.h"
1999-09-07 00:03:20 +00:00
#include "imap_grid.h"
#include "imap_main.h"
#include "imap_menu.h"
1999-09-07 00:03:20 +00:00
#include "imap_preview.h"
#define PREVIEW_MASK (GDK_EXPOSURE_MASK | \
2011-02-21 11:51:47 +01:00
GDK_POINTER_MOTION_MASK | \
GDK_BUTTON_PRESS_MASK | \
2011-02-21 11:51:47 +01:00
GDK_BUTTON_RELEASE_MASK | \
GDK_BUTTON_MOTION_MASK | \
GDK_KEY_PRESS_MASK | \
GDK_KEY_RELEASE_MASK | \
GDK_ENTER_NOTIFY_MASK | \
GDK_LEAVE_NOTIFY_MASK)
1999-09-07 00:03:20 +00:00
#define PREVIEW_SIZE 400
/*======================================================================
2011-02-21 11:51:47 +01:00
Preview Rendering Util routine
1999-09-07 00:03:20 +00:00
=======================================================================*/
#define CHECKWIDTH 4
#define LIGHTCHECK 192
#define DARKCHECK 128
#ifndef OPAQUE
2011-02-21 11:51:47 +01:00
#define OPAQUE 255
1999-09-07 00:03:20 +00:00
#endif
2011-02-21 15:45:26 +01:00
static Object_t *_tmp_obj;
1999-09-07 00:03:20 +00:00
static Preview_t*
preview_user_data(GtkWidget *preview)
{
return (Preview_t*) g_object_get_data (G_OBJECT (preview), "preview");
1999-09-07 00:03:20 +00:00
}
gint
1999-09-07 00:03:20 +00:00
preview_get_width(GtkWidget *preview)
{
return preview_user_data(preview)->width;
}
gint
1999-09-07 00:03:20 +00:00
preview_get_height(GtkWidget *preview)
{
return preview_user_data(preview)->height;
}
static void
render_background(Preview_t *preview_base)
{
GtkWidget *preview = preview_base->preview;
gimp_preview_area_fill (GIMP_PREVIEW_AREA (preview),
0, 0, G_MAXINT, G_MAXINT,
255, 255, 255);
}
1999-09-07 00:03:20 +00:00
static void
2019-07-19 17:20:58 +02:00
render_rgb_image (Preview_t *preview_base,
GimpDrawable *drawable)
1999-09-07 00:03:20 +00:00
{
2019-07-19 17:20:58 +02:00
GeglBuffer *buffer;
guchar *dest_buffer;
gint dwidth, dheight, pwidth, pheight;
GtkWidget *preview = preview_base->preview;
1999-09-07 00:03:20 +00:00
dwidth = gimp_drawable_width (drawable);
dheight = gimp_drawable_height (drawable);
2019-07-19 17:20:58 +02:00
pwidth = preview_base->widget_width;
pheight = preview_base->widget_height;
1999-09-07 00:03:20 +00:00
2019-07-19 17:20:58 +02:00
dest_buffer = g_new (guchar, pwidth * pheight * 4);
buffer = gimp_drawable_get_buffer (drawable);
2019-07-19 17:20:58 +02:00
gegl_buffer_get (buffer, GEGL_RECTANGLE (0, 0, pwidth, pheight),
MIN ((gdouble) pwidth / (gdouble) dwidth,
(gdouble) pheight / (gdouble) dheight),
babl_format ("R'G'B'A u8"), dest_buffer,
GEGL_AUTO_ROWSTRIDE, GEGL_ABYSS_NONE);
g_object_unref (buffer);
gimp_preview_area_draw (GIMP_PREVIEW_AREA (preview),
0, 0, pwidth, pheight,
2019-07-19 17:20:58 +02:00
GIMP_RGBA_IMAGE,
dest_buffer,
2019-07-19 17:20:58 +02:00
pwidth * 4);
1999-09-07 00:03:20 +00:00
2019-07-19 17:20:58 +02:00
g_free (dest_buffer);
1999-09-07 00:03:20 +00:00
}
static void
2019-07-19 17:20:58 +02:00
render_preview (Preview_t *preview_base,
GimpDrawable *drawable)
1999-09-07 00:03:20 +00:00
{
2019-07-19 17:20:58 +02:00
render_background (preview_base);
render_rgb_image (preview_base, drawable);
1999-09-07 00:03:20 +00:00
}
static gboolean
arrow_cb(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
if (event->button == 1)
do_main_popup_menu(event);
return TRUE;
}
static gboolean
preview_draw (GtkWidget *widget,
cairo_t *cr)
1999-09-07 00:03:20 +00:00
{
gint width = preview_get_width (widget);
gint height = preview_get_height (widget);
2011-02-21 15:45:26 +01:00
cairo_set_line_width (cr, 1.);
draw_grid (cr, width, height);
draw_shapes (cr);
2011-02-21 15:45:26 +01:00
if (_tmp_obj)
{
2011-02-21 15:45:26 +01:00
/* this is a bit of a hack */
gdouble dash = 4.;
_tmp_obj->selected |= 4;
cairo_set_source_rgb (cr, 1., 0., 1.);
cairo_set_dash (cr, &dash, 1, dash);
object_draw (_tmp_obj, cr);
}
return FALSE;
1999-09-07 00:03:20 +00:00
}
void
2011-02-21 15:45:26 +01:00
preview_set_tmp_obj (Object_t *obj)
1999-09-07 00:03:20 +00:00
{
2011-02-21 15:45:26 +01:00
_tmp_obj = obj;
1999-09-07 00:03:20 +00:00
}
void
2011-02-21 15:45:26 +01:00
preview_unset_tmp_obj (Object_t *obj)
1999-09-07 00:03:20 +00:00
{
2011-02-21 15:45:26 +01:00
if (_tmp_obj == obj) _tmp_obj = NULL;
1999-09-07 00:03:20 +00:00
}
void
preview_zoom(Preview_t *preview, gint zoom_factor)
{
preview->widget_width = preview->width * zoom_factor;
preview->widget_height = preview->height * zoom_factor;
gtk_widget_set_size_request (preview->preview, preview->widget_width,
preview->widget_height);
1999-09-07 00:03:20 +00:00
gtk_widget_queue_resize(preview->window);
render_preview(preview, preview->drawable);
2011-02-21 15:45:26 +01:00
preview_redraw();
1999-09-07 00:03:20 +00:00
}
1999-10-24 20:57:17 +00:00
GdkCursorType
1999-09-07 00:03:20 +00:00
preview_set_cursor(Preview_t *preview, GdkCursorType cursor_type)
{
GdkCursorType prev_cursor = preview->cursor;
GdkDisplay *display = gtk_widget_get_display (preview->window);
GdkCursor *cursor = gdk_cursor_new_for_display (display,
cursor_type);
gdk_window_set_cursor(gtk_widget_get_window (preview->window), cursor);
g_object_unref (cursor);
1999-10-24 20:57:17 +00:00
preview->cursor = cursor_type;
1999-10-24 20:57:17 +00:00
return prev_cursor;
}
static const GtkTargetEntry target_table[] =
{
{"STRING", 0, 1 },
1999-10-24 20:57:17 +00:00
{"text/plain", 0, 2 }
};
static void
handle_drop(GtkWidget *widget, GdkDragContext *context, gint x, gint y,
2011-02-21 11:51:47 +01:00
GtkSelectionData *data, guint info, guint time)
1999-10-24 20:57:17 +00:00
{
gboolean success = FALSE;
if (gtk_selection_data_get_length (data) >= 0 &&
gtk_selection_data_get_format (data) == 8)
{
1999-10-24 20:57:17 +00:00
ObjectList_t *list = get_shapes();
Object_t *obj;
x = get_real_coord(x);
y = get_real_coord(y);
obj = object_list_find(list, x, y);
if (obj && !obj->locked)
{
command_list_add(edit_object_command_new(obj));
object_set_url(obj, (const gchar *) gtk_selection_data_get_data (data));
object_emit_update_signal(obj);
success = TRUE;
}
}
gtk_drag_finish(context, success, FALSE, time);
1999-09-07 00:03:20 +00:00
}
static void
preview_size_allocate (GtkWidget *widget,
GtkAllocation *allocation,
gpointer preview_void)
{
Preview_t *preview = preview_void;
render_preview (preview, preview->drawable);
}
static void
scroll_adj_changed (GtkAdjustment *adj,
GimpRuler *ruler)
{
gimp_ruler_set_range (ruler,
gtk_adjustment_get_value (adj),
gtk_adjustment_get_value (adj) +
gtk_adjustment_get_page_size (adj),
gtk_adjustment_get_upper (adj));
}
Preview_t *
make_preview (GimpDrawable *drawable)
1999-09-07 00:03:20 +00:00
{
Preview_t *data = g_new(Preview_t, 1);
GtkAdjustment *hadj;
GtkAdjustment *vadj;
1999-09-07 00:03:20 +00:00
GtkWidget *preview;
GtkWidget *window;
GtkWidget *viewport;
GtkWidget *button, *arrow;
1999-09-07 00:03:20 +00:00
GtkWidget *ruler;
GtkWidget *grid;
GtkWidget *scrollbar;
1999-09-07 00:03:20 +00:00
gint width, height;
data->drawable = drawable;
data->preview = preview = gimp_preview_area_new ();
1999-09-07 00:03:20 +00:00
g_object_set_data (G_OBJECT (preview), "preview", data);
gtk_widget_set_events (GTK_WIDGET (preview), PREVIEW_MASK);
g_signal_connect_after (preview, "draw",
G_CALLBACK (preview_draw),
data);
g_signal_connect (preview, "size-allocate",
G_CALLBACK (preview_size_allocate),
data);
1999-09-07 00:03:20 +00:00
1999-10-24 20:57:17 +00:00
/* Handle drop of links in preview widget */
gtk_drag_dest_set (preview, GTK_DEST_DEFAULT_ALL, target_table,
2, GDK_ACTION_COPY);
g_signal_connect (preview, "drag-data-received",
G_CALLBACK (handle_drop),
NULL);
1999-10-24 20:57:17 +00:00
data->widget_width = data->width = gimp_drawable_width (drawable);
data->widget_height = data->height = gimp_drawable_height (drawable);
gtk_widget_set_size_request (preview, data->widget_width,
data->widget_height);
1999-09-07 00:03:20 +00:00
/* The main grid */
data->window = grid = gtk_grid_new ();
gtk_grid_set_row_spacing (GTK_GRID (grid), 1);
gtk_grid_set_column_spacing (GTK_GRID (grid), 1);
/* Create button with arrow */
button = gtk_button_new ();
gtk_widget_set_can_focus (button, FALSE);
gtk_grid_attach (GTK_GRID (grid), button, 0, 0, 1, 1);
// GTK_FILL, GTK_FILL, 0, 0);
gtk_widget_set_events (button,
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
gtk_widget_show (button);
g_signal_connect (button, "button-press-event",
G_CALLBACK (arrow_cb),
NULL);
arrow = gtk_image_new_from_icon_name (GIMP_ICON_GO_NEXT,
GTK_ICON_SIZE_BUTTON);
gtk_container_add (GTK_CONTAINER (button), arrow);
gtk_widget_show (arrow);
1999-09-07 00:03:20 +00:00
/* Create horizontal ruler */
data->hruler = ruler = gimp_ruler_new (GTK_ORIENTATION_HORIZONTAL);
g_signal_connect_swapped (preview, "motion-notify-event",
G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
ruler);
gtk_widget_set_hexpand (ruler, TRUE);
gtk_grid_attach (GTK_GRID (grid), ruler, 1, 0, 1, 1);
gtk_widget_show (ruler);
1999-09-07 00:03:20 +00:00
/* Create vertical ruler */
data->vruler = ruler = gimp_ruler_new (GTK_ORIENTATION_VERTICAL);
g_signal_connect_swapped (preview, "motion-notify-event",
G_CALLBACK (GTK_WIDGET_GET_CLASS (ruler)->motion_notify_event),
2011-02-21 11:51:47 +01:00
ruler);
gtk_widget_set_vexpand (ruler, TRUE);
gtk_grid_attach (GTK_GRID (grid), ruler, 0, 1, 1, 1);
gtk_widget_show (ruler);
1999-09-07 00:03:20 +00:00
window = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (window),
GTK_POLICY_NEVER, GTK_POLICY_NEVER);
width = (data->width > 600) ? 600 : data->width;
height = (data->height > 400) ? 400 : data->height;
gtk_widget_set_size_request (window, width, height);
gtk_grid_attach (GTK_GRID (grid), window, 1, 1, 1, 1);
gtk_widget_show (window);
viewport = gtk_viewport_new (NULL, NULL);
gtk_container_add (GTK_CONTAINER (window), viewport);
gtk_widget_show (viewport);
hadj = gtk_scrolled_window_get_hadjustment (GTK_SCROLLED_WINDOW (window));
g_signal_connect (hadj, "changed",
G_CALLBACK (scroll_adj_changed),
data->hruler);
g_signal_connect (hadj, "value-changed",
G_CALLBACK (scroll_adj_changed),
data->hruler);
vadj = gtk_scrolled_window_get_vadjustment (GTK_SCROLLED_WINDOW (window));
g_signal_connect (vadj, "changed",
G_CALLBACK (scroll_adj_changed),
data->vruler);
g_signal_connect (vadj, "value-changed",
G_CALLBACK (scroll_adj_changed),
data->vruler);
gtk_container_add (GTK_CONTAINER (viewport), preview);
scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_HORIZONTAL, hadj);
gtk_grid_attach (GTK_GRID (grid), scrollbar, 1, 2, 1, 1);
// GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
gtk_widget_show (scrollbar);
scrollbar = gtk_scrollbar_new (GTK_ORIENTATION_VERTICAL, vadj);
gtk_grid_attach (GTK_GRID (grid), scrollbar, 2, 1, 1, 1);
// GTK_FILL | GTK_SHRINK, GTK_FILL | GTK_SHRINK, 0, 0);
gtk_widget_show (scrollbar);
gtk_widget_show (preview);
render_preview (data, drawable);
1999-09-07 00:03:20 +00:00
gtk_widget_show (grid);
1999-09-07 00:03:20 +00:00
return data;
}