1 /* this file is part of evince, a gnome document viewer
3 * Copyright (C) 2004 Red Hat, Inc
5 * Evince is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * Evince is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20 #include <gtk/gtkalignment.h>
22 #include "ev-marshal.h"
25 #define EV_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_VIEW, EvViewClass))
26 #define EV_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_VIEW))
27 #define EV_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_VIEW, EvViewClass))
30 GtkWidget parent_instance;
34 GdkWindow *bin_window;
39 GtkAdjustment *hadjustment;
40 GtkAdjustment *vadjustment;
44 GtkWidgetClass parent_class;
46 void (*set_scroll_adjustments) (EvView *view,
47 GtkAdjustment *hadjustment,
48 GtkAdjustment *vadjustment);
51 static void ev_view_set_scroll_adjustments (EvView *view,
52 GtkAdjustment *hadjustment,
53 GtkAdjustment *vadjustment);
55 G_DEFINE_TYPE (EvView, ev_view, GTK_TYPE_WIDGET)
57 /*** Helper functions ***/
60 view_update_adjustments (EvView *view)
62 int old_x = view->scroll_x;
63 int old_y = view->scroll_y;
65 if (view->hadjustment)
66 view->scroll_x = view->hadjustment->value;
70 if (view->vadjustment)
71 view->scroll_y = view->vadjustment->value;
75 if (GTK_WIDGET_REALIZED (view) &&
76 (view->scroll_x != old_x || view->scroll_y != old_y)) {
77 gdk_window_move (view->bin_window, - view->scroll_x, - view->scroll_y);
78 gdk_window_process_updates (view->bin_window, TRUE);
83 view_set_adjustment_values (EvView *view,
84 GtkOrientation orientation)
86 GtkWidget *widget = GTK_WIDGET (view);
87 GtkAdjustment *adjustment;
88 gboolean value_changed = FALSE;
92 if (orientation == GTK_ORIENTATION_HORIZONTAL) {
93 requisition = widget->requisition.width;
94 allocation = widget->allocation.width;
95 adjustment = view->hadjustment;
97 requisition = widget->requisition.height;
98 allocation = widget->allocation.height;
99 adjustment = view->vadjustment;
105 adjustment->page_size = allocation;
106 adjustment->step_increment = allocation * 0.1;
107 adjustment->page_increment = allocation * 0.9;
108 adjustment->lower = 0;
109 adjustment->upper = MAX (allocation, requisition);
111 if (adjustment->value > adjustment->upper - adjustment->page_size) {
112 adjustment->value = adjustment->upper - adjustment->page_size;
113 value_changed = TRUE;
116 gtk_adjustment_changed (adjustment);
118 gtk_adjustment_value_changed (adjustment);
121 /*** Virtual function implementations ***/
124 ev_view_finalize (GObject *object)
126 EvView *view = EV_VIEW (object);
129 g_object_unref (view->document);
131 ev_view_set_scroll_adjustments (view, NULL, NULL);
133 G_OBJECT_CLASS (ev_view_parent_class)->finalize (object);
137 ev_view_destroy (GtkObject *object)
139 EvView *view = EV_VIEW (object);
141 ev_view_set_scroll_adjustments (view, NULL, NULL);
143 GTK_OBJECT_CLASS (ev_view_parent_class)->destroy (object);
147 ev_view_size_request (GtkWidget *widget,
148 GtkRequisition *requisition)
150 EvView *view = EV_VIEW (widget);
152 if (GTK_WIDGET_REALIZED (widget)) {
153 if (view->document) {
154 ev_document_get_page_size (view->document,
156 &requisition->height);
158 requisition->width = 10;
159 requisition->height = 10;
166 ev_view_size_allocate (GtkWidget *widget,
167 GtkAllocation *allocation)
169 EvView *view = EV_VIEW (widget);
171 GTK_WIDGET_CLASS (ev_view_parent_class)->size_allocate (widget, allocation);
173 view_set_adjustment_values (view, GTK_ORIENTATION_HORIZONTAL);
174 view_set_adjustment_values (view, GTK_ORIENTATION_VERTICAL);
176 if (GTK_WIDGET_REALIZED (widget)) {
177 gdk_window_resize (view->bin_window,
178 MAX (widget->allocation.width, widget->requisition.width),
179 MAX (widget->allocation.height, widget->requisition.height));
184 update_window_backgrounds (EvView *view)
186 GtkWidget *widget = GTK_WIDGET (view);
188 if (GTK_WIDGET_REALIZED (view)) {
189 gdk_window_set_background (view->bin_window,
190 &widget->style->base[GTK_WIDGET_STATE (widget)]);
195 ev_view_realize (GtkWidget *widget)
197 EvView *view = EV_VIEW (widget);
198 GdkWindowAttr attributes;
200 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
202 attributes.window_type = GDK_WINDOW_CHILD;
203 attributes.wclass = GDK_INPUT_OUTPUT;
204 attributes.visual = gtk_widget_get_visual (widget);
205 attributes.colormap = gtk_widget_get_colormap (widget);
207 attributes.x = widget->allocation.x;
208 attributes.y = widget->allocation.y;
209 attributes.width = widget->allocation.width;
210 attributes.height = widget->allocation.height;
211 attributes.event_mask = 0;
213 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
215 GDK_WA_X | GDK_WA_Y |
218 gdk_window_set_user_data (widget->window, widget);
219 widget->style = gtk_style_attach (widget->style, widget->window);
223 attributes.width = MAX (widget->allocation.width, widget->requisition.width);
224 attributes.height = MAX (widget->allocation.height, widget->requisition.height);
225 attributes.event_mask = GDK_EXPOSURE_MASK;
227 view->bin_window = gdk_window_new (widget->window,
229 GDK_WA_X | GDK_WA_Y |
232 gdk_window_set_user_data (view->bin_window, widget);
233 gdk_window_show (view->bin_window);
235 if (view->document) {
236 ev_document_set_target (view->document, view->bin_window);
238 /* We can't get page size without a target, so we have to
239 * queue a size request at realization. Could be fixed
240 * with EvDocument changes to allow setting a GdkScreen
241 * without setting a target.
243 gtk_widget_queue_resize (widget);
246 update_window_backgrounds (view);
250 ev_view_unrealize (GtkWidget *widget)
252 EvView *view = EV_VIEW (widget);
255 ev_document_set_target (view->document, NULL);
257 gdk_window_set_user_data (view->bin_window, NULL);
258 gdk_window_destroy (view->bin_window);
259 view->bin_window = NULL;
261 GTK_WIDGET_CLASS (ev_view_parent_class)->unrealize (widget);
265 ev_view_style_set (GtkWidget *widget,
266 GtkStyle *previous_style)
268 update_window_backgrounds (EV_VIEW (widget));
272 ev_view_state_changed (GtkWidget *widget,
273 GtkStateType previous_state)
275 update_window_backgrounds (EV_VIEW (widget));
279 expose_bin_window (GtkWidget *widget,
280 GdkEventExpose *event)
282 EvView *view = EV_VIEW (widget);
285 ev_document_render (view->document,
286 event->area.x, event->area.y,
287 event->area.width, event->area.height);
291 ev_view_expose_event (GtkWidget *widget,
292 GdkEventExpose *event)
294 EvView *view = EV_VIEW (widget);
296 if (event->window == view->bin_window)
297 expose_bin_window (widget, event);
299 return GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event (widget, event);
306 ev_view_button_press_event (GtkWidget *widget,
307 GdkEventButton *event)
309 /* EvView *view = EV_VIEW (widget); */
315 ev_view_motion_notify_event (GtkWidget *widget,
316 GdkEventMotion *event)
318 /* EvView *view = EV_VIEW (widget); */
324 ev_view_button_release_event (GtkWidget *widget,
325 GdkEventButton *event)
327 /* EvView *view = EV_VIEW (widget); */
333 on_adjustment_value_changed (GtkAdjustment *adjustment,
336 view_update_adjustments (view);
340 set_scroll_adjustment (EvView *view,
341 GtkOrientation orientation,
342 GtkAdjustment *adjustment)
344 GtkAdjustment **to_set;
346 if (orientation == GTK_ORIENTATION_HORIZONTAL)
347 to_set = &view->hadjustment;
349 to_set = &view->vadjustment;
351 if (*to_set != adjustment) {
353 g_signal_handlers_disconnect_by_func (*to_set,
354 (gpointer) on_adjustment_value_changed,
356 g_object_unref (*to_set);
359 *to_set = adjustment;
360 view_set_adjustment_values (view, orientation);
363 g_object_ref (*to_set);
364 g_signal_connect (*to_set, "value_changed",
365 G_CALLBACK (on_adjustment_value_changed), view);
371 ev_view_set_scroll_adjustments (EvView *view,
372 GtkAdjustment *hadjustment,
373 GtkAdjustment *vadjustment)
375 set_scroll_adjustment (view, GTK_ORIENTATION_HORIZONTAL, hadjustment);
376 set_scroll_adjustment (view, GTK_ORIENTATION_VERTICAL, vadjustment);
378 view_update_adjustments (view);
382 ev_view_class_init (EvViewClass *class)
384 GObjectClass *object_class = G_OBJECT_CLASS (class);
385 GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (class);
386 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
388 object_class->finalize = ev_view_finalize;
390 widget_class->expose_event = ev_view_expose_event;
391 widget_class->button_press_event = ev_view_button_press_event;
392 widget_class->motion_notify_event = ev_view_motion_notify_event;
393 widget_class->button_release_event = ev_view_button_release_event;
394 widget_class->size_request = ev_view_size_request;
395 widget_class->size_allocate = ev_view_size_allocate;
396 widget_class->realize = ev_view_realize;
397 widget_class->unrealize = ev_view_unrealize;
398 widget_class->style_set = ev_view_style_set;
399 widget_class->state_changed = ev_view_state_changed;
400 gtk_object_class->destroy = ev_view_destroy;
402 class->set_scroll_adjustments = ev_view_set_scroll_adjustments;
404 widget_class->set_scroll_adjustments_signal = g_signal_new ("set-scroll-adjustments",
405 G_OBJECT_CLASS_TYPE (object_class),
406 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
407 G_STRUCT_OFFSET (EvViewClass, set_scroll_adjustments),
409 ev_marshal_VOID__OBJECT_OBJECT,
412 GTK_TYPE_ADJUSTMENT);
416 ev_view_init (EvView *view)
418 static const GdkColor white = { 0, 0xffff, 0xffff, 0xffff };
420 gtk_widget_modify_bg (GTK_WIDGET (view), GTK_STATE_NORMAL, &white);
428 return g_object_new (EV_TYPE_VIEW, NULL);
432 ev_view_set_document (EvView *view,
433 EvDocument *document)
435 g_return_if_fail (EV_IS_VIEW (view));
437 if (document != view->document) {
439 g_object_unref (view->document);
441 view->document = document;
444 g_object_ref (view->document);
446 if (GTK_WIDGET_REALIZED (view))
447 ev_document_set_target (view->document, view->bin_window);
449 gtk_widget_queue_resize (GTK_WIDGET (view));