Quick Tip: Locate / ScrollIntoView Focused Node In Virtual Tree View

virrtualtreeview-locatefocusedI’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.

5 thoughts on “Quick Tip: Locate / ScrollIntoView Focused Node In Virtual Tree View

    1. zarkogajic Post author

      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.

      Reply
      1. ObjectMethodology.com

        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.

        Reply

Leave a Reply

Your email address will not be published. Required fields are marked *