Expand a branch on Tree object

Expand a branch on Tree object

Postby Luis Krause » Tue Nov 07, 2006 6:06 pm

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
Luis Krause
 
Posts: 59
Joined: Tue Oct 11, 2005 1:39 am
Location: Vancouver, Canada

Postby James Bott » Tue Nov 07, 2006 6:13 pm

Luis,

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

James
User avatar
James Bott
 
Posts: 4840
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA

Postby Luis Krause » Wed Nov 08, 2006 7:15 am

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  Expand view

#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  Expand view

   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 ScanItems 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

Postby Luis Krause » Wed Nov 08, 2006 3:29 pm

Antonio:

I just spotted an odd thing.

Inside ScanItems() itself we have another call to ScanItems() 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

Postby Luis Krause » Wed Nov 08, 2006 3:39 pm

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
Luis Krause
 
Posts: 59
Joined: Tue Oct 11, 2005 1:39 am
Location: Vancouver, Canada

Postby Antonio Linares » Fri Nov 10, 2006 7:57 am

Luis,

Added to FWH.

Many thanks! :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
 
Posts: 42099
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 103 guests