From ff8d0330fc705c931a40d07e28eb4060f1dd92f9 Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Wed, 22 Dec 2004 02:19:48 +0000 Subject: Start of content-area widget. Tue Dec 21 21:07:55 2004 Owen Taylor * shell/ev-view.[ch]: Start of content-area widget. * shell/ev-window.c: Create a EvView, update it as we change documents. * shell/Makefile.am shell/ev-marshal.list: Add generated marshalers. --- (limited to 'shell') diff --git a/shell/.cvsignore b/shell/.cvsignore index 48971d0..eb9b107 100644 --- a/shell/.cvsignore +++ b/shell/.cvsignore @@ -1,3 +1,4 @@ Makefile Makefile.in evince +ev-marshal.[ch] diff --git a/shell/Makefile.am b/shell/Makefile.am index 891eadb..e764e3a 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -17,6 +17,10 @@ evince_SOURCES= \ eggfindbar.h \ ev-application.c \ ev-application.h \ + ev-marshal.c \ + ev-marshal.h \ + ev-view.c \ + ev-view.h \ ev-window.c \ ev-window.h \ ev-sidebar.c \ @@ -29,3 +33,14 @@ evince_LDADD= \ $(top_builddir)/backend/libevbackend.la \ $(top_builddir)/pdf/xpdf/libpdfdocument.la \ $(NULL) + +BUILT_SOURCES = ev-marshal.h ev-marshal.c + +EXTRA_DIST = ev-marshal.list + +ev-marshal.h: ev-marshal.list + glib-genmarshal --prefix=ev_marshal ev-marshal.list --header > ev-marshal.h + +ev-marshal.c: ev-marshal.list + echo '#include "ev-marshal.h"' > ev-marshal.c + glib-genmarshal --prefix=ev_marshal ev-marshal.list --body >> ev-marshal.c diff --git a/shell/ev-marshal.list b/shell/ev-marshal.list new file mode 100644 index 0000000..38076d6 --- /dev/null +++ b/shell/ev-marshal.list @@ -0,0 +1 @@ +VOID:OBJECT,OBJECT diff --git a/shell/ev-view.c b/shell/ev-view.c new file mode 100644 index 0000000..70b50e0 --- /dev/null +++ b/shell/ev-view.c @@ -0,0 +1,422 @@ +/* this file is part of evince, a gnome document viewer + * + * Copyright (C) 2004 Red Hat, Inc + * + * Evince is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Evince 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#include + +#include "ev-marshal.h" +#include "ev-view.h" + +#define EV_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_VIEW, EvViewClass)) +#define EV_IS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_VIEW)) +#define EV_VIEW_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_VIEW, EvViewClass)) + +struct _EvView { + GtkWidget parent_instance; + + EvDocument *document; + + GdkWindow *bin_window; + + int scroll_x; + int scroll_y; + + GtkAdjustment *hadjustment; + GtkAdjustment *vadjustment; +}; + +struct _EvViewClass { + GtkWidgetClass parent_class; + + void (*set_scroll_adjustments) (EvView *view, + GtkAdjustment *hadjustment, + GtkAdjustment *vadjustment); +}; + +static void ev_view_set_scroll_adjustments (EvView *view, + GtkAdjustment *hadjustment, + GtkAdjustment *vadjustment); + +G_DEFINE_TYPE (EvView, ev_view, GTK_TYPE_WIDGET) + +/*** Helper functions ***/ + +static void +view_update_adjustments (EvView *view) +{ + int old_x = view->scroll_x; + int old_y = view->scroll_y; + + if (view->hadjustment) + view->scroll_x = view->hadjustment->value; + else + view->scroll_x = 0; + + if (view->vadjustment) + view->scroll_y = view->vadjustment->value; + else + view->scroll_y = 0; + + if (GTK_WIDGET_REALIZED (view) && + (view->scroll_x != old_x || view->scroll_y != old_y)) { + gdk_window_move (view->bin_window, - view->scroll_x, - view->scroll_y); + gdk_window_process_updates (view->bin_window, TRUE); + } +} + +static void +view_set_adjustment_values (EvView *view, + GtkOrientation orientation) +{ + GtkWidget *widget = GTK_WIDGET (view); + GtkAdjustment *adjustment; + gboolean value_changed = FALSE; + int requisition; + int allocation; + + if (orientation == GTK_ORIENTATION_HORIZONTAL) { + requisition = widget->requisition.width; + allocation = widget->allocation.width; + adjustment = view->hadjustment; + } else { + requisition = widget->requisition.height; + allocation = widget->allocation.height; + adjustment = view->vadjustment; + } + + if (!adjustment) + return; + + adjustment->page_size = allocation; + adjustment->step_increment = allocation * 0.1; + adjustment->page_increment = allocation * 0.9; + adjustment->lower = 0; + adjustment->upper = MAX (allocation, requisition); + + if (adjustment->value > adjustment->upper - adjustment->page_size) { + adjustment->value = adjustment->upper - adjustment->page_size; + value_changed = TRUE; + } + + gtk_adjustment_changed (adjustment); + if (value_changed) + gtk_adjustment_value_changed (adjustment); +} + +/*** Virtual function implementations ***/ + +static void +ev_view_finalize (GObject *object) +{ + EvView *view = EV_VIEW (object); + + if (view->document) + g_object_unref (view->document); + + ev_view_set_scroll_adjustments (view, NULL, NULL); + + G_OBJECT_CLASS (ev_view_parent_class)->finalize (object); +} + +static void +ev_view_destroy (GtkObject *object) +{ + EvView *view = EV_VIEW (object); + + ev_view_set_scroll_adjustments (view, NULL, NULL); + + GTK_OBJECT_CLASS (ev_view_parent_class)->destroy (object); +} + +static void +ev_view_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + /* EvView *view = EV_VIEW (widget); */ + + requisition->width = 500; + requisition->height = 500; +} + +static void +ev_view_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + EvView *view = EV_VIEW (widget); + + GTK_WIDGET_CLASS (ev_view_parent_class)->size_allocate (widget, allocation); + + view_set_adjustment_values (view, GTK_ORIENTATION_HORIZONTAL); + view_set_adjustment_values (view, GTK_ORIENTATION_VERTICAL); + + if (GTK_WIDGET_REALIZED (widget)) { + gdk_window_resize (view->bin_window, + MAX (widget->allocation.width, widget->requisition.width), + MAX (widget->allocation.height, widget->requisition.height)); + } +} + +static void +update_window_backgrounds (EvView *view) +{ + GtkWidget *widget = GTK_WIDGET (view); + + if (GTK_WIDGET_REALIZED (view)) { + gdk_window_set_background (view->bin_window, + &widget->style->base[GTK_WIDGET_STATE (widget)]); + } +} + +static void +ev_view_realize (GtkWidget *widget) +{ + EvView *view = EV_VIEW (widget); + GdkWindowAttr attributes; + + GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED); + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.visual = gtk_widget_get_visual (widget); + attributes.colormap = gtk_widget_get_colormap (widget); + + attributes.x = widget->allocation.x; + attributes.y = widget->allocation.y; + attributes.width = widget->allocation.width; + attributes.height = widget->allocation.height; + attributes.event_mask = 0; + + widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), + &attributes, + GDK_WA_X | GDK_WA_Y | + GDK_WA_COLORMAP | + GDK_WA_VISUAL); + gdk_window_set_user_data (widget->window, widget); + widget->style = gtk_style_attach (widget->style, widget->window); + + attributes.x = 0; + attributes.y = 0; + attributes.width = MAX (widget->allocation.width, widget->requisition.width); + attributes.height = MAX (widget->allocation.height, widget->requisition.height); + attributes.event_mask = GDK_EXPOSURE_MASK; + + view->bin_window = gdk_window_new (widget->window, + &attributes, + GDK_WA_X | GDK_WA_Y | + GDK_WA_COLORMAP | + GDK_WA_VISUAL); + gdk_window_set_user_data (view->bin_window, widget); + gdk_window_show (view->bin_window); + + attributes.event_mask = GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_MOTION_MASK | GDK_EXPOSURE_MASK; + + update_window_backgrounds (view); +} + +static void +ev_view_unrealize (GtkWidget *widget) +{ + EvView *view = EV_VIEW (widget); + + gdk_window_set_user_data (view->bin_window, NULL); + gdk_window_destroy (view->bin_window); + view->bin_window = NULL; + + GTK_WIDGET_CLASS (ev_view_parent_class)->unrealize (widget); +} + +static void +ev_view_style_set (GtkWidget *widget, + GtkStyle *previous_style) +{ + update_window_backgrounds (EV_VIEW (widget)); +} + +static void +ev_view_state_changed (GtkWidget *widget, + GtkStateType previous_state) +{ + update_window_backgrounds (EV_VIEW (widget)); +} + +static void +expose_bin_window (GtkWidget *widget, + GdkEventExpose *event) +{ + /* EvView *view = EV_VIEW (widget); */ +} + +static gboolean +ev_view_expose_event (GtkWidget *widget, + GdkEventExpose *event) +{ + EvView *view = EV_VIEW (widget); + + if (event->window == view->bin_window) + expose_bin_window (widget, event); + else + return GTK_WIDGET_CLASS (ev_view_parent_class)->expose_event (widget, event); + + return FALSE; + +} + +static gboolean +ev_view_button_press_event (GtkWidget *widget, + GdkEventButton *event) +{ + /* EvView *view = EV_VIEW (widget); */ + + return FALSE; +} + +static gboolean +ev_view_motion_notify_event (GtkWidget *widget, + GdkEventMotion *event) +{ + /* EvView *view = EV_VIEW (widget); */ + + return FALSE; +} + +static gboolean +ev_view_button_release_event (GtkWidget *widget, + GdkEventButton *event) +{ + /* EvView *view = EV_VIEW (widget); */ + + return FALSE; +} + +static void +on_adjustment_value_changed (GtkAdjustment *adjustment, + EvView *view) +{ + view_update_adjustments (view); +} + +static void +set_scroll_adjustment (EvView *view, + GtkOrientation orientation, + GtkAdjustment *adjustment) +{ + GtkAdjustment **to_set; + + if (orientation == GTK_ORIENTATION_HORIZONTAL) + to_set = &view->hadjustment; + else + to_set = &view->vadjustment; + + if (*to_set != adjustment) { + if (*to_set) { + g_signal_handlers_disconnect_by_func (*to_set, + (gpointer) on_adjustment_value_changed, + view); + g_object_unref (*to_set); + } + + *to_set = adjustment; + view_set_adjustment_values (view, orientation); + + if (*to_set) { + g_object_ref (*to_set); + g_signal_connect (*to_set, "value_changed", + G_CALLBACK (on_adjustment_value_changed), view); + } + } +} + +static void +ev_view_set_scroll_adjustments (EvView *view, + GtkAdjustment *hadjustment, + GtkAdjustment *vadjustment) +{ + set_scroll_adjustment (view, GTK_ORIENTATION_HORIZONTAL, hadjustment); + set_scroll_adjustment (view, GTK_ORIENTATION_VERTICAL, vadjustment); + + view_update_adjustments (view); +} + +static void +ev_view_class_init (EvViewClass *class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (class); + GtkObjectClass *gtk_object_class = GTK_OBJECT_CLASS (class); + GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); + + object_class->finalize = ev_view_finalize; + + widget_class->expose_event = ev_view_expose_event; + widget_class->button_press_event = ev_view_button_press_event; + widget_class->motion_notify_event = ev_view_motion_notify_event; + widget_class->button_release_event = ev_view_button_release_event; + widget_class->size_request = ev_view_size_request; + widget_class->size_allocate = ev_view_size_allocate; + widget_class->realize = ev_view_realize; + widget_class->unrealize = ev_view_unrealize; + widget_class->style_set = ev_view_style_set; + widget_class->state_changed = ev_view_state_changed; + gtk_object_class->destroy = ev_view_destroy; + + class->set_scroll_adjustments = ev_view_set_scroll_adjustments; + + widget_class->set_scroll_adjustments_signal = g_signal_new ("set-scroll-adjustments", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EvViewClass, set_scroll_adjustments), + NULL, NULL, + ev_marshal_VOID__OBJECT_OBJECT, + G_TYPE_NONE, 2, + GTK_TYPE_ADJUSTMENT, + GTK_TYPE_ADJUSTMENT); +} + +static void +ev_view_init (EvView *view) +{ + static const GdkColor white = { 0, 0xffff, 0xffff, 0xffff }; + + gtk_widget_modify_bg (GTK_WIDGET (view), GTK_STATE_NORMAL, &white); +} + +/*** Public API ***/ + +GtkWidget* +ev_view_new (void) +{ + return g_object_new (EV_TYPE_VIEW, NULL); +} + +void +ev_view_set_document (EvView *view, + EvDocument *document) +{ + g_return_if_fail (EV_IS_VIEW (view)); + + if (document != view->document) { + if (view->document) + g_object_unref (view->document); + + view->document = document; + + if (view->document) + g_object_ref (view->document); + + gtk_widget_queue_resize (GTK_WIDGET (view)); + } +} diff --git a/shell/ev-view.h b/shell/ev-view.h new file mode 100644 index 0000000..bb958f3 --- /dev/null +++ b/shell/ev-view.h @@ -0,0 +1,45 @@ +/* this file is part of evince, a gnome document viewer + * + * Copyright (C) 2004 Red Hat, Inc + * + * Evince is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Evince 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __EV_VIEW_H__ +#define __EV_VIEW_H__ + +#include + +#include "ev-document.h" + +G_BEGIN_DECLS + +#define EV_TYPE_VIEW (ev_view_get_type ()) +#define EV_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), EV_TYPE_VIEW, EvView)) +#define EV_IS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), EV_TYPE_VIEW)) + + +typedef struct _EvView EvView; +typedef struct _EvViewClass EvViewClass; + +GType ev_view_get_type (void) G_GNUC_CONST; +GtkWidget* ev_view_new (void); + +void ev_view_set_document (EvView *view, + EvDocument *document); + +G_END_DECLS + +#endif /* __EV_VIEW_H__ */ diff --git a/shell/ev-window.c b/shell/ev-window.c index a6097ce..d04dd91 100644 --- a/shell/ev-window.c +++ b/shell/ev-window.c @@ -28,6 +28,7 @@ #include "ev-window.h" #include "ev-sidebar.h" +#include "ev-view.h" #include "eggfindbar.h" #include "pdf-document.h" @@ -56,6 +57,7 @@ struct _EvWindowPrivate { GtkWidget *sidebar; GtkWidget *find_bar; GtkWidget *bonobo_widget; + GtkWidget *view; GtkUIManager *ui_manager; GtkWidget *statusbar; guint help_message_cid; @@ -158,6 +160,9 @@ ev_window_open (EvWindow *ev_window, const char *uri) if (ev_window->priv->document) g_object_unref (ev_window->priv->document); ev_window->priv->document = document; + + ev_view_set_document (EV_VIEW (ev_window->priv->view), + document); } else { GtkWidget *dialog; @@ -708,9 +713,9 @@ ev_window_init (EvWindow *ev_window) GtkActionGroup *action_group; GtkAccelGroup *accel_group; GError *error = NULL; + GtkWidget *scrolled_window; GtkWidget *menubar; GtkWidget *toolbar; - GtkWidget *darea; ev_window->priv = EV_WINDOW_GET_PRIVATE (ev_window); @@ -769,11 +774,17 @@ ev_window_init (EvWindow *ev_window) gtk_paned_add1 (GTK_PANED (ev_window->priv->hpaned), ev_window->priv->sidebar); - /* Stub widget, for now */ - darea = gtk_drawing_area_new (); - gtk_widget_show (darea); + scrolled_window = gtk_scrolled_window_new (NULL, NULL); + gtk_widget_show (scrolled_window); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), + GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_paned_add2 (GTK_PANED (ev_window->priv->hpaned), - darea); + scrolled_window); + + ev_window->priv->view = ev_view_new (); + gtk_widget_show (ev_window->priv->view); + gtk_container_add (GTK_CONTAINER (scrolled_window), + ev_window->priv->view); ev_window->priv->statusbar = gtk_statusbar_new (); gtk_widget_show (ev_window->priv->statusbar); -- cgit v0.9.1