Create  Edit  FrontPage  Index  Search  Changes  History  RSS  Back  Login

tut-gtk2-txtw-textview - History


  • Added words are showed as here.
  • Removed words are showed as here.
= The Text View Widget
{{link "tut-gtk2-txtw-scrolledwin", "tut-gtk2-txtw", "tut-gtk", "tut-gtk2-txtw-itrsmrks"}}

== Text Views

{{image_right("txtw-textview-01.png")}}

The Gtk::TextView widget is used to display multiple lines of a text document. it provides many ways to customize the text within the widget. You can even insert Gdk::Pixbuf objects and other child widgets into a document. Gtk::TextView is the first  reasonably involved widget we've encountered so far and in this session we will explore most of its interesting features. It is a versatile widget that you will exploit in many GTK+ applications.

At the first glance you may think that this widget may only be used  to display simple text, however that is not the case. It can also be used to display many types of rich text, and interactive documents used by a variety of different applications. This is what we will learn here in the following few articles.

Let us start with a simple example of Gtk::TextView widget inside a Gtk::ScrolledWindow widget. This listing illustrates the simplest text view example that you could create:


#!/usr/bin/env ruby
require 'gtk2'

window = Gtk::Window.new(Gtk::Window::TOPLEVEL)
window.resizable = true
window.title = "Text Views"
window.border_width = 10
window.signal_connect('delete_event') { Gtk.main_quit }
window.set_size_request(250, 150)

textview = Gtk::TextView.new
textview.buffer.text = "Your 1st Gtk::TextView widget!"

scrolled_win = Gtk::ScrolledWindow.new
scrolled_win.border_width = 5
scrolled_win.add(textview)
scrolled_win.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS)

window.add(scrolled_win)
window.show_all
Gtk.main

=== Text Buffers


Each text view is used to display the contents of a class called Gtk::TextBuffer. Text buffers are used to store the current state of the container within the text view. You can guess this from the following line in our example program above.

textview.buffer.text = "Your 1st Gtk::TextView widget!"

Here the buffer component is the Gtk::TextBuffer. Text buffers hold text, images, child widgets, text tags and other information necessary for rendering the documents. A Gtk::TextBuffer buffer is an independent object and can be displayed by many text view widgets. However any text view has  only a single text buffer associated with it. Most programmers do not take advantage of this feature but it will become important  latter when you learn how to embed child widgets into a text buffer.

Most new text views are created with the Gtk::TextView.new(buffer=nil). When using this method with the default nil argument an empty Gtk::TextBuffer is created for you. This empty text buffer can be replaced or retrieved by "Gtk::TextView#buffer=(buff)", or "buff = Gtk::TextView#buffer" respectively.

When handling text buffers, you will be dealing with terms such as ((*ofset*)) and ((*index*)). As with all text widgets in GTK+, text is stored in UTF-8 strings, hence individual characters may be more than one byte long. This may effect the overall meaning or value that offset and index will represent.

:CAUTION:
   The word ((*index*)) refers to an individual byte, you need to be careful when stepping through a text buffer in later examples. In particular you can not refer to an index pointing to the position between two characters.

=== Text View Properties

{{image_right("txtw-textview-02.png")}}

Gtk::TextView widget was created to be very versatile. Because of this, many properties are provided for the widget. Let's have a look at another example program demonstrating how properties can be used to customize the text:

{{br}}

#!/usr/bin/env ruby
require 'gtk2'

def destroy; Gtk.main_quit; end

window = Gtk::Window.new(Gtk::Window::TOPLEVEL)
window.resizable = true
window.title = "Text View Properties"
window.border_width = 10
window.signal_connect('delete_event') { destroy }
window.set_size_request(250, 150)

textview = Gtk::TextView.new
font = Pango::FontDescription.new("Monospace Bold 10")
textview.modify_font(font)
textview.wrap_mode = Gtk::TextTag::WRAP_WORD
textview.justification = Gtk::JUSTIFY_RIGHT
textview.editable =  true
textview.cursor_visible =  true
textview.pixels_above_lines = 5
textview.pixels_below_lines = 5
textview.pixels_inside_wrap = 5
textview.left_margin = 10
textview.right_margin = 10
textview.buffer.text = "This is some text!\nChange me!\nPlease!"

scrolled_win = Gtk::ScrolledWindow.new
scrolled_win.border_width = 5
scrolled_win.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS)
scrolled_win.add(textview)

window.add(scrolled_win)
window.show_all
Gtk.main

The following two properties need the reference to GTK+ constants:

