Reputation: 452
Let's say you have a Scene
which contains a single complex control that itself contains a TextArea
. The complex control is composed in a way, that when it gains the focus the TextArea
gains the focus.
The ComplexControl has the ability to make the TextArea non-editable. Then a key input can has another semantic than operating a text. The new semantic can be defined by the ComplexControl or any node soemwhat higher in the scene graph.
The Scene has a global shortcut CTRL+N for opening a new Tab/View. In context of the ComplexControl CRTL+N semantic is creating a new Text document.
------------------------
| Scene |
| ------------------ |
| | ComplexControl | |
| | ------------ | |
| | | TextArea | | |
| | ------------ | |
| ------------------ |
------------------------
React globally or by a node somewhat higher in the scene graph on KeyEvents / KeyCombinations. Any control somewhat lower can take over the events, so that in a more special context an occurred event has more relevance as globally defined.
Setting a KeyHandler
onto the Scene
or a higher Node
. Any EventHandler
closer to the Source/Target of the EventDispatchChain
" can consume the event. This way the KeyHandler
can prevent the Scene
or any higher Node
from reacting on the key input, which is what the user intends in the special context of a control. Therefore an EventFilter
at the higher place is not suitable.
The TextArea
consumes always any key event, even if it's not the intention of the design. No EventHandler
higher in the EventDispatchChain
gets informed.
TextArea
without consuming it and then let it bubble up the EventDispatchChain
?Upvotes: 2
Views: 84
Reputation: 452
Thanx to sillyfly, who showed me the way. As an answer to question 2, here's the resulting source. I decided to place the functionality at a central point for reuse and give the opportunity to make the suppression condition based. Please don't blame me for the class name, that's not the point ;-)
public class EventUtil {
/**
* Prevents Events of the given <b>eventTypes</b> to be passed down during the
* event capturing phase, if the <b>condition</b> is met.
*
* @param node
* The Node, whose descendants should not be informed about the Event
* @param eventTypes
* The types of Events for which the prevention should be valid
* @param condition
* The condition that must be met to prevent passing the Event down
*/
public static void preventPassDown(Node node, Supplier<Boolean> condition, EventType<?>... eventTypes) {
for (EventType<?> eventType : eventTypes) {
if (eventTypes == null) {
return;
}
node.addEventFilter(eventType, event -> {
if (condition.get()) {
event.consume();
Parent parent = node.getParent();
if (parent != null) {
Event.fireEvent(parent, event);
}
}
});
}
}
/**
* Prevents Events of the given <b>eventTypes</b> to be passed down during the
* event capturing phase.
*
* @param node
* The Node, whose descendants should not be informed about the Event
* @param eventTypes
* The types of Events for which the prevention should be valid
*/
public static void preventPassDown(Node node, EventType<?>... eventTypes) {
preventPassDown(node, () -> true, eventTypes);
}
If someone finds an answer to question 1, please feel free to jump in.
Upvotes: 1