Focus management
The controls have a new concept that the standard components are unaware of: the focus. In TVision2 Core there is no concept of “focused” components. All components receive all pending events. So, TvControls has to implement the focus management itself in a independent way, and it does basically through the ControlsTree.
The controls tree
The controls tree is just an structure in memory that contains all controls and their relationships. It is an analoug of the Component tree but only for controls.
The controls tree is synchronized with the components tree: when a component is added/removed from the components tree, it is automatically added/removed from the controls tree, if this component is wrapped by a control. The controls tree is needed because TvControls needs a efficient way to mantain a list of controls only.
You never add or remove a control from the controls tree (there are no methods for doing that). You always add the controls to the components tree (as any other component) and then let the controls tree to synchronize automatically.
The controls tree use the components tree events (like
OnComponentRemovedandOnComponentsTreeUpdated) to perform this synchronization.
Handling the focus change key
All UI based applications have some way to change the current focused control (usually this is done by pressing the TAB key). When you configure TvControls, a Hook is installed for you. This Hook intercepts all TAB keystrokes and interacts with the controls tree to perform a focus change.
Remember that a hook is, basically, an event handler that is guaranteed to run before any component behavior.
What is a focused control?
The concept of “focused control” is more complex that it seems. Let’s summarize concepts:
- Only one control has the focus at each time
- There could be controls that never can have the focus
- This is the only control that receive the events, however…
- … events bubble up to the parent control if not handled
- Focused control usually displays it different showing some highlight colors or indications that it has the focus, however…
- … sometimes we want a control that is not really focused render itself as focused. In thoses cases we say the control is “virtually focused”.
A “virtually focused” control is a control that do not have the focus itself but is rendered as it did.
A good example of last point is a menu bar. Menu bar can be the really focused control, but when we open a menu from the menu bar, the control goes to the menu itself. But we want the menu bar still renders as focused.
Really using TvMenuBar the situation is a even a little more complex: The menu bar creates a TvMenu control to display the menu and transfer the focus to the TvMenu. However the TvMenu is a non-focusable control, that creates a child TvList control to show the menu. At this point the status is:
TvListis the real focused control (ControlsTree.CurrentFocused()will return that control).TvMenudo not have focus never (it is created as a non-focusable control)TvMenuBarstill displays as focused, because it is “virtually focused” because one descendant control (theTvList) has the real focus.- When pressing a key, the event goes to the
TvListcontrol (is the real focused control). IfTvListcontrol do not process the event, it bubbles to theTvMenu. IfTvMenudo not process the event it bubles to theTvMenuBar. To handle the event the associated behavior must call theHandle()method of the event received, to mark it as “handled”. Note that one behavior can perform some action when it receives an event, and if theHandle()method is not call, the event will still bubble up. This allows scenarios where both, child and parent must do something on a given event.
Create virtually focused controls
To create a virtually focused control you must override the ConfigureMetadataOptions method of TvControl and call the IsFocused() method in the options parameter. This method gives you access to the focus configuration object (ITvControlMetadataWhenFocusedOptions interface), and you must call only one of the following methods:
Never(): Control never has the focus. It is non-focusable.OnlyWhenAnyChildHasFocus(): Control is non-focusable, but is virtually focused if any of its descendants is the focused control.OnlyWhen(Func<bool> hasFocus): Control is non-focusable, but is virtually focused when the predicatehasFocusevaluates totrue.WhenItselfOrAnyChildHasFocus(): Control is focusable and it is virtually focused when itself or any of its descendants is the focused control.WhenItselfOr(Func<bool> hasFocus): Control is focusable and it is virtually focused when itself is the focused control or the predicatehasFocusevaluates totrue.
protected override void ConfigureMetadataOptions(TvControlMetadataOptions options)
{
options.IsFocused().WhenItselfOrAnyChildHasFocus();
}
If you don’t call
IsFocused()the control is focusable it is virtually focused only when it has the real focus.
FocusTransferred vs IsFocused
The Metadata property of a control contains two properties to know if a control is focused:
IsFocused: Returnstrueif the control is the focused one or if the control is virtually focused.FocusTransferred: Returnstrueif the control is the focused one.
At a given time only one control can have the
FocusTransferredproperty totrue, but more than one control can have theIsFocusedproperty to totrue.
Handling the focus manually
Sometimes you need to handle the focus maually: force some specific control gain focus, or avoid the focus going to specific set of controls. If you are creating complex controls this is usually needed.
The Metadata property of a control offers some methods to manual control the focus:
CaptureFocus(): Capture the focus (only child controls can be focused)ReleaseFocus(): Release the focus (if was captured by any control)ReturnFocusToPrevious(): Returns the focus to previously focused controlIsFocused: Returnstrueif control has focus or is virtually focusedFocus(bool force = false): Transfers focus to the current control. Ifforceistruefocus is transferred regardless of theCanFocusproperty value.CanFocus: Iftruethe control can have the focus. Iffalsethe control is non-focusable.FocusTransferred: Valuestrueif the control is the one currently focusedIsFocused: Valuestrueif the control is the one currently focused or if the control is virtually focused.
Accessing the controls tree
You usually won’t need access to the controls tree. However you can access it through the extension method GetControlsTree() from ITuiEngine. The controls tree exposes the event FocusChanged raised when the focus change.
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.