Showing The Cursor Position
In this lesson you will learn how to use Gtk::TextBuffer
to be notified of the position of the cursor inside the text area widget, and update a label in the header bar of the text viewer application.
Add the cursor position indicator
Update the UI definition
- Add a
GtkLabel
as the child of theAdwHeaderBar
in the UI definition file for theText::Viewer::Window
class; the label must be packed as a child of typeend
, and placed after theGtkMenuButton
- The label has the
cursor_pos
identifier that is going to be used to bind it in theText-Viewer-Window
template - The label has an initial content of Ln 0, Col 0 set using the
label
property - Additionally, the label has two style classes:
dim-label
, to reduce the contrast in the default themenumeric
, which will use tabular numbers in the font used by the label
xml
<object class="AdwHeaderBar" id="header_bar">
<child type="start">
<object class="GtkButton" id="open_button">
<property name="label">Open</property>
<property name="action-name">win.open</property>
</object>
</child>
<child type="end">
<object class="GtkMenuButton">
<property name="primary">True</property>
<property name="icon-name">open-menu-symbolic</property>
<property name="tooltip-text" translatable="yes">Menu</property>
<property name="menu-model">primary_menu</property>
</object>
</child>
<child type="end">
<object class="GtkLabel" id="cursor_pos">
<property name="label">Ln 0, Col 0</property>
<style>
<class name="dim-label"/>
<class name="numeric"/>
</style>
</object>
</child>
</object>
Bind the template in your source code
Add the cursor_pos widget to the Text::Viewer::Window
class
crystal
module Text::Viewer
@[Gtk::UiTemplate(
resource: "/com/example/TextViewer/text-viewer-window.ui",
children: {
"header_bar",
"main_text_view",
"open_button",
"cursor_pos",
}
)]
class Window < Adw::ApplicationWindow
include Gtk::WidgetTemplate
@header_bar = Adw::HeaderBar
@main_text_view : Gtk::TextView
@open_button : Gtk::Button
@cursor_pos : Gtk::Label
def initialize
super()
@header_bar = Adw::HeaderBar.cast(template_child("header_bar"))
@main_text_view = Gtk::TextView.cast(template_child("main_text_view"))
@open_button = Gtk::Button.cast(template_child("open_button"))
@cursor_pos = Gtk::Label.cast(template_child("cursor_pos"))
open_action = Gio::SimpleAction.new("open", nil)
open_action.activate_signal.connect do
self.open_file_dialog
end
self.add_action open_action
end
#...
Update the cursor position label
- Retrieve the
Gtk::TextBuffer
from themain_text_view
widget and connect a callback to thenotify::cursor-position
signal to receive a notification every time thecursor-position
property changes:
crystal
#...
def initialize
super()
@header_bar = Adw::HeaderBar.cast(template_child("header_bar"))
@main_text_view = Gtk::TextView.cast(template_child("main_text_view"))
@open_button = Gtk::Button.cast(template_child("open_button"))
@cursor_pos = Gtk::Label.cast(template_child("cursor_pos"))
open_action = Gio::SimpleAction.new("open", nil)
open_action.activate_signal.connect do
self.open_file_dialog
end
self.add_action open_action
@main_text_view.buffer.notify_signal["cursor-position"].connect do
end
end
#...
- Define the
notify::cursor-position
(lambda) callback to retrieve the position of the cursor from theGtk::TextBuffer
object, and update the contents of thecursor_pos
label:
crystal
#...
def initialize
super()
@header_bar = Adw::HeaderBar.cast(template_child("header_bar"))
@main_text_view = Gtk::TextView.cast(template_child("main_text_view"))
@open_button = Gtk::Button.cast(template_child("open_button"))
@cursor_pos = Gtk::Label.cast(template_child("cursor_pos"))
open_action = Gio::SimpleAction.new("open", nil)
open_action.activate_signal.connect do
self.open_file_dialog
end
self.add_action open_action
@main_text_view.buffer.notify_signal["cursor-position"].connect do
buffer = @main_text_view.buffer
cursor_position = buffer.cursor_position
iter = buffer.iter_at_offset(cursor_position)
@cursor_pos.label = "Ln #{iter.line}, Col #{iter.line_offset}"
end
end
#...
The objective of this lesson is to update the contents of a Gtk::Label
widget every time the position of the cursor in the Gtk::TextView
widget changes by using the property notification mechanism provided by GObject.