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 requisition->width = 500;
153 requisition->height = 500;
157 ev_view_size_allocate (GtkWidget *widget,
158 GtkAllocation *allocation)
160 EvView *view = EV_VIEW (widget);
162 GTK_WIDGET_CLASS (ev_view_parent_class)->size_allocate (widget, allocation);
164 view_set_adjustment_values (view, GTK_ORIENTATION_HORIZONTAL);
165 view_set_adjustment_values (view, GTK_ORIENTATION_VERTICAL);
167 if (GTK_WIDGET_REALIZED (widget)) {
168 gdk_window_resize (view->bin_window,
169 MAX (widget->allocation.width, widget->requisition.width),
170 MAX (widget->allocation.height, widget->requisition.height));
175 update_window_backgrounds (EvView *view)
177 GtkWidget *widget = GTK_WIDGET (view);
179 if (GTK_WIDGET_REALIZED (view)) {
180 gdk_window_set_background (view->bin_window,
181 &widget->style->base[GTK_WIDGET_STATE (widget)]);
186 ev_view_realize (GtkWidget *widget)
188 EvView *view = EV_VIEW (widget);
189 GdkWindowAttr attributes;
191 GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
193 attributes.window_type = GDK_WINDOW_CHILD;
194 attributes.wclass = GDK_INPUT_OUTPUT;
195 attributes.visual = gtk_widget_get_visual (widget);
196 attributes.colormap = gtk_widget_get_colormap (widget);
198 attributes.x = widget->allocation.x;
199 attributes.y = widget->allocation.y;
200 attributes.width = widget->allocation.width;
201 attributes.height = widget->allocation.height;
202 attributes.event_mask = 0;
204 widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
206 GDK_WA_X | GDK_WA_Y |
209 gdk_window_set_user_data (widget->window, widget);
210 widget->style = gtk_style_attach (widget->style, widget->window);
214 attributes.width = MAX (widget->allocation.width, widget->requisition.width);
215 attributes.height = MAX (widget->allocation.height, widget->requisition.height);
216 attributes.event_mask = GDK_EXPOSURE_MASK;
218 view->bin_window = gdk_window_new (widget->window,
220 GDK_WA_X | GDK_WA_Y |
223 gdk_window_set_user_data (view->bin_window, widget);
224 gdk_window_show (view->bin_window);
227 ev_document_set_target (view->document, view->bin_window);
229 update_window_backgrounds (view);
233 ev_view_unrealize (GtkWidget *widget)
235 EvView *view = EV_VIEW (widget);
238 ev_document_set_target (view->document, NULL);
240 gdk_window_set_user_data (view->bin_window, NULL);
241 gdk_window_destroy (view->bin_window);
242 view->bin_window = NULL;
244 GTK_WIDGET_CLASS (ev_view_parent_class)->unrealize (widget);
248 ev_view_style_set (GtkWidget *widget,
249 GtkStyle *previous_style)
251 update_window_backgrounds (EV_VIEW (widget));
255 ev_view_state_changed (GtkWidget *widget,
256 GtkStateType previous_state)
258 update_window_backgrounds (EV_VIEW (widget));
262 expose_bin_window (GtkWidget *widget,
263 GdkEventExpose *event)
265 EvView *view = EV_VIEW (widget);
268 ev_document_render (view->document,
269 event->area.x, event->area.y,
270 event->area.width, event->area.height);
274 ev_view_expose_event (GtkWidget *widget,
275 GdkEventExpose *event)
277 EvView *view = EV_VIEW (widget);
279 if (event->window == view->bin_window)
280 expose_bin_window (widget, event);
282 return GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event (widget, event);
289 ev_view_button_press_event (GtkWidget *widget,
290 GdkEventButton *event)
292 /* EvView *view = EV_VIEW (widget); */
298 ev_view_motion_notify_event (GtkWidget *widget,
299 GdkEventMotion *event)
301 /* EvView *view = EV_VIEW (widget); */
307 ev_view_button_release_event (GtkWidget *widget,
308 GdkEventButton *event)
310 /* EvView *view = EV_VIEW (widget); */
316 on_adjustment_value_changed (GtkAdjustment *adjustment,
319 view_update_adjustments (view);
323 set_scroll_adjustment (EvView *view,
324 GtkOrientation orientation,
325 GtkAdjustment *adjustment)
327 GtkAdjustment **to_set;
329 if (orientation == GTK_ORIENTATION_HORIZONTAL)
330 to_set = &view->hadjustment;
332 to_set = &view->vadjustment;
334 if (*to_set != adjustment) {
336 g_signal_handlers_disconnect_by_func (*to_set,
337 (gpointer) on_adjustment_value_changed,
339 g_object_unref (*to_set);
342 *to_set = adjustment;
343 view_set_adjustment_values (view, orientation);
346 g_object_ref (*to_set);
347 g_signal_connect (*to_set, "value_changed",
348 G_CALLBACK (on_adjustment_value_changed), view);
354 ev_view_set_scroll_adjustments (EvView *view,
355 GtkAdjustment *hadjustment,
356 GtkAdjustment *vadjustment)
358 set_scroll_adjustment (view, GTK_ORIENTATION_HORIZONTAL, hadjustment);
359 set_scroll_adjustment (view, GTK_ORIENTATION_VERTICAL, vadjustment);
361 view_update_adjustments (view);
365 ev_view_class_init (EvViewClass *class)
367 GObjectClass *object_class = G_OBJECT_CLASS (class);
368 GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (class);
369 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
371 object_class->finalize = ev_view_finalize;
373 widget_class->expose_event = ev_view_expose_event;
374 widget_class->button_press_event = ev_view_button_press_event;
375 widget_class->motion_notify_event = ev_view_motion_notify_event;
376 widget_class->button_release_event = ev_view_button_release_event;
377 widget_class->size_request = ev_view_size_request;
378 widget_class->size_allocate = ev_view_size_allocate;
379 widget_class->realize = ev_view_realize;
380 widget_class->unrealize = ev_view_unrealize;
381 widget_class->style_set = ev_view_style_set;
382 widget_class->state_changed = ev_view_state_changed;
383 gtk_object_class->destroy = ev_view_destroy;
385 class->set_scroll_adjustments = ev_view_set_scroll_adjustments;
387 widget_class->set_scroll_adjustments_signal = g_signal_new ("set-scroll-adjustments",
388 G_OBJECT_CLASS_TYPE (object_class),
389 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
390 G_STRUCT_OFFSET (EvViewClass, set_scroll_adjustments),
392 ev_marshal_VOID__OBJECT_OBJECT,
395 GTK_TYPE_ADJUSTMENT);
399 ev_view_init (EvView *view)
401 static const GdkColor white = { 0, 0xffff, 0xffff, 0xffff };
403 gtk_widget_modify_bg (GTK_WIDGET (view), GTK_STATE_NORMAL, &white);
411 return g_object_new (EV_TYPE_VIEW, NULL);
415 ev_view_set_document (EvView *view,
416 EvDocument *document)
418 g_return_if_fail (EV_IS_VIEW (view));
420 if (document != view->document) {
422 g_object_unref (view->document);
424 view->document = document;
427 g_object_ref (view->document);
429 if (GTK_WIDGET_REALIZED (view))
430 ev_document_set_target (view->document, view->bin_window);
432 gtk_widget_queue_resize (GTK_WIDGET (view));