1
/* The GIMP -- an image manipulation program
2
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
4
* gimpnavigationeditor.c
5
* Copyright (C) 2001 Michael Natterer <mitch@gimp.org>
7
* partly based on app/nav_window
8
* Copyright (C) 1999 Andy Thomas <alt@gimp.org>
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* This program is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, write to the Free Software
22
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29
#include "libgimpwidgets/gimpwidgets.h"
31
#include "display-types.h"
33
#include "config/gimpdisplayconfig.h"
35
#include "core/gimp.h"
36
#include "core/gimpcontext.h"
37
#include "core/gimpimage.h"
39
#include "widgets/gimpdocked.h"
40
#include "widgets/gimphelp-ids.h"
41
#include "widgets/gimpmenufactory.h"
42
#include "widgets/gimpnavigationview.h"
43
#include "widgets/gimpuimanager.h"
44
#include "widgets/gimpviewrenderer.h"
46
#include "gimpdisplay.h"
47
#include "gimpdisplayshell.h"
48
#include "gimpdisplayshell-scale.h"
49
#include "gimpdisplayshell-scroll.h"
50
#include "gimpnavigationeditor.h"
52
#include "gimp-intl.h"
55
#define MAX_SCALE_BUF 20
58
static void gimp_navigation_editor_class_init (GimpNavigationEditorClass *klass);
59
static void gimp_navigation_editor_init (GimpNavigationEditor *editor);
61
static void gimp_navigation_editor_docked_iface_init (GimpDockedInterface *docked_iface);
62
static void gimp_navigation_editor_set_context (GimpDocked *docked,
63
GimpContext *context);
65
static void gimp_navigation_editor_destroy (GtkObject *object);
67
static GtkWidget * gimp_navigation_editor_new_private (GimpMenuFactory *menu_factory,
68
GimpDisplayShell *shell);
70
static void gimp_navigation_editor_set_shell (GimpNavigationEditor *view,
71
GimpDisplayShell *shell);
72
static gboolean gimp_navigation_editor_button_release (GtkWidget *widget,
73
GdkEventButton *bevent,
74
GimpDisplayShell *shell);
75
static void gimp_navigation_editor_marker_changed (GimpNavigationView *view,
78
GimpNavigationEditor *editor);
79
static void gimp_navigation_editor_zoom (GimpNavigationView *view,
80
GimpZoomType direction,
81
GimpNavigationEditor *editor);
82
static void gimp_navigation_editor_scroll (GimpNavigationView *view,
83
GdkScrollDirection direction,
84
GimpNavigationEditor *editor);
86
static void gimp_navigation_editor_zoom_adj_changed (GtkAdjustment *adj,
87
GimpNavigationEditor *editor);
89
static void gimp_navigation_editor_shell_scaled (GimpDisplayShell *shell,
90
GimpNavigationEditor *editor);
91
static void gimp_navigation_editor_shell_scrolled (GimpDisplayShell *shell,
92
GimpNavigationEditor *editor);
93
static void gimp_navigation_editor_shell_reconnect (GimpDisplayShell *shell,
94
GimpNavigationEditor *editor);
95
static void gimp_navigation_editor_update_marker (GimpNavigationEditor *editor);
98
static GimpEditorClass *parent_class = NULL;
102
gimp_navigation_editor_get_type (void)
104
static GType type = 0;
108
static const GTypeInfo editor_info =
110
sizeof (GimpNavigationEditorClass),
111
NULL, /* base_init */
112
NULL, /* base_finalize */
113
(GClassInitFunc) gimp_navigation_editor_class_init,
114
NULL, /* class_finalize */
115
NULL, /* class_navigation */
116
sizeof (GimpNavigationEditor),
118
(GInstanceInitFunc) gimp_navigation_editor_init,
120
static const GInterfaceInfo docked_iface_info =
122
(GInterfaceInitFunc) gimp_navigation_editor_docked_iface_init,
123
NULL, /* iface_finalize */
124
NULL /* iface_data */
127
type = g_type_register_static (GIMP_TYPE_EDITOR,
128
"GimpNavigationEditor",
131
g_type_add_interface_static (type, GIMP_TYPE_DOCKED,
139
gimp_navigation_editor_class_init (GimpNavigationEditorClass *klass)
141
GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (klass);
143
parent_class = g_type_class_peek_parent (klass);
145
gtk_object_class->destroy = gimp_navigation_editor_destroy;
149
gimp_navigation_editor_init (GimpNavigationEditor *editor)
153
editor->shell = NULL;
155
frame = gtk_frame_new (NULL);
156
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
157
gtk_box_pack_start (GTK_BOX (editor), frame, TRUE, TRUE, 0);
158
gtk_widget_show (frame);
160
editor->view = gimp_view_new_by_types (GIMP_TYPE_NAVIGATION_VIEW,
162
GIMP_VIEW_SIZE_MEDIUM, 0, TRUE);
163
gtk_container_add (GTK_CONTAINER (frame), editor->view);
164
gtk_widget_show (editor->view);
166
g_signal_connect (editor->view, "marker_changed",
167
G_CALLBACK (gimp_navigation_editor_marker_changed),
169
g_signal_connect (editor->view, "zoom",
170
G_CALLBACK (gimp_navigation_editor_zoom),
172
g_signal_connect (editor->view, "scroll",
173
G_CALLBACK (gimp_navigation_editor_scroll),
176
gtk_widget_set_sensitive (GTK_WIDGET (editor), FALSE);
180
gimp_navigation_editor_docked_iface_init (GimpDockedInterface *docked_iface)
182
docked_iface->set_context = gimp_navigation_editor_set_context;
186
gimp_navigation_editor_context_changed (GimpContext *context,
188
GimpNavigationEditor *editor)
190
GimpDisplayShell *shell = NULL;
193
shell = GIMP_DISPLAY_SHELL (gdisp->shell);
195
gimp_navigation_editor_set_shell (editor, shell);
199
gimp_navigation_editor_set_context (GimpDocked *docked,
200
GimpContext *context)
202
GimpNavigationEditor *editor = GIMP_NAVIGATION_EDITOR (docked);
203
GimpDisplay *gdisp = NULL;
204
GimpDisplayShell *shell = NULL;
208
g_signal_handlers_disconnect_by_func (editor->context,
209
gimp_navigation_editor_context_changed,
213
editor->context = context;
217
g_signal_connect (context, "display_changed",
218
G_CALLBACK (gimp_navigation_editor_context_changed),
221
gdisp = gimp_context_get_display (context);
225
shell = GIMP_DISPLAY_SHELL (gdisp->shell);
227
gimp_navigation_editor_set_shell (editor, shell);
231
gimp_navigation_editor_destroy (GtkObject *object)
233
GimpNavigationEditor *editor = GIMP_NAVIGATION_EDITOR (object);
236
gimp_navigation_editor_set_shell (editor, NULL);
238
GTK_OBJECT_CLASS (parent_class)->destroy (object);
242
/* public functions */
245
gimp_navigation_editor_new (GimpMenuFactory *menu_factory)
247
return gimp_navigation_editor_new_private (menu_factory, NULL);
251
gimp_navigation_editor_popup (GimpDisplayShell *shell,
256
GimpNavigationEditor *editor;
257
GimpNavigationView *view;
262
g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
263
g_return_if_fail (GTK_IS_WIDGET (widget));
265
if (! shell->nav_popup)
269
shell->nav_popup = gtk_window_new (GTK_WINDOW_POPUP);
271
frame = gtk_frame_new (NULL);
272
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
273
gtk_container_add (GTK_CONTAINER (shell->nav_popup), frame);
274
gtk_widget_show (frame);
277
GIMP_NAVIGATION_EDITOR (gimp_navigation_editor_new_private (NULL,
279
gtk_container_add (GTK_CONTAINER (frame), GTK_WIDGET (editor));
280
gtk_widget_show (GTK_WIDGET (editor));
282
g_signal_connect (editor->view, "button_release_event",
283
G_CALLBACK (gimp_navigation_editor_button_release),
288
editor = GIMP_NAVIGATION_EDITOR (GTK_BIN (GTK_BIN (shell->nav_popup)->child)->child);
291
screen = gtk_widget_get_screen (widget);
293
gtk_window_set_screen (GTK_WINDOW (shell->nav_popup), screen);
295
view = GIMP_NAVIGATION_VIEW (editor->view);
297
/* decide where to put the popup */
298
gdk_window_get_origin (widget->window, &x_org, &y_org);
300
#define BORDER_PEN_WIDTH 3
302
x = (x_org + click_x -
304
0.5 * (view->p_width - BORDER_PEN_WIDTH) -
305
2 * widget->style->xthickness);
307
y = (y_org + click_y -
309
0.5 * (view->p_height - BORDER_PEN_WIDTH) -
310
2 * widget->style->ythickness);
312
/* If the popup doesn't fit into the screen, we have a problem.
313
* We move the popup onscreen and risk that the pointer is not
314
* in the square representing the viewable area anymore. Moving
315
* the pointer will make the image scroll by a large amount,
316
* but then it works as usual. Probably better than a popup that
317
* is completely unusable in the lower right of the screen.
319
* Warping the pointer would be another solution ...
322
x = CLAMP (x, 0, (gdk_screen_get_width (screen) -
323
GIMP_VIEW (view)->renderer->width -
324
4 * widget->style->xthickness));
325
y = CLAMP (y, 0, (gdk_screen_get_height (screen) -
326
GIMP_VIEW (view)->renderer->height -
327
4 * widget->style->ythickness));
329
gtk_window_move (GTK_WINDOW (shell->nav_popup), x, y);
330
gtk_widget_show (shell->nav_popup);
334
/* fill in then grab pointer */
335
view->motion_offset_x = 0.5 * (view->p_width - BORDER_PEN_WIDTH);
336
view->motion_offset_y = 0.5 * (view->p_height - BORDER_PEN_WIDTH);
338
#undef BORDER_PEN_WIDTH
340
gimp_navigation_view_grab_pointer (view);
344
/* private functions */
347
gimp_navigation_editor_new_private (GimpMenuFactory *menu_factory,
348
GimpDisplayShell *shell)
350
GimpNavigationEditor *editor;
352
g_return_val_if_fail (menu_factory == NULL ||
353
GIMP_IS_MENU_FACTORY (menu_factory), NULL);
354
g_return_val_if_fail (shell == NULL || GIMP_IS_DISPLAY_SHELL (shell), NULL);
355
g_return_val_if_fail (menu_factory || shell, NULL);
359
GimpDisplayConfig *config;
362
editor = g_object_new (GIMP_TYPE_NAVIGATION_EDITOR, NULL);
364
config = GIMP_DISPLAY_CONFIG (shell->gdisp->gimage->gimp->config);
365
view = GIMP_VIEW (editor->view);
367
gimp_view_renderer_set_size (view->renderer,
368
config->nav_preview_size * 3,
369
view->renderer->border_width);
371
gimp_navigation_editor_set_shell (editor, shell);
377
editor = g_object_new (GIMP_TYPE_NAVIGATION_EDITOR,
378
"menu-factory", menu_factory,
379
"menu-identifier", "<NavigationEditor>",
382
gtk_widget_set_size_request (editor->view,
384
GIMP_VIEW_SIZE_HUGE);
385
gimp_view_set_expand (GIMP_VIEW (editor->view), TRUE);
387
/* the editor buttons */
389
editor->zoom_out_button =
390
gimp_editor_add_action_button (GIMP_EDITOR (editor), "view",
391
"view-zoom-out", NULL);
393
editor->zoom_in_button =
394
gimp_editor_add_action_button (GIMP_EDITOR (editor), "view",
395
"view-zoom-in", NULL);
397
editor->zoom_100_button =
398
gimp_editor_add_action_button (GIMP_EDITOR (editor), "view",
399
"view-zoom-1-1", NULL);
401
editor->zoom_fit_in_button =
402
gimp_editor_add_action_button (GIMP_EDITOR (editor), "view",
403
"view-zoom-fit-in", NULL);
405
editor->zoom_fit_to_button =
406
gimp_editor_add_action_button (GIMP_EDITOR (editor), "view",
407
"view-zoom-fit-to", NULL);
409
editor->shrink_wrap_button =
410
gimp_editor_add_action_button (GIMP_EDITOR (editor), "view",
411
"view-shrink-wrap", NULL);
415
editor->zoom_adjustment =
416
GTK_ADJUSTMENT (gtk_adjustment_new (0.0, -8.0, 8.0, 0.5, 1.0, 0.0));
418
g_signal_connect (editor->zoom_adjustment, "value_changed",
419
G_CALLBACK (gimp_navigation_editor_zoom_adj_changed),
422
hscale = gtk_hscale_new (GTK_ADJUSTMENT (editor->zoom_adjustment));
423
gtk_range_set_update_policy (GTK_RANGE (hscale), GTK_UPDATE_DELAYED);
424
gtk_scale_set_draw_value (GTK_SCALE (hscale), FALSE);
425
gtk_scale_set_digits (GTK_SCALE (hscale), 2);
426
gtk_box_pack_end (GTK_BOX (editor), hscale, FALSE, FALSE, 0);
427
gtk_widget_show (hscale);
431
editor->zoom_label = gtk_label_new ("100%");
432
gtk_box_pack_end (GTK_BOX (editor), editor->zoom_label, FALSE, FALSE, 0);
433
gtk_widget_show (editor->zoom_label);
437
GtkRequisition requisition;
439
gtk_widget_size_request (editor->zoom_label, &requisition);
440
gtk_widget_set_size_request (editor->zoom_label,
441
4 * requisition.width,
446
gimp_view_renderer_set_background (GIMP_VIEW (editor->view)->renderer,
449
return GTK_WIDGET (editor);
453
gimp_navigation_editor_set_shell (GimpNavigationEditor *editor,
454
GimpDisplayShell *shell)
456
g_return_if_fail (GIMP_IS_NAVIGATION_EDITOR (editor));
457
g_return_if_fail (! shell || GIMP_IS_DISPLAY_SHELL (shell));
459
if (shell == editor->shell)
464
g_signal_handlers_disconnect_by_func (editor->shell,
465
gimp_navigation_editor_shell_scaled,
467
g_signal_handlers_disconnect_by_func (editor->shell,
468
gimp_navigation_editor_shell_scrolled,
470
g_signal_handlers_disconnect_by_func (editor->shell,
471
gimp_navigation_editor_shell_reconnect,
476
gtk_widget_set_sensitive (GTK_WIDGET (editor), TRUE);
479
editor->shell = shell;
483
gimp_view_set_viewable (GIMP_VIEW (editor->view),
484
GIMP_VIEWABLE (shell->gdisp->gimage));
486
g_signal_connect (editor->shell, "scaled",
487
G_CALLBACK (gimp_navigation_editor_shell_scaled),
489
g_signal_connect (editor->shell, "scrolled",
490
G_CALLBACK (gimp_navigation_editor_shell_scrolled),
492
g_signal_connect (editor->shell, "reconnect",
493
G_CALLBACK (gimp_navigation_editor_shell_reconnect),
496
gimp_navigation_editor_shell_scaled (editor->shell, editor);
500
gimp_view_set_viewable (GIMP_VIEW (editor->view), NULL);
501
gtk_widget_set_sensitive (GTK_WIDGET (editor), FALSE);
504
if (GIMP_EDITOR (editor)->ui_manager)
505
gimp_ui_manager_update (GIMP_EDITOR (editor)->ui_manager,
506
GIMP_EDITOR (editor)->popup_data);
510
gimp_navigation_editor_button_release (GtkWidget *widget,
511
GdkEventButton *bevent,
512
GimpDisplayShell *shell)
514
if (bevent->button == 1)
516
gtk_widget_hide (shell->nav_popup);
523
gimp_navigation_editor_marker_changed (GimpNavigationView *view,
526
GimpNavigationEditor *editor)
535
xratio = SCALEFACTOR_X (editor->shell);
536
yratio = SCALEFACTOR_Y (editor->shell);
538
xoffset = RINT (x * xratio - editor->shell->offset_x);
539
yoffset = RINT (y * yratio - editor->shell->offset_y);
541
gimp_display_shell_scroll (editor->shell, xoffset, yoffset);
546
gimp_navigation_editor_zoom (GimpNavigationView *view,
547
GimpZoomType direction,
548
GimpNavigationEditor *editor)
550
g_return_if_fail (direction != GIMP_ZOOM_TO);
554
gimp_display_shell_scale (editor->shell, direction, 0.0);
559
gimp_navigation_editor_scroll (GimpNavigationView *view,
560
GdkScrollDirection direction,
561
GimpNavigationEditor *editor)
565
GtkAdjustment *adj = NULL;
570
case GDK_SCROLL_LEFT:
571
case GDK_SCROLL_RIGHT:
572
adj = editor->shell->hsbdata;
576
case GDK_SCROLL_DOWN:
577
adj = editor->shell->vsbdata;
581
g_assert (adj != NULL);
587
case GDK_SCROLL_LEFT:
589
value -= adj->page_increment / 2;
592
case GDK_SCROLL_RIGHT:
593
case GDK_SCROLL_DOWN:
594
value += adj->page_increment / 2;
598
value = CLAMP (value, adj->lower, adj->upper - adj->page_size);
600
gtk_adjustment_set_value (adj, value);
605
gimp_navigation_editor_zoom_adj_changed (GtkAdjustment *adj,
606
GimpNavigationEditor *editor)
608
gimp_display_shell_scale (editor->shell, GIMP_ZOOM_TO,
609
pow (2.0, adj->value));
613
gimp_navigation_editor_shell_scaled (GimpDisplayShell *shell,
614
GimpNavigationEditor *editor)
616
if (editor->zoom_label)
618
gchar scale_str[MAX_SCALE_BUF];
620
/* Update the zoom scale string */
621
g_snprintf (scale_str, sizeof (scale_str),
622
shell->scale >= 0.15 ? "%.0f%%" : "%.2f%%",
623
editor->shell->scale * 100);
625
gtk_label_set_text (GTK_LABEL (editor->zoom_label), scale_str);
628
if (editor->zoom_adjustment)
632
val = log (CLAMP (editor->shell->scale, 1.0 / 256, 256.0) ) / G_LN2;
634
g_signal_handlers_block_by_func (editor->zoom_adjustment,
635
gimp_navigation_editor_zoom_adj_changed,
638
gtk_adjustment_set_value (editor->zoom_adjustment, val);
640
g_signal_handlers_unblock_by_func (editor->zoom_adjustment,
641
gimp_navigation_editor_zoom_adj_changed,
645
gimp_navigation_editor_update_marker (editor);
647
if (GIMP_EDITOR (editor)->ui_manager)
648
gimp_ui_manager_update (GIMP_EDITOR (editor)->ui_manager,
649
GIMP_EDITOR (editor)->popup_data);
653
gimp_navigation_editor_shell_scrolled (GimpDisplayShell *shell,
654
GimpNavigationEditor *editor)
656
gimp_navigation_editor_update_marker (editor);
658
if (GIMP_EDITOR (editor)->ui_manager)
659
gimp_ui_manager_update (GIMP_EDITOR (editor)->ui_manager,
660
GIMP_EDITOR (editor)->popup_data);
664
gimp_navigation_editor_shell_reconnect (GimpDisplayShell *shell,
665
GimpNavigationEditor *editor)
667
gimp_view_set_viewable (GIMP_VIEW (editor->view),
668
GIMP_VIEWABLE (shell->gdisp->gimage));
670
if (GIMP_EDITOR (editor)->ui_manager)
671
gimp_ui_manager_update (GIMP_EDITOR (editor)->ui_manager,
672
GIMP_EDITOR (editor)->popup_data);
676
gimp_navigation_editor_update_marker (GimpNavigationEditor *editor)
678
GimpViewRenderer *renderer;
682
renderer = GIMP_VIEW (editor->view)->renderer;
684
xratio = SCALEFACTOR_X (editor->shell);
685
yratio = SCALEFACTOR_Y (editor->shell);
687
if (renderer->dot_for_dot != editor->shell->dot_for_dot)
688
gimp_view_renderer_set_dot_for_dot (renderer,
689
editor->shell->dot_for_dot);
691
gimp_navigation_view_set_marker (GIMP_NAVIGATION_VIEW (editor->view),
692
editor->shell->offset_x / xratio,
693
editor->shell->offset_y / yratio,
694
editor->shell->disp_width / xratio,
695
editor->shell->disp_height / yratio);