summaryrefslogtreecommitdiff
path: root/src/book-view.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/book-view.c')
-rw-r--r--src/book-view.c224
1 files changed, 139 insertions, 85 deletions
diff --git a/src/book-view.c b/src/book-view.c
index e45e22c..377a156 100644
--- a/src/book-view.c
+++ b/src/book-view.c
@@ -18,8 +18,14 @@
// FIXME: Only render pages that change and only the part that changed
enum {
+ PROP_0,
+ PROP_BOOK
+};
+
+enum {
PAGE_SELECTED,
SHOW_PAGE,
+ SHOW_MENU,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0, };
@@ -37,25 +43,22 @@ struct BookViewPrivate
PageView *selected_page;
/* Widget being rendered to */
- GtkWidget *widget;
+ GtkWidget *drawing_area;
- /* Horizontal adjustment */
+ /* Horizontal scrollbar */
+ GtkWidget *scroll;
GtkAdjustment *adjustment;
- GtkWidget *box, *scroll;
-
- GtkWidget *page_menu;
-
gint cursor;
};
-G_DEFINE_TYPE (BookView, book_view, G_TYPE_OBJECT);
+G_DEFINE_TYPE (BookView, book_view, GTK_TYPE_VBOX);
BookView *
-book_view_new ()
+book_view_new (Book *book)
{
- return g_object_new (BOOK_VIEW_TYPE, NULL);
+ return g_object_new (BOOK_VIEW_TYPE, "book", book, NULL);
}
@@ -148,7 +151,7 @@ set_selected_page (BookView *view, PageView *page)
return;
/* Select new page if widget has focus */
- if (!gtk_widget_has_focus (view->priv->widget))
+ if (!gtk_widget_has_focus (view->priv->drawing_area))
page_view_set_selected (view->priv->selected_page, FALSE);
else
page_view_set_selected (view->priv->selected_page, TRUE);
@@ -173,17 +176,19 @@ static void
show_page (BookView *view, PageView *page)
{
gint left_edge, right_edge;
+ GtkAllocation allocation;
if (!page || !gtk_widget_get_visible (view->priv->scroll))
return;
+ gtk_widget_get_allocation(view->priv->drawing_area, &allocation);
left_edge = page_view_get_x_offset (page);
right_edge = page_view_get_x_offset (page) + page_view_get_width (page);
if (left_edge - get_x_offset (view) < 0)
set_x_offset(view, left_edge);
- else if (right_edge - get_x_offset (view) > view->priv->widget->allocation.width)
- set_x_offset(view, right_edge - view->priv->widget->allocation.width);
+ else if (right_edge - get_x_offset (view) > allocation.width)
+ set_x_offset(view, right_edge - allocation.width);
}
@@ -241,32 +246,6 @@ clear_cb (Book *book, BookView *view)
}
-void
-book_view_set_book (BookView *view, Book *book)
-{
- gint i, n_pages;
-
- g_return_if_fail (view != NULL);
- g_return_if_fail (book != NULL);
-
- view->priv->book = g_object_ref (book);
-
- /* Load existing pages */
- n_pages = book_get_n_pages (view->priv->book);
- for (i = 0; i < n_pages; i++) {
- Page *page = book_get_page (book, i);
- add_cb (book, page, view);
- }
-
- book_view_select_page (view, book_get_page (book, 0));
-
- /* Watch for new pages */
- g_signal_connect (book, "page-added", G_CALLBACK (add_cb), view);
- g_signal_connect (book, "page-removed", G_CALLBACK (remove_cb), view);
- g_signal_connect (book, "cleared", G_CALLBACK (clear_cb), view);
-}
-
-
Book *
book_view_get_book (BookView *view)
{
@@ -370,36 +349,40 @@ layout (BookView *view)
{
gint width, height, book_width, book_height;
gboolean right_aligned = TRUE;
+ GtkAllocation allocation, box_allocation;
if (!view->priv->need_layout)
return;
-
+
view->priv->laying_out = TRUE;
+ gtk_widget_get_allocation(view->priv->drawing_area, &allocation);
+ gtk_widget_get_allocation(GTK_WIDGET(view), &box_allocation);
+
/* If scroll is right aligned then keep that after layout */
if (gtk_adjustment_get_value (view->priv->adjustment) < gtk_adjustment_get_upper (view->priv->adjustment) - gtk_adjustment_get_page_size (view->priv->adjustment))
right_aligned = FALSE;
-
+
/* Try and fit without scrollbar */
- width = view->priv->widget->allocation.width;
- height = view->priv->box->allocation.height;
+ width = allocation.width;
+ height = box_allocation.height - gtk_container_get_border_width (GTK_CONTAINER (view)) * 2;
layout_into (view, width, height, &book_width, &book_height);
/* Relayout with scrollbar */
- if (book_width > view->priv->widget->allocation.width) {
+ if (book_width > allocation.width) {
gint max_offset;
/* Re-layout leaving space for scrollbar */
- height = view->priv->widget->allocation.height;
+ height = allocation.height;
layout_into (view, width, height, &book_width, &book_height);
/* Set scrollbar limits */
gtk_adjustment_set_lower (view->priv->adjustment, 0);
gtk_adjustment_set_upper (view->priv->adjustment, book_width);
- gtk_adjustment_set_page_size (view->priv->adjustment, view->priv->widget->allocation.width);
+ gtk_adjustment_set_page_size (view->priv->adjustment, allocation.width);
/* Keep right-aligned */
- max_offset = book_width - view->priv->widget->allocation.width;
+ max_offset = book_width - allocation.width;
if (right_aligned || get_x_offset (view) > max_offset)
set_x_offset(view, max_offset);
@@ -407,7 +390,7 @@ layout (BookView *view)
} else {
gint offset;
gtk_widget_hide (view->priv->scroll);
- offset = (book_width - view->priv->widget->allocation.width) / 2;
+ offset = (book_width - allocation.width) / 2;
gtk_adjustment_set_lower (view->priv->adjustment, offset);
gtk_adjustment_set_upper (view->priv->adjustment, offset);
gtk_adjustment_set_page_size (view->priv->adjustment, 0);
@@ -435,7 +418,7 @@ expose_cb (GtkWidget *widget, GdkEventExpose *event, BookView *view)
layout (view);
- context = gdk_cairo_create (widget->window);
+ context = gdk_cairo_create (gtk_widget_get_window(widget));
/* Render each page */
for (i = 0; i < n_pages; i++) {
@@ -455,8 +438,8 @@ expose_cb (GtkWidget *widget, GdkEventExpose *event, BookView *view)
cairo_restore (context);
if (page_view_get_selected (page))
- gtk_paint_focus (gtk_widget_get_style (view->priv->widget),
- gtk_widget_get_window (view->priv->widget),
+ gtk_paint_focus (gtk_widget_get_style (view->priv->drawing_area),
+ gtk_widget_get_window (view->priv->drawing_area),
GTK_STATE_SELECTED,
&event->area,
NULL,
@@ -507,7 +490,7 @@ button_cb (GtkWidget *widget, GdkEventButton *event, BookView *view)
layout (view);
- gtk_widget_grab_focus (view->priv->widget);
+ gtk_widget_grab_focus (view->priv->drawing_area);
if (event->type == GDK_BUTTON_PRESS)
select_page (view, get_page_at (view, event->x + get_x_offset (view), event->y, &x, &y));
@@ -526,10 +509,8 @@ button_cb (GtkWidget *widget, GdkEventButton *event, BookView *view)
}
/* Show pop-up menu on right click */
- if (event->button == 3) {
- gtk_menu_popup (GTK_MENU (view->priv->page_menu), NULL, NULL, NULL, NULL,
- event->button, event->time);
- }
+ if (event->button == 3)
+ g_signal_emit (view, signals[SHOW_MENU], 0);
return FALSE;
}
@@ -545,7 +526,7 @@ set_cursor (BookView *view, gint cursor)
view->priv->cursor = cursor;
c = gdk_cursor_new (cursor);
- gdk_window_set_cursor (gtk_widget_get_window (view->priv->widget), c);
+ gdk_window_set_cursor (gtk_widget_get_window (view->priv->drawing_area), c);
gdk_cursor_destroy (c);
}
@@ -618,34 +599,10 @@ scroll_cb (GtkAdjustment *adjustment, BookView *view)
void
-book_view_set_widgets (BookView *view, GtkWidget *box, GtkWidget *area, GtkWidget *scroll, GtkWidget *page_menu)
-{
- g_return_if_fail (view != NULL);
- g_return_if_fail (view->priv->widget == NULL);
-
- view->priv->widget = area;
- view->priv->box = box;
- view->priv->scroll = scroll;
- view->priv->adjustment = gtk_range_get_adjustment (GTK_RANGE (scroll));
- view->priv->page_menu = page_menu;
-
- g_signal_connect (area, "configure-event", G_CALLBACK (configure_cb), view);
- g_signal_connect (area, "expose-event", G_CALLBACK (expose_cb), view);
- g_signal_connect (area, "motion-notify-event", G_CALLBACK (motion_cb), view);
- g_signal_connect (area, "key-press-event", G_CALLBACK (key_cb), view);
- g_signal_connect (area, "button-press-event", G_CALLBACK (button_cb), view);
- g_signal_connect (area, "button-release-event", G_CALLBACK (button_cb), view);
- g_signal_connect_after (area, "focus-in-event", G_CALLBACK (focus_cb), view);
- g_signal_connect_after (area, "focus-out-event", G_CALLBACK (focus_cb), view);
- g_signal_connect (view->priv->adjustment, "value-changed", G_CALLBACK (scroll_cb), view);
-}
-
-
-void
book_view_redraw (BookView *view)
{
g_return_if_fail (view != NULL);
- gtk_widget_queue_draw (view->priv->widget);
+ gtk_widget_queue_draw (view->priv->drawing_area);
}
@@ -693,6 +650,63 @@ book_view_get_selected (BookView *view)
static void
+book_view_set_property(GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ BookView *self;
+ gint i, n_pages;
+
+ self = BOOK_VIEW (object);
+
+ switch (prop_id) {
+ case PROP_BOOK:
+ self->priv->book = g_object_ref (g_value_get_object (value));
+
+ /* Load existing pages */
+ n_pages = book_get_n_pages (self->priv->book);
+ for (i = 0; i < n_pages; i++) {
+ Page *page = book_get_page (self->priv->book, i);
+ add_cb (self->priv->book, page, self);
+ }
+
+ book_view_select_page (self, book_get_page (self->priv->book, 0));
+
+ /* Watch for new pages */
+ g_signal_connect (self->priv->book, "page-added", G_CALLBACK (add_cb), self);
+ g_signal_connect (self->priv->book, "page-removed", G_CALLBACK (remove_cb), self);
+ g_signal_connect (self->priv->book, "cleared", G_CALLBACK (clear_cb), self);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
+book_view_get_property(GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ BookView *self;
+
+ self = BOOK_VIEW (object);
+
+ switch (prop_id) {
+ case PROP_BOOK:
+ g_value_set_object (value, self->priv->book);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+
+static void
book_view_finalize (GObject *object)
{
BookView *view = BOOK_VIEW (object);
@@ -710,6 +724,8 @@ book_view_class_init (BookViewClass *klass)
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->finalize = book_view_finalize;
+ object_class->set_property = book_view_set_property;
+ object_class->get_property = book_view_get_property;
signals[PAGE_SELECTED] =
g_signal_new ("page-selected",
@@ -717,16 +733,32 @@ book_view_class_init (BookViewClass *klass)
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (BookViewClass, page_selected),
NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, page_get_type ());
signals[SHOW_PAGE] =
g_signal_new ("show-page",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (BookViewClass, show_page),
NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
- G_TYPE_NONE, 1, G_TYPE_POINTER);
+ g_cclosure_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1, page_get_type ());
+ signals[SHOW_MENU] =
+ g_signal_new ("show-menu",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (BookViewClass, show_page),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ g_object_class_install_property(object_class,
+ PROP_BOOK,
+ g_param_spec_object("book",
+ "book",
+ "Book being shown",
+ book_get_type(),
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_type_class_add_private (klass, sizeof (BookViewPrivate));
}
@@ -740,4 +772,26 @@ book_view_init (BookView *view)
view->priv->page_data = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, (GDestroyNotify) g_object_unref);
view->priv->cursor = GDK_ARROW;
+
+ view->priv->drawing_area = gtk_drawing_area_new ();
+ gtk_widget_set_size_request (view->priv->drawing_area, 200, 100);
+ gtk_widget_set_can_focus (view->priv->drawing_area, TRUE);
+ gtk_widget_set_events (view->priv->drawing_area, GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_FOCUS_CHANGE_MASK | GDK_STRUCTURE_MASK | GDK_SCROLL_MASK);
+ gtk_box_pack_start (GTK_BOX (view), view->priv->drawing_area, TRUE, TRUE, 0);
+
+ view->priv->scroll = gtk_hscrollbar_new (NULL);
+ view->priv->adjustment = gtk_range_get_adjustment (GTK_RANGE (view->priv->scroll));
+ gtk_box_pack_start (GTK_BOX (view), view->priv->scroll, FALSE, TRUE, 0);
+
+ g_signal_connect (view->priv->drawing_area, "configure-event", G_CALLBACK (configure_cb), view);
+ g_signal_connect (view->priv->drawing_area, "expose-event", G_CALLBACK (expose_cb), view);
+ g_signal_connect (view->priv->drawing_area, "motion-notify-event", G_CALLBACK (motion_cb), view);
+ g_signal_connect (view->priv->drawing_area, "key-press-event", G_CALLBACK (key_cb), view);
+ g_signal_connect (view->priv->drawing_area, "button-press-event", G_CALLBACK (button_cb), view);
+ g_signal_connect (view->priv->drawing_area, "button-release-event", G_CALLBACK (button_cb), view);
+ g_signal_connect_after (view->priv->drawing_area, "focus-in-event", G_CALLBACK (focus_cb), view);
+ g_signal_connect_after (view->priv->drawing_area, "focus-out-event", G_CALLBACK (focus_cb), view);
+ g_signal_connect (view->priv->adjustment, "value-changed", G_CALLBACK (scroll_cb), view);
+
+ gtk_widget_show (view->priv->drawing_area);
}