in reply to Re^2: Tk::Hlist item movement
in thread Tk::Hlist item movement

You're not missing anything. Tk does tend to be wasteful -- quick and dirty, favoring speed of development and prototyping over efficiency of resource consumption. In general, the trade-off still ends up being a good bargain.

So the key to "solving" your problem is to make sure you have a simple, modularized method for adding items to the HList. The following is a somewhat simple-minded, first-stab approach that keeps the HList config data in a HoH (keyed by "entrypath" string and by attribute name), and passes that to the function that (re)configures the entrypaths in the HList widget. Highlight a line in the HList, push the button, and you'll see how it works.

#!/usr/bin/perl use strict; use Tk; use Tk::HList; my $noderef = create_nodes(); my $mw = MainWindow->new(); my $label = $mw->Label(-width=>15); my $hlist = $mw->HList( -itemtype => 'text', -separator => '.', -selectmode => 'single', -browsecmd => sub { my $path = shift; $label->configure(-text=>$path); } ); my $button = $mw->Button(-text => 'Move to Top', -command => [ \&rearrange, $hlist, $noderef ] +, ); add_to_hlist( $hlist, $noderef ); $hlist->pack; $label->pack; $button->pack; MainLoop; sub create_nodes { my %nodehash = ( n1 => { -text => "top_level_1", -data => "first piece of data" }, 'n1.1' => { -text => "first_child_of_1", -data => "2nd data piece" }, 'n1.2' => { -text => "second_child_of_1", -data => "3rd data" }, n2 => { -text => "top_level_2", -data => "4th piece of data" }, 'n2.1' => { -text => "1st_child_of_2", -data => "5th data piece" }, 'n2.2' => { -text => "2nd_child_of_2", -data => "6th data" }, ); return \%nodehash; } sub add_to_hlist { my ( $hlist, $noderef, $which ) = @_; my @to_add; my %at = (); if ( $which ) { @to_add = sort grep /^$which/, keys %$noderef; %at = ( -at => 0 ); } else { @to_add = sort keys %$noderef; } for ( @to_add ) { $hlist->add($_, %at); if ( $which ) { $at{-at}++; } for my $attrib ( keys %{$$noderef{$_}} ) { $hlist->entryconfigure( $_, $attrib, $$noderef{$_}{$attrib +} ); } } } sub rearrange { my ( $hl, $nl ) = @_; my $anchor = $hl->info( 'anchor' ); printf( "anchor = %s whose data is '%s'\n", $anchor, $hl->info( 'data', $anchor )); my $parent = $hl->info( 'parent', $anchor ) || $anchor; while ( my $higher = $hl->info( 'parent', $parent )) { $parent = $higher; } printf( "top-level = %s which follows %s\n\n", $parent, $hl->info( 'prev', $parent )); $hl->delete( 'entry', $parent ); add_to_hlist( $hl, $nl, $parent ); }

It's admittedly klugey -- it doesn't even check to see whether deleting and adding of entries can be skipped (it merrily deletes and re-adds the first portion of the tree if that's what you selected for "moving to the top") -- but the "waste" is not really noticeable to the user, and that's all that counts.

(updated to fix grammar)

Replies are listed 'Best First'.
Re^4: Tk::Hlist item movement
by otto (Beadle) on May 23, 2007 at 14:54 UTC
    Thanks Graff,

    This is what I was thinking I would have to do... I was just hoping there was a better way. In your example, selecting n2.2 (ie 6th piece of data) and clicking MoveButton, moves the whole n2 up before n1. The desired result is to have it move n2.2 before n2.1, ie movement within a set of siblings, but not movement of a parent. That should be fixable. This may be resolvable by not seeking the highest parent, but the immediate parent, but then needs to understand the need to also place the selected item before the prior adjacent sibling, provided there is one.

    Bottom line that I have learned is that one must delete and re-create. Wishful thinking was there may be some method of movement within the widget.

    Thanks for the help

    Best regards

    ..Otto