From 5bec9bc0e9bea45cd553116e5d7fd125564d8dbe Mon Sep 17 00:00:00 2001 From: Philip Chimento Date: Thu, 24 Dec 2009 12:48:45 +0000 Subject: [PATCH] Pager! git-svn-id: http://lassie.dyndns-server.com/svn/gargoyle-gtk@208 ddfedd41-794f-dd11-ae45-00112f111e67 --- tests/barf.c | 108 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 29 deletions(-) diff --git a/tests/barf.c b/tests/barf.c index f211210..0bf2a93 100644 --- a/tests/barf.c +++ b/tests/barf.c @@ -5,7 +5,9 @@ #include -static glong pager_handler = 0; +static gulong pager_handler = 0; +static gulong expose_handler = 0; +static gboolean currently_paging = FALSE; static gboolean quit() @@ -28,63 +30,106 @@ barf(GtkButton *button, GtkTextBuffer *buffer) g_free(loremipsum); } -static void -after_insert(GtkTextBuffer *buffer, GtkTextIter *location, gchar *text, gint len, GtkTextView *textview) +static gint +move_pager_and_get_scroll_distance(GtkTextView *textview) { - while(gtk_events_pending()) - gtk_main_iteration(); - GdkRectangle pagerpos, endpos, visiblerect; GtkTextIter pager, end; - gtk_text_buffer_get_end_iter(buffer, &end); - gtk_text_view_get_visible_rect(textview, &visiblerect); + GtkTextBuffer *buffer = gtk_text_view_get_buffer(textview); - /* Move the pager to the last visible character in the buffer */ - gtk_text_view_get_line_at_y(textview, &pager, visiblerect.y, NULL); - if(!gtk_text_iter_ends_line(&pager)) - gtk_text_iter_forward_to_line_end(&pager); + gtk_text_view_get_visible_rect(textview, &visiblerect); + gtk_text_view_get_iter_at_location(textview, &pager, visiblerect.x + visiblerect.width, visiblerect.y + visiblerect.height); gtk_text_buffer_move_mark_by_name(buffer, "pager_position", &pager); + gtk_text_buffer_get_end_iter(buffer, &end); gtk_text_view_get_iter_location(textview, &pager, &pagerpos); gtk_text_view_get_iter_location(textview, &end, &endpos); g_printerr("View height = %d\n", visiblerect.height); g_printerr("End - Pager = %d\n", endpos.y - pagerpos.y); + return endpos.y - pagerpos.y; +} + +static void +start_paging(GtkTextView *textview) +{ + currently_paging = TRUE; + g_signal_handler_unblock(textview, expose_handler); + g_signal_handler_unblock(textview, pager_handler); +} + +static void +stop_paging(GtkTextView *textview) +{ + currently_paging = FALSE; + g_signal_handler_block(textview, expose_handler); + g_signal_handler_block(textview, pager_handler); +} + +static void +after_insert(GtkTextBuffer *buffer, GtkTextIter *location, gchar *text, gint len, GtkTextView *textview) +{ + while(gtk_events_pending()) + gtk_main_iteration(); + + /* Move the pager to the last visible character in the buffer */ + gint scroll_distance = move_pager_and_get_scroll_distance(textview); + /* Wait for a keypress to advance the pager */ - if(endpos.y > pagerpos.y) - g_signal_handler_unblock(textview, pager_handler); + if(scroll_distance > 0 && !currently_paging) + start_paging(textview); } static gboolean pager_wait(GtkTextView *textview, GdkEventKey *event, GtkTextBuffer *buffer) { - GdkRectangle pagerpos, endpos, visiblerect; - GtkTextIter pager, end; GtkTextMark *pagermark = gtk_text_buffer_get_mark(buffer, "pager_position"); gtk_text_view_scroll_to_mark(textview, pagermark, 0.0, TRUE, 0.0, 0.0); + /*** ALTERNATIVE, POSSIBLY BETTER, METHOD OF SCROLLING *** + GtkWidget *scrolledwindow = gtk_widget_get_parent(GTK_WIDGET(textview)); + GtkAdjustment *adjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(scrolledwindow)); + gdouble page_size; // SUCKY_DEBIAN: use gtk_adjustment_get_page_size() post 2.12 + g_object_get(adjustment, "page-size", &page_size, NULL); + gtk_adjustment_set_value(adjustment, gtk_adjustment_get_value(adjustment) + page_size); + */ + while(gtk_events_pending()) gtk_main_iteration(); /* Move the pager to the last visible character in the buffer */ - gtk_text_view_get_line_at_y(textview, &pager, visiblerect.y, NULL); - if(!gtk_text_iter_ends_line(&pager)) - gtk_text_iter_forward_to_line_end(&pager); - gtk_text_buffer_move_mark(buffer, pagermark, &pager); + gint scroll_distance = move_pager_and_get_scroll_distance(textview); - gtk_text_buffer_get_end_iter(buffer, &end); - gtk_text_view_get_visible_rect(textview, &visiblerect); - gtk_text_view_get_iter_location(textview, &pager, &pagerpos); - gtk_text_view_get_iter_location(textview, &end, &endpos); + if(scroll_distance == 0) + stop_paging(textview); + + return TRUE; /* block further handlers */ +} + +static gboolean +expose_prompt(GtkTextView *textview, GdkEventExpose *event) +{ + /* Use Cairo? Cairo supported on Iliad? */ + PangoLayout *prompt = gtk_widget_create_pango_layout(GTK_WIDGET(textview), "More"); + gint promptwidth, promptheight; + pango_layout_get_pixel_size(prompt, &promptwidth, &promptheight); - g_printerr("View height = %d\n", visiblerect.height); - g_printerr("End - Pager = %d\n", endpos.y - pagerpos.y); + GdkGC *context = gdk_gc_new(GDK_DRAWABLE(event->window)); + GdkColor red, white; + gdk_color_parse("red", &red); + gdk_color_parse("white", &white); - if(endpos.y == pagerpos.y) - g_signal_handler_block(textview, pager_handler); + gint winx, winy, winwidth, winheight; + gdk_window_get_position(event->window, &winx, &winy); + gdk_drawable_get_size(GDK_DRAWABLE(event->window), &winwidth, &winheight); - return TRUE; /* block further handlers */ + gdk_draw_layout_with_colors(event->window, context, + winx + winwidth - promptwidth, + winy + winheight - promptheight, + prompt, &white, &red); + + return FALSE; /* Propagate event further */ } int @@ -106,11 +151,16 @@ main(int argc, char **argv) gtk_box_pack_start(GTK_BOX(vbox), scrolledwindow, TRUE, TRUE, 0); gtk_container_add(GTK_CONTAINER(window), vbox); gtk_widget_show_all(window); + + /* Set up the textview widget to receive exposure events, must be done after widget has been shown */ + gdk_window_set_events(gtk_widget_get_window(textview), GDK_EXPOSURE_MASK); GtkTextBuffer *buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); g_signal_connect_after(buffer, "insert-text", G_CALLBACK(after_insert), textview); pager_handler = g_signal_connect(textview, "key-press-event", G_CALLBACK(pager_wait), buffer); g_signal_handler_block(textview, pager_handler); + expose_handler = g_signal_connect_after(textview, "expose-event", G_CALLBACK(expose_prompt), NULL); + g_signal_handler_block(textview, expose_handler); GtkTextIter end; gtk_text_buffer_get_end_iter(buffer, &end); -- 2.30.2