FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin for Harbour/xHarbour Expand a branch on Tree object
Posts: 59
Joined: Tue Oct 11, 2005 01:39 AM
Expand a branch on Tree object
Posted: Tue Nov 07, 2006 06: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"
Posts: 4840
Joined: Fri Nov 18, 2005 04:52 PM
Expand a branch on Tree object
Posted: Tue Nov 07, 2006 06:13 PM

Luis,

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

James

FWH 18.05/xHarbour 1.2.3/BCC7/Windows 10
Posts: 59
Joined: Tue Oct 11, 2005 01:39 AM
Expand a branch on Tree object
Posted: Wed Nov 08, 2006 07: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:

#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

   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
"May the Source be with GNU"
Posts: 59
Joined: Tue Oct 11, 2005 01:39 AM
Re: Expand a branch on Tree object
Posted: Wed Nov 08, 2006 03: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"
Posts: 59
Joined: Tue Oct 11, 2005 01:39 AM
Re: Expand a branch on Tree object
Posted: Wed Nov 08, 2006 03: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"
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Expand a branch on Tree object
Posted: Fri Nov 10, 2006 07:57 AM

Luis,

Added to FWH.

Many thanks! :-)

regards, saludos

Antonio Linares
www.fivetechsoft.com

Continue the discussion