13.7. A TextView Example

The testtext.py example program (derived from the testtext.c program included in the GTK+ 2.0.x distribution) demonstrates the use of the TextView widget and its associated objects: TextBuffers, TextIters, TextMarks, TextTags, TextTagTables. Figure 13.2, “TextView Example” illustrates its operation:

Figure 13.2. TextView Example

TextView Example

The testtext.py program defines a number of classes in addition to the application class TestText:

The color cycle display is implemented by using text tags applied to a section of text in a buffer. Lines 109-115 (in the __init__() method) create these tags and lines 763-784 (do_apply_colors() method) apply the color tags to a section of text two characters at a time. Lines 202-239 provide the methods (color_cycle_timeout(), set_colors() and cycle_colors()) that produce the color cycle display when enabled. Color cycling is enabled by setting (line 220) the foreground_gdk property of the individual color_tags (which also sets the foreground_set property). Color cycling is disabled by setting the foreground_set property to FALSE (line 222). The colors are periodically changed by shifting the start_hue (line 237)

A new Buffer is filled with example content when the Test->Example menu item is selected (the fill_example_buffer() method in lines 302-372). The example buffer contains text of various colors, styles and languages and pixbufs. The init_tags() method (lines 260-300) sets up a variety of TextTags for use with the example text. The event signal of these tags is connected to the tag_event_handler() method (lines 241-256) to illustrate button and motion event capture.

The TextView wrap mode is set to WRAP_WORD (line 580) and the TextView border windows are displayed by setting their sizes in lines 587-588 and line 596-597. The left and right border windows are used to display line numbers and the top and bottom border windows display the tab locations when custom tabs are set. The border windows are updated when an "expose-event" signal is received by the TextView (lines 590 and 599). The line_numbers_expose() method (lines 1079-1116) determines whether the left or right border window has an expose event and if so calculates the size of the expose area. Then the location of the line start and the line number for each line in the exposed area is calculated in the get_lines() method (lines 1057-1077). The line numbers are then drawn in the border window at the location (transformed by line 1109).

The custom tab locations are displayed in the top and bottom border windows in a similar fashion (lines 1013-1055). They are displayed only when the cursor is moved inside a range of text that has the custom tab attribute set. This is detected by handling the "mark-set" signal in the cursor_set_handler() method (lines 999-1011) and invalidating the top and bottom border windows if the mark set is the insert mark.

Movable widgets are added to a View with the do_add_children() method (lines 892-899) which calls the add_movable_children() method (lines 874-890). The children are gtk.Labels that can be dragged around inside the various windows that are part of a TextView widget.

Likewise, widgets are added to the TextView windows of a View and the Buffer by using the do_add_focus_children() method (lines 901-949).