1 /* Text Widget/Automatic scrolling
3 * This example demonstrates how to use the gravity of
4 * GtkTextMarks to keep a text view scrolled to the bottom
5 * while appending text.
9 #include "demo-common.h"
11 /* Scroll to the end of the buffer.
14 scroll_to_end (GtkTextView *textview)
16 GtkTextBuffer *buffer;
22 buffer = gtk_text_view_get_buffer (textview);
24 /* Get "end" mark. It's located at the end of buffer because
27 mark = gtk_text_buffer_get_mark (buffer, "end");
28 gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark);
30 /* and insert some text at its position, the iter will be
31 * revalidated after insertion to point to the end of inserted text
33 spaces = g_strnfill (count++, ' ');
34 gtk_text_buffer_insert (buffer, &iter, "\n", -1);
35 gtk_text_buffer_insert (buffer, &iter, spaces, -1);
36 gtk_text_buffer_insert (buffer, &iter,
37 "Scroll to end scroll to end scroll "
38 "to end scroll to end ",
42 /* Now scroll the end mark onscreen.
44 gtk_text_view_scroll_mark_onscreen (textview, mark);
46 /* Emulate typewriter behavior, shift to the left if we
47 * are far enough to the right.
55 /* Scroll to the bottom of the buffer.
58 scroll_to_bottom (GtkTextView *textview)
60 GtkTextBuffer *buffer;
66 buffer = gtk_text_view_get_buffer (textview);
68 /* Get end iterator */
69 gtk_text_buffer_get_end_iter (buffer, &iter);
71 /* and insert some text at it, the iter will be revalidated
72 * after insertion to point to the end of inserted text
74 spaces = g_strnfill (count++, ' ');
75 gtk_text_buffer_insert (buffer, &iter, "\n", -1);
76 gtk_text_buffer_insert (buffer, &iter, spaces, -1);
77 gtk_text_buffer_insert (buffer, &iter,
78 "Scroll to bottom scroll to bottom scroll "
79 "to bottom scroll to bottom",
83 /* Move the iterator to the beginning of line, so we don't scroll
84 * in horizontal direction
86 gtk_text_iter_set_line_offset (&iter, 0);
88 /* and place the mark at iter. the mark will stay there after we
89 * insert some text at the end because it has right gravity.
91 mark = gtk_text_buffer_get_mark (buffer, "scroll");
92 gtk_text_buffer_move_mark (buffer, mark, &iter);
94 /* Scroll the mark onscreen.
96 gtk_text_view_scroll_mark_onscreen (textview, mark);
98 /* Shift text back if we got enough to the right.
107 setup_scroll (GtkTextView *textview,
110 GtkTextBuffer *buffer;
113 buffer = gtk_text_view_get_buffer (textview);
114 gtk_text_buffer_get_end_iter (buffer, &iter);
118 /* If we want to scroll to the end, including horizontal scrolling,
119 * then we just create a mark with right gravity at the end of the
120 * buffer. It will stay at the end unless explicitely moved with
121 * gtk_text_buffer_move_mark.
123 gtk_text_buffer_create_mark (buffer, "end", &iter, FALSE);
125 /* Add scrolling timeout. */
126 return g_timeout_add (50, (GSourceFunc) scroll_to_end, textview);
130 /* If we want to scroll to the bottom, but not scroll horizontally,
131 * then an end mark won't do the job. Just create a mark so we can
132 * use it with gtk_text_view_scroll_mark_onscreen, we'll position it
133 * explicitely when needed. Use left gravity so the mark stays where
134 * we put it after inserting new text.
136 gtk_text_buffer_create_mark (buffer, "scroll", &iter, TRUE);
138 /* Add scrolling timeout. */
139 return g_timeout_add (100, (GSourceFunc) scroll_to_bottom, textview);
144 remove_timeout (GtkWidget *window,
147 g_source_remove (GPOINTER_TO_UINT (timeout));
151 create_text_view (GtkWidget *hbox,
158 swindow = gtk_scrolled_window_new (NULL, NULL);
159 gtk_box_pack_start (GTK_BOX (hbox), swindow, TRUE, TRUE, 0);
160 textview = gtk_text_view_new ();
161 gtk_container_add (GTK_CONTAINER (swindow), textview);
163 timeout = setup_scroll (GTK_TEXT_VIEW (textview), to_end);
165 /* Remove the timeout in destroy handler, so we don't try to
166 * scroll destroyed widget.
168 g_signal_connect (textview, "destroy",
169 G_CALLBACK (remove_timeout),
170 GUINT_TO_POINTER (timeout));
174 do_textscroll (GtkWidget *do_widget)
176 static GtkWidget *window = NULL;
182 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
183 g_signal_connect (window, "destroy",
184 G_CALLBACK (gtk_widget_destroyed), &window);
185 gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
187 hbox = gtk_hbox_new (TRUE, 6);
188 gtk_container_add (GTK_CONTAINER (window), hbox);
190 create_text_view (hbox, TRUE);
191 create_text_view (hbox, FALSE);
194 if (!gtk_widget_get_visible (window))
195 gtk_widget_show_all (window);
197 gtk_widget_destroy (window);