use Tk;
require Tk::HList;
$top = MainWindow->new();
$h = $top->Scrolled('HList', 
                    '-drawbranch'     => 1, 
                    '-separator'      => '/',
                    '-indent'         => 15,
                    '-command'        => \&show_or_hide_dir,
                    )->pack('-fill'   => 'both',
                            '-expand' => 'y');

$icons{"open"}   = $top->Bitmap(-file => './open_folder.xbm');
$icons{"closed"} = $top->Bitmap(-file => './folder.xbm');

show_or_hide_dir("/");
MainLoop();

#-----------------------------------------------------------------------
sub show_or_hide_dir {    # Called when an entry is double-clicked
    my $path = $_[0];
    return if (! -d $path);  # Not a directory.
    if ($h->info('exists', $path)) { 
        # Toggle the directory state. 
        # We know that a directory is open by examining the next
        # entry: it is open if it is a substring of the current path
        $next_entry = $h->info('next', $path);
        if (!$next_entry || (index ($next_entry, "$path/") == -1)) {
            # No. open it
            $h->entryconfigure($path, '-image' => $icons{"open"});
            add_dir_contents($path);
        } else {
            # Yes. Close it by changing the icon, and deleting its subnode.
            $h->entryconfigure($path, '-image' => $icons{"closed"});
            $h->delete('offsprings', $path);
        }
    } else {
        die "'$path' is not a directory\n" if (! -d $path);
        $h->add($path, '-itemtype' => 'imagetext',
                '-image' => $icons{"open"}, '-text' => $path);
        add_dir_contents($path);
    }
}

sub add_dir_contents {
    my $path = $_[0];
    my $oldcursor = $top->cget('-cursor');
    $top->configure('-cursor' => 'watch');
    $top->update();
    my @files = <$path/*>;
    foreach $file (@files) {
        $file =~ s|//|/|g;
        ($text = $file) =~ s|^.*/||g;
        if (-d $file) {
            $h->add($file, '-itemtype' => 'imagetext',
                    '-image' => $icons{"closed"}, '-text' => $text);
        } else {
            $h->add($file, -itemtype => 'text',
                    '-text' => $text);
        }
    }
    $top->configure('-cursor' => $oldcursor);
}



