1
/* The GIMP -- an image manipulation program
1
/* GIMP - The GNU Image Manipulation Program
2
2
* Copyright (C) 1995 Spencer Kimball and Peter Mattis
5
* Copyright (C) 2001 Michael Natterer <mitch@gimp.org>
5
* Copyright (C) 2001-2006 Michael Natterer <mitch@gimp.org>
7
7
* This program is free software; you can redistribute it and/or modify
8
8
* it under the terms of the GNU General Public License as published by
60
static void gimp_view_class_init (GimpViewClass *klass);
61
static void gimp_view_init (GimpView *view);
63
56
static void gimp_view_destroy (GtkObject *object);
64
57
static void gimp_view_realize (GtkWidget *widget);
65
58
static void gimp_view_unrealize (GtkWidget *widget);
80
73
static gboolean gimp_view_leave_notify_event (GtkWidget *widget,
81
74
GdkEventCrossing *event);
76
static void gimp_view_real_set_viewable (GimpView *view,
78
GimpViewable *viewable);
83
80
static void gimp_view_update_callback (GimpViewRenderer *renderer,
86
83
static GimpViewable * gimp_view_drag_viewable (GtkWidget *widget,
84
GimpContext **context,
86
static GdkPixbuf * gimp_view_drag_pixbuf (GtkWidget *widget,
90
G_DEFINE_TYPE (GimpView, gimp_view, GTK_TYPE_WIDGET)
92
#define parent_class gimp_view_parent_class
91
94
static guint view_signals[LAST_SIGNAL] = { 0 };
93
static GtkWidgetClass *parent_class = NULL;
97
gimp_view_get_type (void)
99
static GType view_type = 0;
103
static const GTypeInfo view_info =
105
sizeof (GimpViewClass),
106
NULL, /* base_init */
107
NULL, /* base_finalize */
108
(GClassInitFunc) gimp_view_class_init,
109
NULL, /* class_finalize */
110
NULL, /* class_data */
113
(GInstanceInitFunc) gimp_view_init,
116
view_type = g_type_register_static (GTK_TYPE_WIDGET,
125
98
gimp_view_class_init (GimpViewClass *klass)
127
100
GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
128
101
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
130
parent_class = g_type_class_peek_parent (klass);
103
view_signals[SET_VIEWABLE] =
104
g_signal_new ("set-viewable",
105
G_TYPE_FROM_CLASS (klass),
107
G_STRUCT_OFFSET (GimpViewClass, set_viewable),
109
gimp_marshal_VOID__OBJECT_OBJECT,
111
GIMP_TYPE_VIEWABLE, GIMP_TYPE_VIEWABLE);
132
113
view_signals[CLICKED] =
133
114
g_signal_new ("clicked",
140
121
GDK_TYPE_MODIFIER_TYPE);
142
123
view_signals[DOUBLE_CLICKED] =
143
g_signal_new ("double_clicked",
124
g_signal_new ("double-clicked",
144
125
G_TYPE_FROM_CLASS (klass),
145
126
G_SIGNAL_RUN_FIRST,
146
127
G_STRUCT_OFFSET (GimpViewClass, double_clicked),
220
210
GTK_WIDGET_CLASS (parent_class)->realize (widget);
222
212
attributes.window_type = GDK_WINDOW_CHILD;
223
attributes.x = widget->allocation.x;
224
attributes.y = widget->allocation.y;
225
attributes.width = widget->allocation.width;
226
attributes.height = widget->allocation.height;
228
attributes.wclass = GDK_INPUT_ONLY;
229
attributes.event_mask = gtk_widget_get_events (widget);
230
attributes.event_mask |= VIEW_EVENT_MASK;
213
attributes.x = widget->allocation.x;
214
attributes.y = widget->allocation.y;
215
attributes.width = widget->allocation.width;
216
attributes.height = widget->allocation.height;
217
attributes.wclass = GDK_INPUT_ONLY;
218
attributes.event_mask = gtk_widget_get_events (widget);
232
220
attributes_mask = GDK_WA_X | GDK_WA_Y;
396
387
gimp_view_expose_event (GtkWidget *widget,
397
GdkEventExpose *event)
388
GdkEventExpose *event)
399
if (! GTK_WIDGET_DRAWABLE (widget))
402
gimp_view_renderer_draw (GIMP_VIEW (widget)->renderer,
403
widget->window, widget,
390
if (GTK_WIDGET_DRAWABLE (widget))
392
gimp_view_renderer_draw (GIMP_VIEW (widget)->renderer,
393
widget->window, widget,
495
488
if (bevent->button == 1)
497
490
gtk_grab_remove (widget);
499
491
view->has_grab = FALSE;
501
493
if (view->clickable && view->in_button)
503
g_signal_emit (widget, view_signals[CLICKED], 0,
495
g_signal_emit (widget, view_signals[CLICKED], 0, view->press_state);
539
gimp_view_real_set_viewable (GimpView *view,
541
GimpViewable *viewable)
543
GType viewable_type = G_TYPE_NONE;
545
if (viewable == view->viewable)
550
viewable_type = G_TYPE_FROM_INSTANCE (viewable);
552
g_return_if_fail (g_type_is_a (viewable_type,
553
view->renderer->viewable_type));
558
g_object_remove_weak_pointer (G_OBJECT (view->viewable),
559
(gpointer) &view->viewable);
561
if (! viewable && ! view->renderer->is_popup)
563
if (gimp_dnd_viewable_source_remove (GTK_WIDGET (view),
564
G_TYPE_FROM_INSTANCE (view->viewable)))
566
if (gimp_viewable_get_size (view->viewable, NULL, NULL))
567
gimp_dnd_pixbuf_source_remove (GTK_WIDGET (view));
569
gtk_drag_source_unset (GTK_WIDGET (view));
573
else if (viewable && ! view->renderer->is_popup)
575
if (gimp_dnd_drag_source_set_by_type (GTK_WIDGET (view),
576
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
580
gimp_dnd_viewable_source_add (GTK_WIDGET (view),
582
gimp_view_drag_viewable,
585
if (gimp_viewable_get_size (viewable, NULL, NULL))
586
gimp_dnd_pixbuf_source_add (GTK_WIDGET (view),
587
gimp_view_drag_pixbuf,
592
gimp_view_renderer_set_viewable (view->renderer, viewable);
593
view->viewable = viewable;
597
g_object_add_weak_pointer (G_OBJECT (view->viewable),
598
(gpointer) &view->viewable);
548
602
/* public functions */
551
gimp_view_new (GimpViewable *viewable,
605
gimp_view_new (GimpContext *context,
606
GimpViewable *viewable,
553
608
gint border_width,
554
609
gboolean is_popup)
613
g_return_val_if_fail (context == NULL || GIMP_IS_CONTEXT (context), NULL);
558
614
g_return_val_if_fail (GIMP_IS_VIEWABLE (viewable), NULL);
560
view = gimp_view_new_by_types (GIMP_TYPE_VIEW,
616
view = gimp_view_new_by_types (context,
561
618
G_TYPE_FROM_INSTANCE (viewable),
562
619
size, border_width, is_popup);
641
g_return_val_if_fail (context == NULL || GIMP_IS_CONTEXT (context), NULL);
583
642
g_return_val_if_fail (GIMP_IS_VIEWABLE (viewable), NULL);
585
view = gimp_view_new_full_by_types (GIMP_TYPE_VIEW,
644
view = gimp_view_new_full_by_types (context,
586
646
G_TYPE_FROM_INSTANCE (viewable),
587
647
width, height, border_width,
588
648
is_popup, clickable, show_popup);
599
gimp_view_new_by_types (GType view_type,
659
gimp_view_new_by_types (GimpContext *context,
605
666
GimpViewRenderer *renderer;
669
g_return_val_if_fail (context == NULL || GIMP_IS_CONTEXT (context), NULL);
608
670
g_return_val_if_fail (g_type_is_a (view_type, GIMP_TYPE_VIEW), NULL);
609
671
g_return_val_if_fail (g_type_is_a (viewable_type, GIMP_TYPE_VIEWABLE), NULL);
610
672
g_return_val_if_fail (size > 0 &&
612
674
g_return_val_if_fail (border_width >= 0 &&
613
675
border_width <= GIMP_VIEW_MAX_BORDER_WIDTH, NULL);
615
renderer = gimp_view_renderer_new (viewable_type, size,
677
renderer = gimp_view_renderer_new (context, viewable_type, size,
616
678
border_width, is_popup);
618
680
g_return_val_if_fail (renderer != NULL, NULL);
632
gimp_view_new_full_by_types (GType view_type,
694
gimp_view_new_full_by_types (GimpContext *context,
641
704
GimpViewRenderer *renderer;
707
g_return_val_if_fail (context == NULL || GIMP_IS_CONTEXT (context), NULL);
644
708
g_return_val_if_fail (g_type_is_a (view_type, GIMP_TYPE_VIEW), NULL);
645
709
g_return_val_if_fail (g_type_is_a (viewable_type, GIMP_TYPE_VIEWABLE), NULL);
646
710
g_return_val_if_fail (width > 0 &&
650
714
g_return_val_if_fail (border_width >= 0 &&
651
715
border_width <= GIMP_VIEW_MAX_BORDER_WIDTH, NULL);
653
renderer = gimp_view_renderer_new_full (viewable_type, width, height,
654
border_width, is_popup);
717
renderer = gimp_view_renderer_new_full (context, viewable_type,
718
width, height, border_width,
656
721
g_return_val_if_fail (renderer != NULL, NULL);
668
733
return GTK_WIDGET (view);
737
gimp_view_get_viewable (GimpView *view)
739
g_return_val_if_fail (GIMP_IS_VIEW (view), NULL);
741
return view->viewable;
672
745
gimp_view_set_viewable (GimpView *view,
673
746
GimpViewable *viewable)
675
GType viewable_type = G_TYPE_NONE;
677
748
g_return_if_fail (GIMP_IS_VIEW (view));
678
749
g_return_if_fail (viewable == NULL || GIMP_IS_VIEWABLE (viewable));
680
751
if (viewable == view->viewable)
685
viewable_type = G_TYPE_FROM_INSTANCE (viewable);
687
g_return_if_fail (g_type_is_a (viewable_type,
688
view->renderer->viewable_type));
693
g_object_remove_weak_pointer (G_OBJECT (view->viewable),
694
(gpointer *) &view->viewable);
696
if (! viewable && ! view->renderer->is_popup)
698
if (gimp_dnd_viewable_source_remove (GTK_WIDGET (view),
699
G_TYPE_FROM_INSTANCE (view->viewable)))
701
gtk_drag_source_unset (GTK_WIDGET (view));
705
else if (viewable && ! view->renderer->is_popup)
707
if (gimp_dnd_drag_source_set_by_type (GTK_WIDGET (view),
708
GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
712
gimp_dnd_viewable_source_add (GTK_WIDGET (view),
714
gimp_view_drag_viewable,
719
gimp_view_renderer_set_viewable (view->renderer, viewable);
720
view->viewable = viewable;
724
g_object_add_weak_pointer (G_OBJECT (view->viewable),
725
(gpointer *) &view->viewable);
754
g_signal_emit (view, view_signals[SET_VIEWABLE], 0, view->viewable, viewable);
770
798
static GimpViewable *
771
gimp_view_drag_viewable (GtkWidget *widget,
799
gimp_view_drag_viewable (GtkWidget *widget,
800
GimpContext **context,
804
*context = GIMP_VIEW (widget)->renderer->context;
774
806
return GIMP_VIEW (widget)->viewable;
810
gimp_view_drag_pixbuf (GtkWidget *widget,
813
GimpView *view = GIMP_VIEW (widget);
814
GimpViewable *viewable = view->viewable;
818
if (viewable && gimp_viewable_get_size (viewable, &width, &height))
819
return gimp_viewable_get_new_pixbuf (viewable, view->renderer->context,