summaryrefslogtreecommitdiff
path: root/demos
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2006-08-26 02:44:39 +0000
committerMatthias Clasen <matthiasc@src.gnome.org>2006-08-26 02:44:39 +0000
commit482f74d63619922db07d5ad90290fa910b44e18a (patch)
tree5b5437238c658a7aab2dda4f7812b6218b9cd4ba /demos
parent063ff75ae54239946bf0948ffbe10ff1ba91efe5 (diff)
downloadgdk-pixbuf-482f74d63619922db07d5ad90290fa910b44e18a.tar.gz
Add an example of automatic scrolling, thanks to Yevgen Muntyan. (#351206)
2006-08-25 Matthias Clasen <mclasen@redhat.com> * demos/gtk-demo/Makefile.am: * demos/gtk-demo/textscroll.c: Add an example of automatic scrolling, thanks to Yevgen Muntyan. (#351206)
Diffstat (limited to 'demos')
-rw-r--r--demos/gtk-demo/Makefile.am1
-rw-r--r--demos/gtk-demo/textscroll.c202
2 files changed, 203 insertions, 0 deletions
diff --git a/demos/gtk-demo/Makefile.am b/demos/gtk-demo/Makefile.am
index e1adb57b6..f043ee0f4 100644
--- a/demos/gtk-demo/Makefile.am
+++ b/demos/gtk-demo/Makefile.am
@@ -31,6 +31,7 @@ demos = \
sizegroup.c \
stock_browser.c \
textview.c \
+ textscroll.c \
tree_store.c \
ui_manager.c
diff --git a/demos/gtk-demo/textscroll.c b/demos/gtk-demo/textscroll.c
new file mode 100644
index 000000000..063322141
--- /dev/null
+++ b/demos/gtk-demo/textscroll.c
@@ -0,0 +1,202 @@
+/* Text Widget/Automatic scrolling
+ *
+ * This example demonstrates how to use the gravity of
+ * GtkTextMarks to keep a text view scrolled to the bottom
+ * while appending text.
+ */
+
+#include <gtk/gtk.h>
+#include "demo-common.h"
+
+/* Scroll to the end of the buffer.
+ */
+static gboolean
+scroll_to_end (GtkTextView *textview)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter iter;
+ GtkTextMark *mark;
+ char *spaces;
+ static int count;
+
+ buffer = gtk_text_view_get_buffer (textview);
+
+ /* Get "end" mark. It's located at the end of buffer because
+ * of right gravity
+ */
+ mark = gtk_text_buffer_get_mark (buffer, "end");
+ gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark);
+
+ /* and insert some text at its position, the iter will be
+ * revalidated after insertion to point to the end of inserted text
+ */
+ spaces = g_strnfill (count++, ' ');
+ gtk_text_buffer_insert (buffer, &iter, "\n", -1);
+ gtk_text_buffer_insert (buffer, &iter, spaces, -1);
+ gtk_text_buffer_insert (buffer, &iter,
+ "Scroll to end scroll to end scroll "
+ "to end scroll to end ",
+ -1);
+ g_free (spaces);
+
+ /* Now scroll the end mark onscreen.
+ */
+ gtk_text_view_scroll_mark_onscreen (textview, mark);
+
+ /* Emulate typewriter behavior, shift to the left if we
+ * are far enough to the right.
+ */
+ if (count > 150)
+ count = 0;
+
+ return TRUE;
+}
+
+/* Scroll to the bottom of the buffer.
+ */
+static gboolean
+scroll_to_bottom (GtkTextView *textview)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter iter;
+ GtkTextMark *mark;
+ char *spaces;
+ static int count;
+
+ buffer = gtk_text_view_get_buffer (textview);
+
+ /* Get end iterator */
+ gtk_text_buffer_get_end_iter (buffer, &iter);
+
+ /* and insert some text at it, the iter will be revalidated
+ * after insertion to point to the end of inserted text
+ */
+ spaces = g_strnfill (count++, ' ');
+ gtk_text_buffer_insert (buffer, &iter, "\n", -1);
+ gtk_text_buffer_insert (buffer, &iter, spaces, -1);
+ gtk_text_buffer_insert (buffer, &iter,
+ "Scroll to bottom scroll to bottom scroll "
+ "to bottom scroll to bottom",
+ -1);
+ g_free (spaces);
+
+ /* Move the iterator to the beginning of line, so we don't scroll
+ * in horizontal direction
+ */
+ gtk_text_iter_set_line_offset (&iter, 0);
+
+ /* and place the mark at iter. the mark will stay there after we
+ * insert some text at the end because it has right gravity.
+ */
+ mark = gtk_text_buffer_get_mark (buffer, "scroll");
+ gtk_text_buffer_move_mark (buffer, mark, &iter);
+
+ /* Scroll the mark onscreen.
+ */
+ gtk_text_view_scroll_mark_onscreen (textview, mark);
+
+ /* Shift text back if we got enough to the right.
+ */
+ if (count > 40)
+ count = 0;
+
+ return TRUE;
+}
+
+static guint
+setup_scroll (GtkTextView *textview,
+ gboolean to_end)
+{
+ GtkTextBuffer *buffer;
+ GtkTextIter iter;
+ GtkTextMark *mark;
+
+ buffer = gtk_text_view_get_buffer (textview);
+ gtk_text_buffer_get_end_iter (buffer, &iter);
+
+ if (to_end)
+ {
+ /* If we want to scroll to the end, including horizontal scrolling,
+ * then we just create a mark with right gravity at the end of the
+ * buffer. It will stay at the end unless explicitely moved with
+ * gtk_text_buffer_move_mark.
+ */
+ gtk_text_buffer_create_mark (buffer, "end", &iter, FALSE);
+
+ /* Add scrolling timeout. */
+ return g_timeout_add (50, (GSourceFunc) scroll_to_end, textview);
+ }
+ else
+ {
+ /* If we want to scroll to the bottom, but not scroll horizontally,
+ * then an end mark won't do the job. Just create a mark so we can
+ * use it with gtk_text_view_scroll_mark_onscreen, we'll position it
+ * explicitely when needed. Use left gravity so the mark stays where
+ * we put it after inserting new text.
+ */
+ gtk_text_buffer_create_mark (buffer, "scroll", &iter, TRUE);
+
+ /* Add scrolling timeout. */
+ return g_timeout_add (100, (GSourceFunc) scroll_to_bottom, textview);
+ }
+}
+
+static void
+remove_timeout (GtkWidget *window,
+ gpointer timeout)
+{
+ g_source_remove (GPOINTER_TO_UINT (timeout));
+}
+
+static void
+create_text_view (GtkWidget *hbox,
+ gboolean to_end)
+{
+ GtkWidget *swindow;
+ GtkWidget *textview;
+ guint timeout;
+
+ swindow = gtk_scrolled_window_new (NULL, NULL);
+ gtk_box_pack_start_defaults (GTK_BOX (hbox), swindow);
+ textview = gtk_text_view_new ();
+ gtk_container_add (GTK_CONTAINER (swindow), textview);
+
+ timeout = setup_scroll (GTK_TEXT_VIEW (textview), to_end);
+
+ /* Remove the timeout in destroy handler, so we don't try to
+ * scroll destroyed widget.
+ */
+ g_signal_connect (textview, "destroy",
+ G_CALLBACK (remove_timeout),
+ GUINT_TO_POINTER (timeout));
+}
+
+GtkWidget *
+do_textscroll (GtkWidget *do_widget)
+{
+ static GtkWidget *window = NULL;
+
+ if (!window)
+ {
+ GtkWidget *hbox;
+ GtkWidget *swindow;
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ g_signal_connect (window, "destroy",
+ G_CALLBACK (gtk_widget_destroyed), &window);
+ gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
+
+ hbox = gtk_hbox_new (TRUE, 6);
+ gtk_container_add (GTK_CONTAINER (window), hbox);
+
+ create_text_view (hbox, TRUE);
+ create_text_view (hbox, FALSE);
+ }
+
+ if (!GTK_WIDGET_VISIBLE (window))
+ gtk_widget_show_all (window);
+ else
+ gtk_widget_destroy (window);
+
+ return window;
+}