Pager!
authorfliep <fliep@ddfedd41-794f-dd11-ae45-00112f111e67>
Thu, 24 Dec 2009 12:48:45 +0000 (12:48 +0000)
committerfliep <fliep@ddfedd41-794f-dd11-ae45-00112f111e67>
Thu, 24 Dec 2009 12:48:45 +0000 (12:48 +0000)
tests/barf.c

index f211210a33ee0904a6f1bf6d6832be3d82c0820b..0bf2a93f186a2357714f384bc6534769c15df368 100644 (file)
@@ -5,7 +5,9 @@
 
 #include <gtk/gtk.h>
 
-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);