|
Packit Service |
fb6fa5 |
/* Text Widget/Automatic scrolling
|
|
Packit Service |
fb6fa5 |
*
|
|
Packit Service |
fb6fa5 |
* This example demonstrates how to use the gravity of
|
|
Packit Service |
fb6fa5 |
* GtkTextMarks to keep a text view scrolled to the bottom
|
|
Packit Service |
fb6fa5 |
* while appending text.
|
|
Packit Service |
fb6fa5 |
*/
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
#include <gtk/gtk.h>
|
|
Packit Service |
fb6fa5 |
#include "demo-common.h"
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
/* Scroll to the end of the buffer.
|
|
Packit Service |
fb6fa5 |
*/
|
|
Packit Service |
fb6fa5 |
static gboolean
|
|
Packit Service |
fb6fa5 |
scroll_to_end (GtkTextView *textview)
|
|
Packit Service |
fb6fa5 |
{
|
|
Packit Service |
fb6fa5 |
GtkTextBuffer *buffer;
|
|
Packit Service |
fb6fa5 |
GtkTextIter iter;
|
|
Packit Service |
fb6fa5 |
GtkTextMark *mark;
|
|
Packit Service |
fb6fa5 |
char *spaces;
|
|
Packit Service |
fb6fa5 |
static int count;
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
buffer = gtk_text_view_get_buffer (textview);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
/* Get "end" mark. It's located at the end of buffer because
|
|
Packit Service |
fb6fa5 |
* of right gravity
|
|
Packit Service |
fb6fa5 |
*/
|
|
Packit Service |
fb6fa5 |
mark = gtk_text_buffer_get_mark (buffer, "end");
|
|
Packit Service |
fb6fa5 |
gtk_text_buffer_get_iter_at_mark (buffer, &iter, mark);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
/* and insert some text at its position, the iter will be
|
|
Packit Service |
fb6fa5 |
* revalidated after insertion to point to the end of inserted text
|
|
Packit Service |
fb6fa5 |
*/
|
|
Packit Service |
fb6fa5 |
spaces = g_strnfill (count++, ' ');
|
|
Packit Service |
fb6fa5 |
gtk_text_buffer_insert (buffer, &iter, "\n", -1);
|
|
Packit Service |
fb6fa5 |
gtk_text_buffer_insert (buffer, &iter, spaces, -1);
|
|
Packit Service |
fb6fa5 |
gtk_text_buffer_insert (buffer, &iter,
|
|
Packit Service |
fb6fa5 |
"Scroll to end scroll to end scroll "
|
|
Packit Service |
fb6fa5 |
"to end scroll to end ",
|
|
Packit Service |
fb6fa5 |
-1);
|
|
Packit Service |
fb6fa5 |
g_free (spaces);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
/* Now scroll the end mark onscreen.
|
|
Packit Service |
fb6fa5 |
*/
|
|
Packit Service |
fb6fa5 |
gtk_text_view_scroll_mark_onscreen (textview, mark);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
/* Emulate typewriter behavior, shift to the left if we
|
|
Packit Service |
fb6fa5 |
* are far enough to the right.
|
|
Packit Service |
fb6fa5 |
*/
|
|
Packit Service |
fb6fa5 |
if (count > 150)
|
|
Packit Service |
fb6fa5 |
count = 0;
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
return TRUE;
|
|
Packit Service |
fb6fa5 |
}
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
/* Scroll to the bottom of the buffer.
|
|
Packit Service |
fb6fa5 |
*/
|
|
Packit Service |
fb6fa5 |
static gboolean
|
|
Packit Service |
fb6fa5 |
scroll_to_bottom (GtkTextView *textview)
|
|
Packit Service |
fb6fa5 |
{
|
|
Packit Service |
fb6fa5 |
GtkTextBuffer *buffer;
|
|
Packit Service |
fb6fa5 |
GtkTextIter iter;
|
|
Packit Service |
fb6fa5 |
GtkTextMark *mark;
|
|
Packit Service |
fb6fa5 |
char *spaces;
|
|
Packit Service |
fb6fa5 |
static int count;
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
buffer = gtk_text_view_get_buffer (textview);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
/* Get end iterator */
|
|
Packit Service |
fb6fa5 |
gtk_text_buffer_get_end_iter (buffer, &iter);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
/* and insert some text at it, the iter will be revalidated
|
|
Packit Service |
fb6fa5 |
* after insertion to point to the end of inserted text
|
|
Packit Service |
fb6fa5 |
*/
|
|
Packit Service |
fb6fa5 |
spaces = g_strnfill (count++, ' ');
|
|
Packit Service |
fb6fa5 |
gtk_text_buffer_insert (buffer, &iter, "\n", -1);
|
|
Packit Service |
fb6fa5 |
gtk_text_buffer_insert (buffer, &iter, spaces, -1);
|
|
Packit Service |
fb6fa5 |
gtk_text_buffer_insert (buffer, &iter,
|
|
Packit Service |
fb6fa5 |
"Scroll to bottom scroll to bottom scroll "
|
|
Packit Service |
fb6fa5 |
"to bottom scroll to bottom",
|
|
Packit Service |
fb6fa5 |
-1);
|
|
Packit Service |
fb6fa5 |
g_free (spaces);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
/* Move the iterator to the beginning of line, so we don't scroll
|
|
Packit Service |
fb6fa5 |
* in horizontal direction
|
|
Packit Service |
fb6fa5 |
*/
|
|
Packit Service |
fb6fa5 |
gtk_text_iter_set_line_offset (&iter, 0);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
/* and place the mark at iter. the mark will stay there after we
|
|
Packit Service |
fb6fa5 |
* insert some text at the end because it has right gravity.
|
|
Packit Service |
fb6fa5 |
*/
|
|
Packit Service |
fb6fa5 |
mark = gtk_text_buffer_get_mark (buffer, "scroll");
|
|
Packit Service |
fb6fa5 |
gtk_text_buffer_move_mark (buffer, mark, &iter);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
/* Scroll the mark onscreen.
|
|
Packit Service |
fb6fa5 |
*/
|
|
Packit Service |
fb6fa5 |
gtk_text_view_scroll_mark_onscreen (textview, mark);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
/* Shift text back if we got enough to the right.
|
|
Packit Service |
fb6fa5 |
*/
|
|
Packit Service |
fb6fa5 |
if (count > 40)
|
|
Packit Service |
fb6fa5 |
count = 0;
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
return TRUE;
|
|
Packit Service |
fb6fa5 |
}
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
static guint
|
|
Packit Service |
fb6fa5 |
setup_scroll (GtkTextView *textview,
|
|
Packit Service |
fb6fa5 |
gboolean to_end)
|
|
Packit Service |
fb6fa5 |
{
|
|
Packit Service |
fb6fa5 |
GtkTextBuffer *buffer;
|
|
Packit Service |
fb6fa5 |
GtkTextIter iter;
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
buffer = gtk_text_view_get_buffer (textview);
|
|
Packit Service |
fb6fa5 |
gtk_text_buffer_get_end_iter (buffer, &iter);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
if (to_end)
|
|
Packit Service |
fb6fa5 |
{
|
|
Packit Service |
fb6fa5 |
/* If we want to scroll to the end, including horizontal scrolling,
|
|
Packit Service |
fb6fa5 |
* then we just create a mark with right gravity at the end of the
|
|
Packit Service |
fb6fa5 |
* buffer. It will stay at the end unless explicitely moved with
|
|
Packit Service |
fb6fa5 |
* gtk_text_buffer_move_mark.
|
|
Packit Service |
fb6fa5 |
*/
|
|
Packit Service |
fb6fa5 |
gtk_text_buffer_create_mark (buffer, "end", &iter, FALSE);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
/* Add scrolling timeout. */
|
|
Packit Service |
fb6fa5 |
return g_timeout_add (50, (GSourceFunc) scroll_to_end, textview);
|
|
Packit Service |
fb6fa5 |
}
|
|
Packit Service |
fb6fa5 |
else
|
|
Packit Service |
fb6fa5 |
{
|
|
Packit Service |
fb6fa5 |
/* If we want to scroll to the bottom, but not scroll horizontally,
|
|
Packit Service |
fb6fa5 |
* then an end mark won't do the job. Just create a mark so we can
|
|
Packit Service |
fb6fa5 |
* use it with gtk_text_view_scroll_mark_onscreen, we'll position it
|
|
Packit Service |
fb6fa5 |
* explicitely when needed. Use left gravity so the mark stays where
|
|
Packit Service |
fb6fa5 |
* we put it after inserting new text.
|
|
Packit Service |
fb6fa5 |
*/
|
|
Packit Service |
fb6fa5 |
gtk_text_buffer_create_mark (buffer, "scroll", &iter, TRUE);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
/* Add scrolling timeout. */
|
|
Packit Service |
fb6fa5 |
return g_timeout_add (100, (GSourceFunc) scroll_to_bottom, textview);
|
|
Packit Service |
fb6fa5 |
}
|
|
Packit Service |
fb6fa5 |
}
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
static void
|
|
Packit Service |
fb6fa5 |
remove_timeout (GtkWidget *window,
|
|
Packit Service |
fb6fa5 |
gpointer timeout)
|
|
Packit Service |
fb6fa5 |
{
|
|
Packit Service |
fb6fa5 |
g_source_remove (GPOINTER_TO_UINT (timeout));
|
|
Packit Service |
fb6fa5 |
}
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
static void
|
|
Packit Service |
fb6fa5 |
create_text_view (GtkWidget *hbox,
|
|
Packit Service |
fb6fa5 |
gboolean to_end)
|
|
Packit Service |
fb6fa5 |
{
|
|
Packit Service |
fb6fa5 |
GtkWidget *swindow;
|
|
Packit Service |
fb6fa5 |
GtkWidget *textview;
|
|
Packit Service |
fb6fa5 |
guint timeout;
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
swindow = gtk_scrolled_window_new (NULL, NULL);
|
|
Packit Service |
fb6fa5 |
gtk_box_pack_start (GTK_BOX (hbox), swindow, TRUE, TRUE, 0);
|
|
Packit Service |
fb6fa5 |
textview = gtk_text_view_new ();
|
|
Packit Service |
fb6fa5 |
gtk_container_add (GTK_CONTAINER (swindow), textview);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
timeout = setup_scroll (GTK_TEXT_VIEW (textview), to_end);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
/* Remove the timeout in destroy handler, so we don't try to
|
|
Packit Service |
fb6fa5 |
* scroll destroyed widget.
|
|
Packit Service |
fb6fa5 |
*/
|
|
Packit Service |
fb6fa5 |
g_signal_connect (textview, "destroy",
|
|
Packit Service |
fb6fa5 |
G_CALLBACK (remove_timeout),
|
|
Packit Service |
fb6fa5 |
GUINT_TO_POINTER (timeout));
|
|
Packit Service |
fb6fa5 |
}
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
GtkWidget *
|
|
Packit Service |
fb6fa5 |
do_textscroll (GtkWidget *do_widget)
|
|
Packit Service |
fb6fa5 |
{
|
|
Packit Service |
fb6fa5 |
static GtkWidget *window = NULL;
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
if (!window)
|
|
Packit Service |
fb6fa5 |
{
|
|
Packit Service |
fb6fa5 |
GtkWidget *hbox;
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
|
Packit Service |
fb6fa5 |
g_signal_connect (window, "destroy",
|
|
Packit Service |
fb6fa5 |
G_CALLBACK (gtk_widget_destroyed), &window);
|
|
Packit Service |
fb6fa5 |
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
hbox = gtk_hbox_new (TRUE, 6);
|
|
Packit Service |
fb6fa5 |
gtk_container_add (GTK_CONTAINER (window), hbox);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
create_text_view (hbox, TRUE);
|
|
Packit Service |
fb6fa5 |
create_text_view (hbox, FALSE);
|
|
Packit Service |
fb6fa5 |
}
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
if (!gtk_widget_get_visible (window))
|
|
Packit Service |
fb6fa5 |
gtk_widget_show_all (window);
|
|
Packit Service |
fb6fa5 |
else
|
|
Packit Service |
fb6fa5 |
gtk_widget_destroy (window);
|
|
Packit Service |
fb6fa5 |
|
|
Packit Service |
fb6fa5 |
return window;
|
|
Packit Service |
fb6fa5 |
}
|