The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Tk::Treeplus - A Tree (and/or HList) replacement that supports Sorting, Filtering and Resizing of columns

SYNOPSIS

use Tk;
use Tk::Treeplus;

my $mw = MainWindow->new();

# CREATE THE NEW WIDGET
my $hlist = $mw->Scrolled('Treeplus',
    -columns => 5, 
    -width => 70, height => 30,
   #-browsecmd => sub { print "DBG: browsecmd [".((caller(0))[3])."] with >@_<\n";  },
    -browsecmd => sub {  },
    -wrapsearch => 1,
   #-indicator => 0, # If this is a flat list, we may drop the empty indicator space
)->pack(-expand => '1', -fill => 'both');

$hlist->headerCreate(0, 
      -itemtype => 'advancedheader',
      -text => 'ColorName', 
      -activeforeground => 'white',
      -is_primary_column => 1,
);
$hlist->headerCreate(1, 
      -itemtype => 'advancedheader',
      -text => 'Red Value', 
      -activebackground => 'orange',
      -resize_column => 1,
);
#$hlist->headerCreate(2, 
#      -itemtype => 'advancedheader',
$hlist->advancedHeaderCreate(
      -text => 'Green Value', 
      -background => 'khaki',
      -foreground => 'red',
      -command => sub { print("Hello World >@_<, pressed Header #2\n"); },
      -resize_column => 1,
);
#$hlist->headerCreate(3, 
#      -itemtype => 'advancedheader',
$hlist->advancedHeaderCreate(
      -text => 'Blue Value', 
      -activebackground => 'skyblue',
      # NOTE: The prototyping ($$) is MANDATORY for this search-func to work !!!
      -sort_func_cb => sub ($$) { my ($a, $b) = @_; 
                                  print "EXT: a=>$a<>" . join(',',@$a) . "<\n";
                                  $a->[1] <=> $b->[1] },
);
#$hlist->headerCreate(4, 
#       -itemtype => 'advancedheader',
$hlist->advancedHeaderCreate(
      -text => 'ColorID', 
      -sort_numeric => 1,
      -resize_column => 1,
);

my $image = $hlist->Pixmap(-data => <<'img_demo_EOP'
/* XPM */
static char *Up[] = {
"8 5 3 1",
". c none",
"X c black",
"Y c red",
"...YY...",
"..YXXY..",
".YXXXXY.",
"..YXXY..",
"...YY...",
};
img_demo_EOP
);
my $style = $hlist->ItemStyle(qw(imagetext -padx 0 -pady 5 -anchor nw -background forestgreen));
my $child;
foreach (qw( orange red green blue purple wheat)) {
    my ($r, $g, $b) = $mw->rgb($_);
    $hlist->add($_, -data => 'data+' . $_, (/blue/ ? (-itemtype => 'imagetext') : ()) );
    $hlist->itemCreate($_, 0, -text => $_, (/blue/ ? (-itemtype => 'imagetext', -image => $image) : ()));
    $hlist->itemCreate($_, 1, -text => sprintf("%#x", $r), style => $style);
    $hlist->itemCreate($_, 2, -text => sprintf("%#x", $g));
    $hlist->itemCreate($_, 3, -text => sprintf("%#x", $b));
    $hlist->itemCreate($_, 4, -text => sprintf("%d", (($r<<16) | ($b<<8) | ($g)) ));
}
# Create smoe more dummy entries
foreach (qw(red green blue)) {
    $child = $hlist->addchild('purple', -data => 'data+purple+' . $_);
    create_columns($child, $_);
}
foreach (qw(cyan magenta yellow)) {
    my $gchild = $hlist->addchild($child, -data => 'data+'.$child.'+' . $_);
    create_columns($gchild, $_);
}

#-------------------------------------------------------------------
### Uncomment either none, #1 or #2 for different scenarios
#--------------------------------------
# #1 Test for single closed branch
#$hlist->setmode($child, 'close');
#--------------------------------------
# #2 Test for 'full tree mode'
$hlist->autosetmode();
#-------------------------------------------------------------------

# Refresh the content - sort according primary sort columns
$hlist->initSort();

$mw->Button(
    -text => 'Exit',
    -command => sub { exit(0) },
)->pack(qw(-side bottom -pady 10));

Tk::MainLoop;

sub create_columns
{
    my ($path, $value) = @_;
    my ($r, $g, $b) = $mw->rgb($_);
    $hlist->itemCreate($path, 0, -text => $value);
    $hlist->itemCreate($path, 1, -text => sprintf("%#x", $r));
    $hlist->itemCreate($path, 2, -text => sprintf("%#x", $g));
    $hlist->itemCreate($path, 3, -text => sprintf("%#x", $b));
    $hlist->itemCreate($path, 4, -text => sprintf("%d", (($r<<16) | ($b<<8) | ($g)) ));
}

DESCRIPTION

A Tk::Tree (Tk::HList) derived widget that has Sortable, Filterable & Resizable columns.

METHODS

headerCreate()

The create command accepts a new, virtual itemtype 'advancedheader', which will create a header-element with image-based markers for sortorder and current filtering status. Additionally it has a right-side located optional sensor area for column resizing operations. Although all options suitable for Tk::Buttons apply, only those related to coloring are recommended, especially the borderwidth and relief defaults should be UNCHANGED.

In addition, the following options may be specified:

-is_primary_column 0/1

