Chapter 23. Text Widgets

Table of Contents
23.1. Creating and Configuring a Text Box
23.2. Text Manipulation
23.3. Keyboard Shortcuts
23.4. Text Widget Example

Inheritance Hierarchy

Object
   +--- Widget
         +--- Editable
               +--- Text
       

The Text widget allows multiple lines of text to be displayed and edited. It supports both multi-colored and multi-font text, allowing them to be mixed in any way we wish. It also has a wide set of key based text editing commands, which are compatible with the Emacs text editor.

The text widget supports full cut-and-paste facilities, including the use of double-click and triple-click to select a word and a whole line, respectively.

23.1. Creating and Configuring a Text Box

There is only one function for creating a new Text widget.

$text = new Gtk::Text( $hadj, $vadj );

The arguments allow us to give the Text widget adjustments that can be used to track the viewing position of the widget. Passing undefined values to either or both of these arguments will cause the new() function to create its own.

$text->set_adjustments( $hadj, $vadj );

The above function allows the horizontal and vertical adjustments of a text widget to be changed at any time.

The text widget will not automatically create its own scrollbars when the amount of text to be displayed is too long for the display window. We therefore have to create and add them to the display layout ourselves.

$vscrollbar = new Gtk::VScrollbar( $text->vadj );

$hbox->pack_start( $vscrollbar, $false, $false, 0 );

$vscrollbar->show();

The above code snippet creates a new vertical scrollbar, and attaches it to the vertical adjustment of the text widget. It then packs it into a box in the normal way.

Currently the Text widget does not support horizontal scrollbars.

There are two main ways in which a Text widget can be used: to allow the user to edit a body of text, or to allow us to display multiple lines of text to the user. In order for us to switch between these modes of operation, the text widget has the following function:

$text->set_editable( $editable );

The $editable argument is a true or false value that specifies whether the user is permitted to edit the contents of the Text widget. When the text widget is editable, it will display a cursor at the current insertion point.

You are not, however, restricted to just using the text widget in these two modes. You can toggle the editable state of the text widget at any time, and can insert text at any time.

The text widget wraps lines of text that are too long to fit onto a single line of the display window. Its default behaviour is to break words across line breaks. This can be changed using the next function:

$text->set_word_wrap( $word_wrap );

Using this function allows us to specify that the text widget should wrap long lines on word boundaries. The $word_wrap argument is a true or false value.

You can also wrap a line when it reaches the end of the Text widget, disregarding word boundries. This is set using:

$text->set_line_wrap( $line_wrap );

23.2. Text Manipulation

The current insertion point of a Text widget can be set using

$text->set_point( $index );

Where $index is the position to set the insertion point.

Analogous to this is the function for getting the current insertion point:

$text->get_point();

A function that is useful in combination with the above two functions is:

$text->get_length();

which returns the current length of the Text widget. The length is the number of characters that are within the text block of the widget, including characters such as newlines.

In order to insert text at the current insertion point of a Text widget, the function insert() is used, which also allows us to specify background and foreground colors and a font for the text.

$text->insert( $font, $foreground, $background, $string );

Passing an undefined value as the foreground color, background color or font will result in the values set within the widget style to be used.

The text widget is one of the few within GTK that redraws itself dynamically, outside of main Gtk. This means that all changes to the contents of the text widget take effect immediately. This may be undesirable when performing multiple changes to the text widget. In order to allow us to perform multiple updates to the text widget without it continuously redrawing, we can freeze the widget, which temporarily stops it from automatically redrawing itself every time it is changed. We can then thaw the widget after our updates are complete.

The following two functions perform this freeze and thaw action:

$tree->freeze();

$tree->thaw();

Text is deleted from the text widget relative to the current insertion point by the following two functions. The return value is a true or false indicator of whether the operation was successful.

$text->backward_delete( $num_chars );

$text->forward_delete( $num_chars );

If you want to retrieve the contents of the text widget, then use index( $index ), which allows you to retrieve the character at position $index within the text widget.

23.3. Keyboard Shortcuts

The text widget has a number of pre-installed keyboard shortcuts for common editing, motion and selection functions. These are accessed using Control and Alt key combinations.

In addition to these, holding down the Control key while using cursor key movement will move the cursor by words rather than characters. Holding down Shift while using cursor movement will extend the selection.

Motion Shortcuts

Editing Shortcuts

Selection Shortcuts

23.4. Text Widget Example

Text Widget Example Source

      
#!/usr/bin/perl -w

