The CTree widget is derived from the CList widget. It is designed to display hierarchically-organised data. The tree is displayed vertically, and branches of the tree can be clapsed and expanded as required by the user.
A CTree, being derived from CList, can have multiple
columns. These columns optionally have titles that are displayed
along the top of the CTree widget. Hence there are two functions
for creating a new CTree widget:
$ctree = new Gtk::CTree( $columns, $tree_column );
$ctree = new_with_titles Gtk::CTree( $tree_column, @titles );
The $columns argument specifies the number of columns that the CTree will contain. The $tree_column argumnet specifies which of those columns is to contain the tree. Columns are numbered starting from 0.
With the second funtion above, the
@titles
argument contains a list of strings that contain the captions
for the column headings. The number of columns is determined
from the number of strings in the list. A typical code fragment
using the
new_with_titles()
function would be:
$ctree = new_with_titles Gtk::CTree( 0, "Location", "Description" );
This would create a new CTree with two columns entitled "Location" and "Description", with the first column containing the tree.
The items in a CTree are termed nodes. Nodes are inserted into a
CTree in such a way as to create a hierarchy (although the order
of insertion is not critical). The following function is used to
insert a node:
$ctree->insert_node( $parent,
$sibling,
$text,
$spacing,
$pixmap_closed,
$mask_closed,
$pixmap_opened,
$mask_opened,
$is_leaf,
$expanded );
This function looks a little daunting, but that is merely due to the power of the CTreee widget. Not all of the parameters above are required.
The CTree widget allows you to specify pixmaps to display in each node. For branch nodes, you can specify different pixmaps for when the branch is collapsed or expanded. This gives a nice visual feedback to the user, but it is optional so you don't have to specify pixmaps.
Lets have a quick look at all of the parameters:
- $parent
The parent node of the one we are inserting. May be undef for a root-level (i.e. initial) node
- $sibling
A sibling of the node we are inserting. May be undef if there are no siblings.
- $text
The textual contents of each column in the tree for this node. This must have an entry for each column, even if it is an empty string. You may be wondering how a scalar holds the text for each column. The answer is pretty simple. The scalar actually holds an anonymouse list containing each of the text labels. For example, if you have a two column tree, you should use something like this:
$text = [ "column 1", "column 2" ];
- $spacing
Specifies the padding between the nodes pixmap and text elements, if a pixmap is provided.
- $pixmap_closed
A pixmap to display for a collapsed branch node and for a leaf node.
- $mask_closed
A bitmap mask for the above pixmap.
- $pixmap_opened
A pixmap to display for an expanded branch node.
- $mask_opened
A bitmap mask for the above pixmap.
- $is_leaf
Indicates whether this is a leaf or branch node.
- $expanded
Indicates whether a branch node is initially expanded or collapsed.
An object of type GtkCTreeNode is returned by the insert_node() function. This object is used to reference the node when manipulating it. The node is also supplied by many of the CTree signals to identify which node the signal pertains to.
To remove a node for a CTree, the following function is
provided:
$ctree->remove_node( $node );
There are a number of functions that set options that pertain to
a CTree instance as a whole (rather than to a particular
node). The first group set padding attributes that effect how
the widget is drawn:
$ctree->set_indent( $indent );
$ctree->set_spacing( $spacing );
The function set_indent() sets how far a new branch is indented in relation to it's parent. The default is 20.
The function set_spacing() sets how far a node is horizontally padded from the vertical line that is drawn linking the nodes of each branch. The default is 5.
The next two functions affect the style of the lines and
expander that are drawn to represent the tree structure. An
expander is a graphical component that the user can select to
expand and collapse a branch of the tree.
$ctree->set_line_style( $line_style );
$ctree->set_expander_style( $expander_style );
The function
set_line_style()
is used to select the style of line that is drawn between nodes
of the tree. The parameter line_style can be one of:
'none'
'solid'
'dotted'
'tabbed'
The function
set_expander_style()
is used to select the style of branch expander, and the
parameter expander_style can be one of:
'none'
'square'
'triangle'
'circular'
#!/usr/bin/perl -w use Gtk ; use strict ; set_locale Gtk; init Gtk; my $false = 0; my $true = 1; my $window; my $scrolled_window; my $ctree; my $closed; my $closed_mask; my $opened; my $opened_mask; my $leaf; my $leaf_mask; my @closed_xpm = ( "16 16 6 1", " c None s None", ". c black", "X c red", "o c yellow", "O c #808080", "# c white", " ", " .. ", " ..XX. ", " ..XXXXX. ", " ..XXXXXXXX. ", ".ooXXXXXXXXX. ", "..ooXXXXXXXXX. ", ".X.ooXXXXXXXXX. ", ".XX.ooXXXXXX.. ", " .XX.ooXXX..#O ", " .XX.oo..##OO. ", " .XX..##OO.. ", " .X.#OO.. ", " ..O.. ", " .. ", " "); my @open_xpm = ( "16 16 4 1", " c None s None", ". c black", "X c #808080", "o c white", " ", " .. ", " .Xo. ... ", " .Xoo. ..oo. ", " .Xooo.Xooo... ", " .Xooo.oooo.X. ", " .Xooo.Xooo.X. ", " .Xooo.oooo.X. ", " .Xooo.Xooo.X. ", " .Xooo.oooo.X. ", " .Xoo.Xoo..X. ", " .Xo.o..ooX. ", " .X..XXXXX. ", " ..X....... ", " .. ", " "); my @leaf_xpm = ( "16 16 4 1", " c None s None", ". c black", "X c white", "o c #808080", " ", " ....... ", " .XXXXX.. ", " .XoooX.X. ", " .XXXXX.... ", " .XooooXoo.o ", " .XXXXXXXX.o ", " .XooooooX.o ", " .XXXXXXXX.o ", " .XooooooX.o ", " .XXXXXXXX.o ", " .XooooooX.o ", " .XXXXXXXX.o ", " ..........o ", " oooooooooo ", " "); # Create Window $window = new Gtk::Window( "toplevel" ); $window->set_usize( 300, 200 ); $window->set_title( "CTree Example" ); $window->signal_connect( "destroy", sub { Gtk-> exit ( 0 ); } ); $window->border_width( 5 ); $window->realize(); # Create Scrolled Window $scrolled_window = new Gtk::ScrolledWindow( undef, undef ); $window->add( $scrolled_window ); $scrolled_window->set_policy( 'automatic', 'always' ); $scrolled_window->show(); # Set up Pixmaps ($closed, $closed_mask) = initialize_pixmap( @closed_xpm ); ($opened, $opened_mask) = initialize_pixmap( @open_xpm ); ($leaf, $leaf_mask) = initialize_pixmap( @leaf_xpm ); # Create CTree $ctree = create_tree(); $ctree->signal_connect( 'select_row', \&selection_made ); $scrolled_window->add( $ctree ); $ctree->show(); $window->show(); main Gtk; exit 0; ### Subroutines # Since I am hard-coding the values of the tree, I've decided to # include all that code inside this function. Once the tree is built, # it is returned. sub create_tree { my $tree = new_with_titles Gtk::CTree( 0, "Column 1", "Column 2" ); $tree->set_column_width( 0, 150 ); my $root = insert_node( $tree, undef, ["root", "a"], $false ); my $node = insert_node( $tree, $root, ["branch", "b1"], $false ); insert_node( $tree, $node, ["leaf", "c11"], $true ); insert_node( $tree, $node, ["leaf", "c12"], $true ); insert_node( $tree, $node, ["leaf", "c13"], $true ); insert_node( $tree, $root, ["leaf", "b2"], $true ); $node = insert_node( $tree, $root, ["branch", "b3"], $false ); $node = insert_node( $tree, $node, ["branch", "c31"], $false ); insert_node( $tree, $node, ["leaf", "d311"], $true ); insert_node( $tree, $node, ["leaf", "d312"], $true ); insert_node( $tree, $node, ["leaf", "d313"], $true ); insert_node( $tree, $node, ["leaf", "d314"], $true ); return $tree; } # Given the tree, parent node (undef for root node), text, and whether # the node is to be a leaf node, add the node to the tree. sub insert_node { my ( $tree, $parent, $text, $is_leaf ) = @_; my @args; if ( $is_leaf ) { @args = ( $leaf, $leaf_mask, undef, undef, $true, $false ); } else { @args = ( $closed, $closed_mask, $opened, $opened_mask, $false, $true ); } return ( $tree->insert_node( $parent, undef, $text, 5, @args ) ); } # Callback run when the mouse is clicked inside the CTree. It does # nothing more than printing out the text label at the row and column # in the tree. sub selection_made { my ( $ctree, $row, $column ) = @_; my $node = $ctree->node_nth( $row ); my $text = $ctree->node_get_text( $node, $column ); # I think this should work, but I get a segmentation fault #my $text = $ctree->get_text( $row, $column ); print ( "($row, $column) => $text\n" ); } # Given a pre-defined xpm, return the pixmap and the mask associated # with it. sub initialize_pixmap { my @xpm = @_; my $pixmap; my $mask; my $style = $window->get_style()->bg( 'normal' ); ($pixmap, $mask) = Gtk::Gdk::Pixmap->create_from_xpm_d( $window->window, $style, @xpm ); return ( $pixmap, $mask ); } # END EXAMPLE PROGRAM
CTree Example Screenshot