textview.wrap_mode = Gtk::TextTag::WRAP_WORD

You can find the constants for the above line at: ((<Gtk::TextTag#GtkWrapMode>))
textview.justification = Gtk::JUSTIFY_RIGHT

And again, you can find the constants for the above line at: ((<Gtk#GtkJustification>))


=== Pango Tab Arrays

{{image_right("txtw-textview-03.png")}}
Tabs added to a text view are set to a default width, but there are times when this is not what you want. GTK+ provides Pango::TabArray object, which can help you define a new tab size. In order to change the tab size you must first calculate the number of horizontal pixels the tab will take up based on the current font. Let us expand our first simple example by adding a tab size altering function called ((*make_tab_array.*))


{{br}}


#!/usr/bin/env ruby
require 'gtk2'

def make_tab_array(textview, tab_size, font_desc)
   raise "Tab size can't be more than 20" if tab_size > 20
   tab_string = " " * tab_size
   layout = textview.create_pango_layout(tab_string)
   layout.font_description = font_desc
   width, height = layout.pixel_size
   tab_array = Pango::TabArray.new(1, true)
   tab_array.set_tab(0, Pango::TAB_LEFT, width)
   textview.set_tabs(tab_array)
end

window = Gtk::Window.new(Gtk::Window::TOPLEVEL)
window.resizable = true
window.title = "TABs in Text Views"
window.border_width = 10
window.signal_connect('delete_event') { Gtk.main_quit }
window.set_size_request(250, 150)

textview = Gtk::TextView.new
textview.buffer.text = "Tab is now set to 15!\n" +
                        "You can hit a TAB key\n" +
                        "and see for yourself:\n" +
                        "123456789012345678901234567890\n"

# For font styles "Italic", "Bold", "Bold Italic" and
# "Regular", currently all but "Regular" does not work.
font
= Pango::FontDescription.new("Monospace Bold 10")Italic 8")
textview.modify_font(font)
make_tab_array(textview, 15, font)

scrolled_win = Gtk::ScrolledWindow.new
scrolled_win.border_width = 5
scrolled_win.add(textview)
scrolled_win.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_ALWAYS)

window.add(scrolled_win)
window.show_all
Gtk.main

Following are the methods we used in order to implement our tab size altering functionality.


--- Gtk::Widget#create_pango_layout(text=nil)

    Creates a new Pango::Layout with the appropriate colormap, font description, and base direction for drawing text for this widget.
    If you keep a Pango::Layout created in this way around, in order notify the layout of changes to the base direction or font of this widget, you must call Pango::Layout#context_changed in response to the ::style_set and ::direction_set signals for the widget.
    * text: text to set on the layout (can be nil)
    * Returns: the new Pango::Layout



--- Pango::Layout#font_description

    Gets the font description for the layout, if any.
    * Returns: the layout's font description(Pango::FontDescription), or nil if the font description from the layout's context is inherited.

--- Pango::Layout#font_description=(desc)

    Sets the default font description for the layout. If no font description is set on the layout, the font description from the layout's context is used.
    * desc: the new Pango::FontDescription, or nil to unset the current font description.
    * Returns: desc


--- Pango::Layout#pixel_size

    Determines the logical width and height of a Pango::Layout in device units. (Pango::Layout#size returns the width and height in thousandths of a device unit.) This is simply a convenience method around Pango::Layout#extents.
    * Returns: [width, height]
       * width: the logical width
       * height: the logical height


--- Pango::TabArray#set_tab(0, Pango::TAB_LEFT, width)

    Before applying the tab array, you need to add the width.
    * 0: refers to the first element in the Pango::TabArray, the only one that should ever exist.
    * Pango::TAB_LEFT - must always be specified; it is the only constant in ((<Pango#TabAlign>)).
    * width: the width of the tab in pixels.
    * Returns: self: ((*FIXME ??? *))


--- Gtk::TextView#tabs

    Gets the default tabs for text_view. Tags in the buffer may override the defaults. The returned array will be nil if "standard" (8-space) tabs are used.
    * Returns: copy of default tab array, or nil if "standard" tabs are used

--- Gtk::TextView#tabstabs=(tabs)

    Sets the default tab stops for paragraphs in the Gtk::TextView. Tags in the buffer may override the default.
    * tabs: tabs as a Pango::TabArray
    * Returns: tabs

--- Gtk::TextView#tabsset_tabs(tabs)

    Same as Gtk::TextView#tabs=.
    * tabs: tabs as a Pango::TabArray
    * Returns: self
Last modified:2021/08/04 04:22:43
Keyword(s):
References: