App-Widget
view release on metacpan or search on metacpan
lib/App/Widget/HierSelector.pm view on Meta::CPAN
######################################################################
## $Id: HierSelector.pm 10070 2007-10-10 18:55:12Z spadkins $
######################################################################
package App::Widget::HierSelector;
$VERSION = (q$Revision: 10070 $ =~ /(\d[\d\.]*)/)[0]; # VERSION numbers generated by svn
use App;
use App::Widget;
@ISA = ( "App::Widget" );
use strict;
=head1 NAME
App::Widget::HierSelector - A generic hierarchical view
=head1 SYNOPSIS
use App::Widget::HierSelector;
$name = "tree";
$w = App::Widget::HierSelector->new($name);
print $w->html();
=cut
######################################################################
# CONSTANTS
######################################################################
######################################################################
# ATTRIBUTES
######################################################################
# {node}{number}{type} # whether open or closed
# {node}{number}{open} # 1=open 0=closed
# {node}{number}{value} #
# {node}{number}{label} #
# {node}{number}{icon} # icon to use (default, closed)
# {node}{number}{openicon} # icon to use when open (optional)
# {node}{number}{hovericon} # icon to use when cursor over icon
# INPUTS FROM THE ENVIRONMENT
=head1 DESCRIPTION
This class implements a generic hierarchical view such as is useful
for a TreeSelector, a Menu, a ToolbarSet, or an IconPaneSelector.
The main function of a HierSelector is to display a hierarchical set of
data and allow the user to generate events based on that view.
=cut
######################################################################
# INITIALIZATION
######################################################################
# uncomment this when I need to do more than just call SUPER::_init()
sub _init {
&App::sub_entry if ($App::trace);
my $self = shift;
$self->SUPER::_init(@_);
&App::sub_exit() if ($App::trace);
}
######################################################################
# EVENTS
######################################################################
# Usage: $widget->handle_event($wname, $event, @args);
sub handle_event {
&App::sub_entry if ($App::trace);
my ($self, $wname, $event, @args) = @_;
my ($nodenumber, $x, $y);
my $node = $self->node_list(1);
if ($event eq "open") {
($nodenumber, $x, $y) = @args;
$node->{$nodenumber}{open} = 1;
}
elsif ($event eq "open_exclusively") {
($nodenumber, $x, $y) = @args;
$self->open_exclusively($nodenumber);
}
elsif ($event eq "close") {
($nodenumber, $x, $y) = @args;
$node->{$nodenumber}{open} = 0;
}
elsif ($event eq "select") {
($nodenumber, $x, $y) = @args;
$self->set("selected", $nodenumber); # save node number
# intentionally bubble "select" event to the container
if ($wname =~ /^(.*)-([^.]+)$/) {
my $parent = $1;
my $result = $self->{context}->widget($parent)->handle_event($wname, $event, @args);
return $result;
}
}
else {
return $self->SUPER::handle_event($wname, $event, @args);
}
&App::sub_exit() if ($App::trace);
lib/App/Widget/HierSelector.pm view on Meta::CPAN
if ($node->{$nodenumber}{open} && $authorized) {
$nodebase = $nodenumber;
$nodeidx = 1;
$first_auth_nodeidx = undef;
}
else {
$first_auth_nodeidx = $nodeidx if (!defined $first_auth_nodeidx && $authorized);
$nodeidx++;
}
}
}
&App::sub_exit() if ($App::trace);
#$self->{debug} .= "select_first_open_leaf($selected_nodenumber): [$nodenumber]<br>";
}
######################################################################
# METHODS
######################################################################
sub get_selected {
&App::sub_entry if ($App::trace);
my ($self, $nodeattrib) = @_;
my ($nodenumber);
$nodenumber = $self->{selected}; # might be a tag or a nodenumber
return undef if (!defined $nodenumber);
return $nodenumber if (!defined $nodeattrib);
my $node = $self->node_list();
$nodenumber = $self->get_tag_nodenumber($nodenumber);
&App::sub_exit($node->{$nodenumber}{$nodeattrib}) if ($App::trace);
return $node->{$nodenumber}{$nodeattrib};
}
sub get_tag_nodenumber {
&App::sub_entry if ($App::trace);
my ($self, $tag) = @_;
my $node = $self->node_list();
my ($nodenumber);
if ($tag !~ /^\d+/) { # if $tag is not a $nodenumber already ...
foreach my $nodenum (keys %$node) {
if ( $node->{$nodenum}{tag} && $node->{$nodenum}{tag} eq $tag) {
$nodenumber = $nodenum;
last;
}
}
}
else {
$nodenumber = $tag;
}
&App::sub_exit($nodenumber) if ($App::trace);
return $nodenumber;
}
######################################################################
# OUTPUT METHODS
######################################################################
sub html {
&App::sub_entry if ($App::trace);
my $self = shift;
my ($html, $label);
my $node = $self->node_list();
my ($nodebase, $nodeidx, $nodenumber, $nodelevel);
my (@nextnodebase, @nextnodeidx, @nextnodelevel);
@nextnodebase = (""); # the next nodenumber to check is "$nodebase$nodeidx" (nodenumber = "1" is first)
@nextnodeidx = (1); # check nodenumber "1" next
@nextnodelevel = (1); # index into the resulting table that the folder icon will go
$html = "";
while ($#nextnodebase > -1) {
$nodebase = pop(@nextnodebase); # get info about next node to check
$nodeidx = pop(@nextnodeidx);
$nodelevel = pop(@nextnodelevel);
$nodenumber = "$nodebase$nodeidx"; # create its node number
if (defined $node->{$nodenumber}) { # if the node exists...
$label = $node->{$nodenumber}{label};
$label = $node->{$nodenumber}{value} if (!defined $label);
$label = "" if (!defined $label);
$html .= (" " x ($nodelevel-1)) if ($nodelevel > 1);
$html .= $label;
$html .= $node->{$nodenumber}{open} ? " (open)" : " (closed)";
$html .= "<br>\n";
push(@nextnodebase, $nodebase); # let's search for the node's brother (same depth, next idx)
push(@nextnodeidx, $nodeidx+1); # (next idx)
push(@nextnodelevel, $nodelevel); # (same level)
push(@nextnodebase, "${nodenumber}."); # let's search for the node's children (1 deeper, idx 1)
push(@nextnodeidx, 1); # (idx is 1)
push(@nextnodelevel, $nodelevel+1); # (1 deeper)
}
}
&App::sub_exit() if ($App::trace);
$html;
}
1;
( run in 0.772 second using v1.01-cache-2.11-cpan-39bf76dae61 )