Gtk2::TextView
content As you may by now have gathered, the Gtk2::TextView
can be used in quite complex scenarios. Rather than having one large demo program, we will be going through a few basic ones, that will use available methods to accomplish what we want.
This lesson will look at the three items that can fit into a Gtk2::TextView
. They are text, pictures and widgets. You will also see how to change the cursor when the mouse pointer is at certain places.
Table 12-4. Gtk2 object classes used
Gtk2 Class Name |
---|
Gtk2::Pango |
Gtk2::Window |
Gtk2::VBox |
Gtk2::Button |
Gtk2::CheckButton |
Gtk2::Frame |
Gtk2::ScrolledWindow |
Gtk2::Gdk::Cursor |
Gtk2::Gdk::Pixbuf |
Gtk2::TextView |
Gtk2::TextBuffer |
Gtk2::TextTag |
The program can be found here: 'Gtk2::TextView
- Basic '
1 #! /usr/bin/perl -w 2 use strict; 3 4 use Gtk2 '-init'; 5 use Glib qw/TRUE FALSE/; 6 use Gtk2::Pango; 7 8 #anchor for a checkbutton 9 my $check_anchor; 10 #anchor for a normal button 11 my $submit_anchor; 12 13 my $hovering_over_link = FALSE; 14 #the two cursors that we want to use 15 my $pencil_cursor = Gtk2::Gdk::Cursor->new ('pencil'); 16 my $point_cursor = Gtk2::Gdk::Cursor->new ('shuttle'); 17 18 #standard window creation, placement, and signal connecting 19 my $window = Gtk2::Window->new('toplevel'); 20 $window->signal_connect('delete_event' => sub { Gtk2->main_quit; }); 21 $window->set_border_width(5); 22 #$window->set_position('center_always'); 23 24 $window->set_property ('window-position' => 'center_always'); 25 26 #this vbox will geturn the bulk of the gui 27 my $vbox = &ret_vbox(); 28 29 #add and show the vbox 30 $window->add($vbox); 31 $window->show(); 32 33 #our main event-loop 34 Gtk2->main(); 35 36 sub ret_vbox { 37 38 my $vbox = Gtk2::VBox->new(FALSE,5); 39 40 my $frame = Gtk2::Frame->new("Gtk2::TextView - Gentle Introduction"); 41 42 #method of Gtk2::Container 43 $frame->set_border_width(5); 44 #create a scrolled window to put the textview in 45 my $sw = Gtk2::ScrolledWindow->new (undef, undef); 46 $sw->set_shadow_type ('etched-out'); 47 $sw->set_policy ('automatic', 'automatic'); 48 #This is a method of the Gtk2::Widget class,it will force a minimum 49 #size on the widget. Handy to give intitial size to a 50 #Gtk2::ScrolledWindow class object 51 $sw->set_size_request (500, 200); 52 #method of Gtk2::Container 53 $sw->set_border_width(5); 54 55 #we create and build the buffer 56 my $buffer = &create_buffer; 57 #we add this buffer to a new textview 58 my $tview = Gtk2::TextView->new_with_buffer($buffer); 59 #if we want to change the cursors, we have to connect the 60 #motion_notify_event to a sub that will handle it 61 $tview->signal_connect (motion_notify_event => \&motion_notify_event); 62 #create a widget to add to the textview's anchor 63 my $chk_button = Gtk2::CheckButton->new(); 64 #attach this widget to the textview's anchor 65 $tview->add_child_at_anchor ($chk_button, $check_anchor); 66 #create a widget to add to the textview's anchor 67 my $btn_submit = Gtk2::Button->new("_Submit"); 68 #attach this widget to the textview's anchor 69 $tview->add_child_at_anchor ($btn_submit, $submit_anchor); 70 #we do not want to edit anything else than specified text. 71 $tview->set_editable(FALSE); 72 #add the textview to the scrolled window 73 $sw->add($tview); 74 #add the scrolledwindow to the frame 75 $frame->add($sw); 76 77 #add the frame to the vbox 78 $vbox->pack_start($frame,TRUE,TRUE,4); 79 #make them all visable 80 $vbox->show_all(); 81 return $vbox; 82 } 83 84 sub create_buffer { 85 #----------------------------------------------- 86 #a standard buffer will typically be: 87 #1.) created 88 #2.) tags added to; 89 #3.) anchors, text, marks, and pixbuffs added to 90 #----------------------------------------------- 91 #create a net textbuffer 92 my $buffer = Gtk2::TextBuffer->new(); 93 #create a bunch of standard tags 94 $buffer->create_tag ("bold", weight => PANGO_WEIGHT_BOLD); 95 $buffer->create_tag ("big", size => 20 * PANGO_SCALE); 96 $buffer->create_tag ("italic", style => 'italic'); 97 $buffer->create_tag ("grey_foreground", foreground => "grey"); 98 #create a tag for the editable text (editable => TRUE) 99 my $tag = $buffer->create_tag ("editable", 100 style =>'italic', 101 weight => PANGO_WEIGHT_ULTRALIGHT, 102 foreground => "blue", 103 editable => TRUE, 104 ); 105 #a created tag is for all practical purposes a hash with keys and values. 106 #the "create_tag" method does not allow any additional keys, other than a standard set. 107 #here we add a key and value to the $tag hash JUST after creation. This will later be used 108 #when we check if the cursor must change. 109 $tag->{pointer} = "edit"; 110 111 #we get the pointer to the start of the buffer, and add some content. 112 #after every addition, this pointer ($iter) will be pointing to 113 #a new place in the buffer. This works fine for sequencial additions 114 my $iter = $buffer->get_start_iter; 115 #tags is a list, thus they can be stacked to get desired results. 116 $buffer->insert_with_tags_by_name ($iter, "Question:", "bold","big","grey_foreground"); 117 #pixbuffs can also be inserted into the buffer 118 $buffer->insert_pixbuf ($iter, Gtk2::Gdk::Pixbuf->new_from_file ("./pix/tux.png")); 119 $buffer->insert_with_tags_by_name($iter, "\nDo you like Gtk2-Perl?\n\n","grey_foreground"); 120 #anchors are places where widgets can attach to 121 $check_anchor = $buffer->create_child_anchor ($iter); 122 #our editable text 123 $buffer->insert_with_tags_by_name ($iter, "\"Oh, yes my dear, its quite alright, I hear the tinkle of a bell!\"", "editable"); 124 $buffer->insert_with_tags_by_name($iter, "\n\n","grey_foreground"); 125 $submit_anchor = $buffer->create_child_anchor ($iter); 126 127 #return the finished buffer 128 return $buffer; 129 130 } 131 132 sub motion_notify_event{ 133 134 my ($text_view, $event) = @_; 135 136 #we have to discover where in the buffer the mouse currently 137 #roams 138 my ($x, $y) = $text_view->window_to_buffer_coords ( 139 'widget', #GTK_TEXT_WINDOW_WIDGET, 140 $event->x, $event->y); 141 #when we have the pointer co-ordinates within the buffer, 142 #we can do extra processing 143 &determine_pointer($text_view,$x,$y); 144 145 #this is a must to ensure the continuaty of 146 # recording the pointer position 147 $text_view->window->get_pointer; 148 return FALSE; 149 } 150 151 152 sub determine_pointer { 153 154 #this sub will determine the iter where the mouse points at 155 #in the textbuffer. Then it will check the iter's tags and 156 # if it finds the interesting one, change the cursor 157 my ($text_view, $x, $y) = @_; 158 159 my $hovering = FALSE; 160 161 #get the textbuffer 162 my $buffer = $text_view->get_buffer; 163 #determine which iter is at the x and y points where the mouse 164 #currently sits at 165 my $iter = $text_view->get_iter_at_location ($x, $y); 166 #get all the tags associated with this iter 167 #step througk them to check if one is a key 168 #with value "pointer" 169 foreach my $tag ($iter->get_tags) { 170 if ($tag->{pointer}) { 171 $hovering = TRUE; 172 last; 173 } 174 } 175 #check if we need to change the cursor. 176 #this will only execute when there is a change 177 if ($hovering != $hovering_over_link){ 178 $hovering_over_link = $hovering; 179 180 $text_view->get_window ('text')->set_cursor 181 182 #compact conditional statement 183 ($hovering_over_link ? $pencil_cursor : $point_cursor); 184 } 185 }
Remember, when you need to use pango constants, to load it first
use Gtk2::Pango;
You create an anchor for a widget using the Gtk2::TextBuffer
's create_child_anchor
method, but you attach the widget to the Gtk2::TextView
and NOT to the Gtk2::TextBuffer
.
In the sub that handles the motion_notify_event
,you NEED the following line, else it will record the mouse position only as it enters or leaves the Gtk2::TextView
.
$text_view->window->get_pointer;
When you create a Gtk2::TextTag
, you can specify more than one attribute.
my $tag = $buffer->create_tag ("editable", style =>'italic', weight => PANGO_WEIGHT_ULTRALIGHT, foreground => "blue", editable => TRUE, );
You can even add your own key/value pairs to a created Gtk2::TextTag
.
#a created tag is for all practical purposes a hash with keys and values. #the "create_tag" method does not allow any additional keys, other than a standard set. #here we add a key and value to the $tag hash JUST after creation. This will later be used #when we check if the cursor must change. $tag->{pointer} = "edit";
When you insert text with tags into a buffer, you can list more than one tag.
$buffer->insert_with_tags_by_name ($iter, "Question:", "bold","big","gray_foreground");
To ensure we only set the cursor when the Gtk2::TextTag
's key changes, we use the following trick.
#check if we need to change the cursor. #this will only execute when there is a change if ($hovering != $hovering_over_link){ $hovering_over_link = $hovering; $text_view->get_window ('text')->set_cursor #compact conditional statement ($hovering_over_link ? $pencil_cursor : $point_cursor); }
Usually when we want to change the cursor of a widget, we use the widget's |