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.
10 /* Scroll to the end of the buffer.
13 scroll_to_end (GtkTextView *textview)
15 GtkTextBuffer *buffer;
21 buffer = gtk_text_view_get_buffer (textview);
23 /* Get "end" mark. It's located at the end of buffer because
26 mark = gtk_text_buffer_get_mark (buffer, "end");
27 gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark);
29 /* and insert some text at its position, the iter will be
30 * revalidated after insertion to point to the end of inserted text
32 spaces = g_strnfill (count++, ' ');
33 gtk_text_buffer_insert (buffer, &iter, "\n", -1);
34 gtk_text_buffer_insert (buffer, &iter, spaces, -1);
35 gtk_text_buffer_insert (buffer, &iter,
36 "Scroll to end scroll to end scroll "
37 "to end scroll to end ",
41 /* Now scroll the end mark onscreen.
43 gtk_text_view_scroll_mark_onscreen (textview, mark);
45 /* Emulate typewriter behavior, shift to the left if we
46 * are far enough to the right.
51 return G_SOURCE_CONTINUE;
54 /* Scroll to the bottom of the buffer.
57 scroll_to_bottom (GtkTextView *textview)
59 GtkTextBuffer *buffer;
65 buffer = gtk_text_view_get_buffer (textview);
67 /* Get end iterator */
68 gtk_text_buffer_get_end_iter (buffer, &iter);
70 /* and insert some text at it, the iter will be revalidated
71 * after insertion to point to the end of inserted text
73 spaces = g_strnfill (count++, ' ');
74 gtk_text_buffer_insert (buffer, &iter, "\n", -1);
75 gtk_text_buffer_insert (buffer, &iter, spaces, -1);
76 gtk_text_buffer_insert (buffer, &iter,
77 "Scroll to bottom scroll to bottom scroll "
78 "to bottom scroll to bottom",
82 /* Move the iterator to the beginning of line, so we don't scroll
83 * in horizontal direction
85 gtk_text_iter_set_line_offset (&iter, 0);
87 /* and place the mark at iter. the mark will stay there after we
88 * insert some text at the end because it has right gravity.
90 mark = gtk_text_buffer_get_mark (buffer, "scroll");
91 gtk_text_buffer_move_mark (buffer, mark, &iter);
93 /* Scroll the mark onscreen.
95 gtk_text_view_scroll_mark_onscreen (textview, mark);
97 /* Shift text back if we got enough to the right.
102 return G_SOURCE_CONTINUE;
106 setup_scroll (GtkTextView *textview,
109 GtkTextBuffer *buffer;
112 buffer = gtk_text_view_get_buffer (textview);
113 gtk_text_buffer_get_end_iter (buffer, &iter);
117 /* If we want to scroll to the end, including horizontal scrolling,
118 * then we just create a mark with right gravity at the end of the
119 * buffer. It will stay at the end unless explicitely moved with
120 * gtk_text_buffer_move_mark.
122 gtk_text_buffer_create_mark (buffer, "end", &iter, FALSE);
124 /* Add scrolling timeout. */
125 return g_timeout_add (50, (GSourceFunc) scroll_to_end, textview);
129 /* If we want to scroll to the bottom, but not scroll horizontally,
130 * then an end mark won't do the job. Just create a mark so we can
131 * use it with gtk_text_view_scroll_mark_onscreen, we'll position it
132 * explicitely when needed. Use left gravity so the mark stays where
133 * we put it after inserting new text.
135 gtk_text_buffer_create_mark (buffer, "scroll", &iter, TRUE);
137 /* Add scrolling timeout. */
138 return g_timeout_add (100, (GSourceFunc) scroll_to_bottom, textview);
143 remove_timeout (GtkWidget *window,
146 g_source_remove (GPOINTER_TO_UINT (timeout));
150 create_text_view (GtkWidget *hbox,
157 swindow = gtk_scrolled_window_new (NULL, NULL);
158 gtk_box_pack_start (GTK_BOX (hbox), swindow, TRUE, TRUE, 0);
159 textview = gtk_text_view_new ();
160 gtk_container_add (GTK_CONTAINER (swindow), textview);
162 timeout = setup_scroll (GTK_TEXT_VIEW (textview), to_end);
164 /* Remove the timeout in destroy handler, so we don't try to
165 * scroll destroyed widget.
167 g_signal_connect (textview, "destroy",
168 G_CALLBACK (remove_timeout),
169 GUINT_TO_POINTER (timeout));
173 do_textscroll (GtkWidget *do_widget)
175 static GtkWidget *window = NULL;
181 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
182 g_signal_connect (window, "destroy",
183 G_CALLBACK (gtk_widget_destroyed), &window);
184 gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
186 hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
187 gtk_box_set_homogeneous (GTK_BOX (hbox), TRUE);
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);