Expand a branch on Tree object

Post Reply
User avatar
Luis Krause
Posts: 59
Joined: Tue Oct 11, 2005 1:39 am
Location: Vancouver, Canada

Expand a branch on Tree object

Post by Luis Krause »

Hi everyone

I was wondering if someone has already come with a solution to be able to expand only a branch on a tree (not the whole tree).

I guess it's just a matter of traversiing ::aItems for that branch, so I'm just hoping someone already made that method.

Regards,

Luis
"May the Source be with GNU"
User avatar
James Bott
Posts: 4654
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA
Contact:

Post by James Bott »

Luis,

Have you tried oTree:aItems[n]:expand()?

James
User avatar
Luis Krause
Posts: 59
Joined: Tue Oct 11, 2005 1:39 am
Location: Vancouver, Canada

Post by Luis Krause »

James:
James Bott wrote: Have you tried oTree:aItems[n]:expand()?
Indeed. I was looking for an efficient way to walk through the branches and either expand or collapse all branches below any given node.

I added a few new methods, and made a minor enhancement to the way the static funcition ScanItems() in TTreeView class works to support a toggle mode.

Here's what I added to TtvItem.prg:

Code: Select all


#define TVE_TOGGLE        3

#define TVM_ENSUREVISIBLE TV_FIRST + 20

....

   METHOD Toggle() INLINE ;
      SendMessage( ::oTree:hWnd, TVM_EXPAND, TVE_TOGGLE, ::hItem )

   METHOD MakeVisible() INLINE ;
      SendMessage( ::oTree:hWnd, TVM_ENSUREVISIBLE, 0, ::hItem )

And here's what I added to TTreeVie.prg (ehnancements in bold):
[ Note: it seems bold doesn't work inside the code bbcode, so look out for
[ b ] .... [ / b ] and strip it out from the actual code

Code: Select all


   METHOD CollapseAll( [b]oItem[/b] ) INLINE ScanItems( ::aItems, .f. ), ;
      [b]oItem := ::GetSelected(), if( oItem <> nil, oItem:MakeVisible(), nil )[/b]

   METHOD CollapseBranch( oItem ) INLINE ;
      if( oItem == nil, oItem := ::GetSelected(), nil ), ;
      if( oItem <> nil, ( oItem:Collapse(), ScanItems( oItem:aItems, .f. ), oItem:MakeVisible() ), nil )

   METHOD ExpandAll( [b]oItem[/b] ) INLINE ScanItems( ::aItems, .t. ), ;
      [b]oItem := ::GetSelected(), if( oItem <> nil, oItem:MakeVisible(), nil )[/b]

   METHOD ExpandBranch( oItem ) INLINE ;
      if( oItem == nil, oItem := ::GetSelected(), nil ), ;
      if( oItem <> nil, ( oItem:Expand(), ScanItems( oItem:aItems, .t. ), oItem:MakeVisible() ), nil )

   METHOD Toggle() INLINE AEval( ::aItems, { | oItem | oItem:Toggle() } )

   METHOD ToggleAll( oItem ) INLINE ScanItems( ::aItems, , .t. ), ;
      oItem := ::GetSelected(), if( oItem <> nil, oItem:MakeVisible(), nil )

   METHOD ToggleBranch( oItem ) INLINE ;
      if( oItem == nil, oItem := ::GetSelected(), nil ), ;
      if( oItem <> nil, ( oItem:Toggle(), ScanItems( oItem:aItems, , .t. ), oItem:MakeVisible() ), nil )

....

static function ScanItems( aItems, lExpand[b], lToggle[/b] )

   local oItem, i

   DEFAULT lExpand := .t.[b], lToggle := .f.[/b]

   for i := 1 to Len( aItems )
       oItem = aItems[ i ]

       [b]if lToggle
          oItem:Toggle()
       else[/b]if lExpand
          oItem:Expand()
       else
          oItem:Collapse()
       endif

       if Len( oItem:aItems ) != 0
          ScanItems( oItem:aItems[b], lExpand, lToggle[/b] )
       endif
   next

return nil


As you can see, I added a 3rd param _ to handle the toggle mode (which overrides lExpand param).

The previously existing methods ExpandAll() and CollapseAll() were just augmented with a call to the new TTvItem method MakeVisible() to ensure that when you have lots of branches in your tree, the selected item remains within the visible area.

The ToggleBranch() method was precisely what I was aiming for; with this new method you just pass the oItem you want to expand all the way down, with a single call. Toggle() will just act like Expand() or Collapse(), only acting upon the specified oItem, but not on the rest of the items below the specified one.

Hope this is useful for others, and Antonio, please add it to FWH.

Regards,

Luis
Last edited by Luis Krause on Wed Nov 08, 2006 3:40 pm, edited 1 time in total.
"May the Source be with GNU"
User avatar
Luis Krause
Posts: 59
Joined: Tue Oct 11, 2005 1:39 am
Location: Vancouver, Canada

Re: Expand a branch on Tree object

Post by Luis Krause »

Antonio:

I just spotted an odd thing.

Inside ScanItems() itself we have another call _() to make it recursive.

What I just noticed is that this call doesn't pass down the value of lExpand.
I realized I hadn't passed down lToggle either, but now that I realize you didn't pass lExpand in the original code, I'm a bit confused how come this function actually works as expected.

What am I missing here?


Regards,

Luis
"May the Source be with GNU"
User avatar
Luis Krause
Posts: 59
Joined: Tue Oct 11, 2005 1:39 am
Location: Vancouver, Canada

Re: Expand a branch on Tree object

Post by Luis Krause »

Antonio:

I think I now understand what's going on.

If you don't pass down the additional params to the recursive call, that means that all TTvItem objects below the orignal one will *always* be expanded, even if the original call is collapsing the current one.

The different wasn't obvious at first because you can't see that the branches below the collapsed one are actually expanded :-).

So indeed we need to pass down lExpand (and lToggle in my extension) so that all depending branches are executed with the same method call.

I've just edited my original posting with the code to reflect this adjustment.


Regards,

Luis
"May the Source be with GNU"
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Luis,

Added to FWH.

Many thanks! :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
Post Reply