arc_of_descent has asked for the wisdom of the Perl Monks concerning the following question:



Greetings!

I'm coding a Explorer-like interface
for managing my bookmark collection using perl and Tk.
I even successfully implemented a perl module which
uses XML to store the bookmarks via manipulation of a hash
But now Tk has me stumped
I just can't seem to get the hover effect right!
I have pasted all the code in my scratchpad so If
any kind Monk can have a look at it I will very
much appreciate it!
You can view my scratchpad Here

The problem appears when I double-click the Root(/) Folder
The child folders don't seem to obey the hover effect I've coded

I hope I've posted enuff info!

--
arc_of_descent

-------------- folder_gui.pl --------------- #!/usr/bin/perl -w use strict; use Tk; use Tk::ROText; use BKhash; use Data::Dumper; my $mw; # Main Window my $fview; # Text box (Read only) my %finfo; # Folder Info my $folder_sep = "/"; my $bkhash = new BKhash(-filename => "./1.xml", -foldersep => "/"); sub init_folder($); sub hover($$); sub sclick($); sub dclick($); sub expand_folder($); sub collapse_folder($); sub get_indentation($); sub make_proper_path($); # Create Main Window and Read only textbox $mw = new MainWindow; $fview = $mw->Scrolled('ROText', -scrollbars => "oe", -cursor => "hand +2"); $fview->pack; # initialize folder info init_folder("/"); # Show Root folder #$fview->insert('end', "\n"); =head $fview->insert('end', "Line 1", '/line1'); $fview->insert('/line1.last', "\n", "/line1_newline"); # Hover over $fview->tagBind('/line1', "<Enter>" => sub { hover('/line1', 1); }); # Hover out $fview->tagBind('/line1', "<Leave>" => sub { hover('/line1', 0); }); $fview->insert('/line1_newline.last', "Line 2", '/line2'); $fview->insert('/line2.last', "\n", "/line2_newline"); # Hover over $fview->tagBind('/line2', "<Enter>" => sub { hover('/line2', 1); }); # Hover out $fview->tagBind('/line2', "<Leave>" => sub { hover('/line2', 0); }); $fview->tagConfigure('/line2', -lmargin1 => 4); $fview->insert('/line2_newline.last', "Line 3", '/line3'); $fview->insert('/line3.last', "\n", "/line3_newline"); # Hover over $fview->tagBind('/line3', "<Enter>" => sub { hover('/line3', 1); }); # Hover out $fview->tagBind('/line3', "<Leave>" => sub { hover('/line3', 0); }); $fview->tagConfigure('/line3', -lmargin1 => 8); # print tag info for (qw{/line1 /line2 /line3}) { print "tag is $_\n"; my @ranges = $fview->tagRanges($_); my $range = join ", ", @ranges; print "range is $range\n"; } for (qw{/line1_newline /line2_newline /line3_newline}) { print "tag is $_\n"; my @ranges = $fview->tagRanges($_); my $range = join ", ", @ranges; print "range is $range\n"; } =cut $fview->insert('end', "\n"); $fview->insert('end', "/" , "/"); $fview->insert("/.last", "\n", "/_newline"); # Hover over $fview->tagBind("/", "<Enter>" => sub { hover("/", 1); }); # Hover out $fview->tagBind("/", "<Leave>" => sub { hover("/", 0); }); # Single click $fview->tagBind("/", "<ButtonRelease-1>" => sub { sclick("/"); }); # Double click $fview->tagBind("/", "<Double-Button-1>" => sub { dclick("/"); }); # make text box disabled #$fview->configure(-state => "disabled"); # Loop MainLoop; # Initailize folder info # ie. Make all collapsed and unselected sub init_folder($) { my $folder = shift; my @f = $bkhash->get_folders($folder); $finfo{$folder}{"selected"} = 0; $finfo{$folder}{"expanded"} = 0; for (@f) { init_folder(make_proper_path("$folder"."/"."$_")); } } # make folder hot! sub hover($$) { my $tag = shift; my $do = shift; if ($do == 1) { if (not $finfo{$tag}{"selected"}) { $fview->tagConfigure($tag, -foreground => "red"); #print "tag is $tag\n"; } } elsif ($do == 0) { if (not $finfo{$tag}{"selected"}) { $fview->tagConfigure($tag, -foreground => "black"); } } } # make folder selected and show bookmarks sub sclick($) { my $tag = shift; # make it look selected #$fview->tagConfigure($tag, # -foreground => "white", # -background => "black", #); # mark it as selected #$finfo{$tag}{"selected"} = 1; } # expand/collapse folder sub dclick($) { my $tag = shift; if ($finfo{$tag}{"expanded"} == 0) { expand_folder($tag); $finfo{$tag}{"expanded"} = 1; } else { collapse_folder($tag); $finfo{$tag}{"expanded"} = 0; } } sub expand_folder($) { my $tag = shift; my @folders; my $fullpath; my $tagnl = $tag."_newline"; my $indentation = get_indentation($tag); @folders = sort $bkhash->get_folders($tag); foreach my $folder (@folders) { $DB::single = 2; $fullpath = make_proper_path($tag.'/'.$folder); my $fullpath_last = $fullpath.'.last'; # Diplay the folder link $fview->insert($tagnl.'.last', $folder, $fullpath); $tagnl = "$fullpath"."_newline"; my $tmp = $fullpath.'_newline'; #print "folder: $folder, \$fullpath: $fullpath, \$tmp: $tmp\n"; $fview->insert($fullpath_last, "\n", $tmp); #print "fullpath is now $fullpath\n"; # Hover over $fview->tagBind($fullpath, "<Enter>" => sub { hover($fullpath, 1); + }); # Hover out $fview->tagBind($fullpath, "<Leave>" => sub { hover($fullpath, 0); + }); # Single click $fview->tagBind($fullpath, "<ButtonRelease-1>" => sub { sclick $fu +llpath); }); # Double click $fview->tagBind($fullpath, "<Double-Button-1>" => sub { dclick($fu +llpath); }); # Indentation $fview->tagConfigure($fullpath, -lmargin1 => $indentation); # print tag info #print "tag is $tagnl\n"; #my @ranges = $fview->tagRanges($tagnl); #my $range = join ", ", @ranges; #print "range is $range\n"; } } sub collapse_folder($) { } sub get_indentation($) { my $tag = shift; my $tabfactor = 16; my @c = split m</>, $tag; my $n; if (scalar(@c) == 0) { $n = 1; } else { $n = scalar(@c); } return ($n * $tabfactor); } sub make_proper_path($) { my $p = shift; $p =~ s!/+!/!g; return $p; } ----------------------- End of folder_gui.pl ---------------------- ------------------ BKhash.pm --------------- package BKhash; use warnings; use strict; use XML::Simple; use Data::Dumper; # Methods sub new($); sub dump(); sub write_to_disk($); sub add_folder($$); sub add_bookmark($$); sub get_folders($); sub get_bookmarks($); sub delete_folder($); sub delete_bookmark($$); # Private methods my $get_ref_to_folder; sub new($) { my $invocant = shift; my $filename = ""; my $foldersep = "/"; my $self; if (@_) { for (my $i=0; $i<scalar(@_); $i++) { if ($_$i eq "-filename") { $filename = $_$i+1; } if ($_$i eq "-foldersep") { $foldersep = $_$i+1; } } } my $class = ref($invocant) || $invocant; if ($filename ne "") { if (-f $filename) { $self->{bkref} = XMLin($filename, forcearray => 1); } else { $self->{bkref} = {}; } } else { $self->{bkref} = {}; } $self->{filename} = $filename; $self->{foldersep} = $foldersep; bless ($self, $class); return $self; } sub dump() { my $self = shift; print Dumper($self->{bkref}); } sub write_to_disk($) { my $self = shift; my $filename = $self->{filename}; my $fileout = XMLout($self->{bkref}); $filename = shift if @_; open FH, ">$filename"; print FH $fileout; close FH; } sub add_folder($$) { my $self = shift; my $ref = $self->$get_ref_to_folder(shift); my $new_folder = shift; $ref->{folder}{$new_folder} = {}; } sub add_bookmark($$) { my $self = shift; my $ref = $self->$get_ref_to_folder(shift); my $bm = shift; push @{$ref->{bookmark}}, $bm; } sub get_folders($) { my $self = shift; my $ref = $self->$get_ref_to_folder(shift); my @retarr; if (exists $ref->{folder}) { @retarr = keys %{$ref->{folder}}; } return @retarr; } sub get_bookmarks($) { my $self = shift; my $ref = $self->$get_ref_to_folder(shift); if (exists $ref->{bookmark}) { return $ref->{bookmark}; } else { return 0; } } sub delete_folder($) { my $self = shift; my $folder_path = shift; my $foldersep = $self->{foldersep}; my $folder_pre; my $folder_del; my $ref; ($folder_pre, $folder_del) = $folder_path =~ /^(.*)$foldersep(.*)$/; $ref = $self->$get_ref_to_folder($folder_pre); delete $ref->{folder}{$folder_del}; # remove folder key if empty if (scalar(keys %{$ref->{folder}}) == 0) { delete $ref->{folder}; } } sub delete_bookmark($$) { my $self = shift; my $folder_path = shift; my $bk_title = shift; my $ref = $self->$get_ref_to_folder($folder_path); my $i = 0; my $index = -1; for (@{$ref->{bookmark}}) { if ($_->{title} eq $bk_title) { print "match\n"; $index = $i; last; } $i++; } splice(@{$ref->{bookmark}}, $index, 1) unless ($index == -1); # remove bookmark key if empty if (scalar(@{$ref->{bookmark}}) == 0) { delete $ref->{bookmark}; } } $get_ref_to_folder = sub { my $self = shift; my $parent = shift; my $foldersep = $self->{foldersep}; my @parents = split /$foldersep/, $parent; my $ref = $self->{bkref}; shift(@parents) if (scalar(@parents) > 0); for (@parents) { $ref = $ref->{folder}{$_}; } return $ref; }; 1; ----------------- End of BKhash.pm ------------------- ------------------------ 1.xml -------------------------- <opt> <folder name="Mail"> <folder name="Free" /> <bookmark title="Hotmail" href="http://www.hotmail.com" /> <bookmark title="Rediffmail" href="http://rediffmail.com" /> </folder> <folder name="Linux" /> <folder name="Stuff" /> </opt> ---------------------------- End of 1.xml ------------------------------

Edited: ~Tue Jan 14 19:54:29 2003 (GMT) by footpad: Replaced A HREF links with more appropriate ones, per Consideration
2003-01-16 Corion : Pasted code from scratchpad. I reformatted the code (due to HTML cut'n'paste), so all formatting errors are most likely mine.

Replies are listed 'Best First'.
Re: Tk tagBind for hover effect
by arc_of_descent (Hermit) on Jan 24, 2003 at 20:41 UTC
Re: Tk tagBind for hover effect
by converter (Priest) on Jan 15, 2003 at 03:43 UTC

    I hope I've posted enuff info!

    I think you've posted too much info. :)

    Since I've been doing a bit of Perl/Tk lately, your problem sounds like it might be interesting, but I'm not in the mood to deal with all that code. I think you'd be more likely to get some useful input if you trimmed your code down to a few small, concise examples and included detailed explanations of the behavior you want from your interface.