Mark this column to be the primary one (PRIMARYCOLUMN, s.b.) for any subsequent sort- or filter operation. This can be changed during runtime by clicking on different columns or via program by invoking the headerConfigure function (headerConfigure($column, -is_primary_column => 0/1). Note that NO subsequent call to initSort() is needed to (re)sort the list/tree accordingly, this is done implicitely.

-foreground COLOR

The foreground color used for the column Header in normal state.

-background COLOR

The background color used for the column Header in normal state.

-activeforeground COLOR

The foreground color used for the column Header during active state (Mouse over Header).

-activebackground COLOR

The background color used for the column Header during active state (Mouse over Header).

-headerminwidth nnn

Specifies the minimum size of the current column during custom column resizing operation (default: see OPTIONS below)

-headerclosedwidth nnn

Specifies the size of the current column in case it is rendered closed (default: see OPTIONS below)

-sort_numeric 0/1

Specifies that this column will be sorted NUMERIC (in opposite to the default that is ALPHANUMERIC sorting)

-sort_func_cb CB

Specifies that this column will use a custom function specified via -sort_func_cb. This function gets references for $a and $b. First element is the path-id, second is the text of the currently selected PRIMARYCOLUMN, and third element is the content of the '-data' element of the current entry. Note: Due to internal behavior of perl, it is necessary to define the prototype ($$) for this user search function. Additionally the $a & $b must be pulled of the stack function internally.

sub sortfunc ($$) { my ($a, $b) = @_; 
                    print "EXT: a=>$a<>" .
                            join(',',@$a) . "<\n";
                    $a->[1] <=> $b->[1]
                  },

Most elegant way is to specify an anonymous sort function in the headerCreate code:

$hlist->headerCreate(3, 
      -itemtype => 'advancedheader',
      -text => 'Blue Value', 
      -activebackground => 'skyblue',
      # NOTE: The prototyping ($$) is
      # MANDATORY for this search-func to work !!!
      -sort_func_cb =>
          sub ($$) { my ($a, $b) = @_; 
                     print "EXT: a=>$a<>" .
                            join(',',@$a) . "<\n";
                     $a->[1] <=> $b->[1] },
);
-command CB

Specifies a command (function-callback) that becomes executed whenver the column header is pressed(+released), as for a standard 'ButtonRelease-1' event. See headerConfigure() (below) about how to change this callback at runtime.

-resize_column 0/1

This booolean flag decides whether this column is resizable, when the column created. This can be changed later via headerConfigure($column, -resize_column => 0/1) and probed via headerCget()

-filter_column 0/1

Retrieve the current custom filter pattern (perl regex style!) of the given column

headerConfigure()
-command CB

Assign a new custom command to the given column header

-resize_column 0/1

Assign a new resize status (0/1) to the given column (header)

-sort_numeric 0/1

Change the given sortmode to NUMERIC for the given column Note: If the given value is 0 and there is no custom sorting the sortmode switches back to ALPHANUMERIC.

-sort_func_cb CB

Assign a new custom sort_func to the given column

-filter_column RE

Assign a new custom filter pattern (perl regex style!) to the given column

headerCget()
-command

Retrieve the current custom command assigned to the probed column header

-resize_column

Retrieve the current resize status (0/1) of the probed column (header)

-sort_numeric

Retrieve the current sort_numeric status (0/1) of the probed column (header)

-widget (SPECIAL-purpose only)

This command allows with -widget to retrieve the Headerbutton-Widget Reference. NOTE: This is only useful for very experienced users!

initSort()

'initSort( [new_primary_column] )' refreshes the list/tree content and sorts it according the current settings for the primary sort columns (PRIMARYCOLUMN). Additionally it takes current filter settings into consideration.

activateEntry()

'activateEntry(path)' selects the given entry (if it is existing), opens it (and its parents) incase it is hidden and executes a potential browsecmd callback on it. (This is equivalent to clicking an entry in the GUI)

advancedHeaderCreate()

This is an easy-to-use wrapper for 'headerCreate($col++, -itemtype => 'advancedheader', -<...> ... )', it avoids the app to trace the column numbers and the '-itemtype => 'advancedheader' during headercreate(). Every invocation creates another column header for the next unused column (0,1,...n) (NB> Max column number n must be set in advance during treeplus item-creation.

OPTIONS (CreateTime)

-wrapsearch 0/1

Decides whether the Find search will restart from the begin of the list in case it reaches the end.

-maxselhistory nnn

Specifies the maximum number of chached list-selection operations, which can be recalled via the pop-up-menu.

-clipboardseparator CHAR

Specifies the colum separator character which is used if the the current selection is export to the X11 Clipboard. This operation can be done via CTRl-C or via the pop-up-menu. (default char: '|')

-headerminwidth nnn

Specifies the minimum size of a column during custom column resizing operation (default: 20px)

-headerclosedwidth nnn

Specifies the size of a closed column (default: 5px)

-headerforeground COLOR

The foreground color used for the column Header in normal state.

-headerbackground COLOR

The background color used for the column Header in normal state.

-headeractiveforeground COLOR

The foreground color used for the column Header during active state (Mouse over Header).

-headeractivebackground COLOR

The background color used for the column Header during active state (Mouse over Header).

AUTHORS

Michael Krause, KrauseM_AT_gmx_DOT_net

This code may be distributed under the same conditions as Perl.

V0.4 (C) February 2013