I’m a huge fan of one big gem in the Delphi third party controls arena: Virtual Tree View.
Whatever issue I had to solve in my applications harvesting the power of the TVirtualStringTree, the component had the answer, either through vast amount of properties or through nicely exposed events.
The only solution I was not able to find straight forward, or out of the box, is how to have a visual indication that the currently focused node is not visible in the tree. Not “not visible” as hidden but not visible as currently not in view.
The Virtual TreeView, initially being developed by Mike Lischke and now being maintained as an open source project on Google Code is a must-use control if you are up to working with whatever you could call “nodes”.
Again, the solution is rather simple, one only needs to know what combination of tree event + tree method + node property is required to accomplish the above.
Therefore, here’s a simple tree having a few nodes. At one time several nodes can be selected (if allowed using the corresponding property), but only one node at one time can be focused.
Having one node focused I needed to have a button “Locate Focused Node” made visible or hidden: visible if the focused node is “out of the view”.
To make this work, handle the OnScroll event as (the name of the TVirtualStringtree control on my form is “tree”):
//handles OnScroll event procedure TvstForm.treeScroll( Sender: TBaseVirtualTree; DeltaX, DeltaY: Integer); var nr : TRect; begin inherited; if Assigned(sender.FocusedNode) then nr := sender.GetDisplayRect(sender.FocusedNode, 0, false); btnLocateFocused.Enabled := (nr.Top < 0) OR (nr.Bottom > sender.ClientHeight); end;
The above code will make my “locate focused node” button enabled or disabled depending on the visibility of the focused node.
When the focused node goes out of the view area of the tree, the button gets enabled.
Clicking the button scrolls the tree so that the given node is “back” in the client area.
procedure TvstForm.btnLocateFocusedClick(Sender: TObject); begin //get the focused node in the center of the tree! tree.ScrollIntoView(tree.FocusedNode, true); end;
Note that if the node was made invisible using tree.IsVisible[node], the GetDisplayRect method would return a zero height/witdh rect structure and the button will be disabled.
That’s it.
I think VirtualTreeView needs to add a FocusedCell property that scrolls the cell into view upon setting the property.
Am not sure I would agree as you already have the method ScrollIntoView and this property setter would do nothing more but ScrollIntoView (FocusCell).
The IsInView[node] would be a better option here I would say.
Cool.
What is the FocusedCell? The cell that is being interacted with? Can a cell be focused if the TreeView isn’t visable? Is the FocusedCell changed when the user clicks on a cell?
While I like the ScrollIntoView method, I’m concerned whether or not the terminology “FocusedCell” is being used correctly here. Maybe I just misunderstood what FocusedCell means.
I was thinking the FocusedCell is the one being interacted with. Also, I was thinking FocusedCell was nil when the TreeView isn’t visible. I was also thinking the FocusedCell changed when a new cell is clicked on.
BTW, I really like to have proper terminology used when naming properties. I also don’t like one property to be used for multiple things if it forces features to be eliminated. So, in this case we might need a CurrentCell and a FocusedCell. The CurrentCell is the one being worked with wether or not the TreeView is visible but the FocusedCell is the one that is valid when the TreeView is visible.
It doesn’t really matter as long as you can derive from a component and change it’s behavior just like OO is intended to be used.
Oops forgot…
That’s just my opinion. I’m not trying to convince others to share see it the same way.
Lets say you are writing a file manager and you double click a folder in the rightside listview pane that would focus a folder in the tree that may have been scrolled out of view…that would be an example of a FocusedCell that was focused not by direct user clicking on the tree.
Nice tip. thanx.