use Gtk;
use strict;

set_locale Gtk;
init Gtk;

my $false = 0;
my $true = 1;

my $line;

my $window;
my $main_vbox;
my $vbox;
my $hbox;
my $button;
my $check;
my $separator;
my $table;
my $vscrollbar;
my $text;
my $cmap;
my $color;
my $fixed_font;


# Create a window
$window = new Gtk::Window( 'toplevel' );
$window->set_usize( 600, 500 );
$window->set_policy( $true, $true, $false );
$window->signal_connect( 'destroy', sub { Gtk->exit( 0 ); } );
$window->set_title( "Text Widget Example" );
$window->border_width( 0 );

$main_vbox = new Gtk::VBox( $false, 0 );
$window->add( $main_vbox );
$main_vbox->show();

$vbox = new Gtk::VBox( $false, 10 );
$vbox->border_width( 10 );
$main_vbox->pack_start( $vbox, $true, $true, 0 );
$vbox->show();

# Create a table
$table = new Gtk::Table( 2, 2, $false );
$table->set_row_spacing( 0, 2 );
$table->set_col_spacing( 0, 2 );
$vbox->pack_start( $table, $true, $true, 0 );
$table->show();

# Create the Text widget
$text = new Gtk::Text( undef, undef );
$text->set_editable( $true );
$table->attach( $text, 0, 1, 0, 1,
		[ 'expand', 'shrink', 'fill' ],
		[ 'expand', 'shrink', 'fill' ],
		0, 0 );
$text->show();

# Add a vertical scrollbar to the GtkText widget
$vscrollbar = new Gtk::VScrollbar( $text->vadj );
$table->attach( $vscrollbar, 1, 2, 0, 1, 'fill',
		[ 'expand', 'shrink', 'fill' ], 0, 0 );
$vscrollbar->show();

# Get the system color map and allocate the color red
$cmap = Gtk::Gdk::Colormap->get_system();
$color->{ 'red' } = 0xFFFF;
$color->{ 'green' } = 0;
$color->{ 'blue' } = 0;

unless ( defined( $cmap->color_alloc( $color ) ) )
{
   warn( "Couldn't allocate color\n" );
}

# Load a fixed font
my $name = "-misc-fixed-medium-r-normal-*-*-140-*-*-c-*-koi8-r";
$fixed_font = Gtk::Gdk::Font->load( $name );

# Realizing a widget creates a window for it, its now ready for us to
# insert some text
$text->realize();

# Freeze the text widget, ready for multiple updates
$text->freeze();

# Insert some colored text
$text->insert( undef, $text->style->black, undef, "Supports " );
$text->insert( undef, $color, undef, "colored " );
$text->insert( undef, $text->style->black, undef, "text and different " );
$text->insert( $fixed_font, $text->style->black, undef, "fonts\n\n" );

# Load the file text (this program) into the text window
open( FILE, "text" );

foreach $line ( <FILE> )
{
   $text->insert( $fixed_font, undef, undef, $line );
}

close( FILE );

# Thaw the text widget, allowing the updates to become visible
$text->thaw();

$hbox = new Gtk::HButtonBox();
$vbox->pack_start( $hbox, $false, $false, 0 );
$hbox->show();

# Create an editable check box
$check = new Gtk::CheckButton( "Editable" );
$hbox->pack_start( $check, $false, $false, 0 );
$check->signal_connect( 'toggled',
			sub { $text->set_editable( $check->active ); } );
$check->set_active( $true );
$check->show();

# Create a word wrap check box
$check = new Gtk::CheckButton( "Wrap Words" );
$hbox->pack_start( $check, $false, $true, 0 );
$check->signal_connect( 'toggled',
			sub { $text->set_word_wrap( $check->active ); } );
$check->set_active( $false );
$check->show();

$separator = new Gtk::HSeparator();
$main_vbox->pack_start( $separator, $false, $true, 0 );
$separator->show();

$vbox = new Gtk::VBox( $false, 10 );
$vbox->border_width( 10 );
$main_vbox->pack_start( $vbox, $false, $true, 0 );
$vbox->show();

# Create a close button
$button = new Gtk::Button( "Close" );
$button->signal_connect( 'clicked', sub { Gtk->exit( 0 ); } );
$vbox->pack_start( $button, $true, $true, 0 );
$button->can_default( $true );
$button->grab_default();
$button->show();

$window->show();
main Gtk;
exit( 0 );



# END EXAMPLE PROGRAM
      
   

Text Example Screenshot