Node
The base class for all GUI elements in a Scene. The nodes form a Scene Graph
(which is a misnomer, because it is a tree
structure, not a graph
), starting at the Scene.root Node.
Each Node may only appear once (i.e. you cannot use the same node in two place, or in two scenes).
See Scene for a Class Diagram.
Nodes are arranged in a tree structure, starting at Scene.root. All nodes may have 0 or more child Nodes (see children). However, children is often private.
Any changes of a Node's state which change its appearance must call requestRedraw. The redrawing doesn't happen immediately, it happens once at the end of a frame
.
Any changes of a Node's state which affects its size must call requestLayout. Again, the recalculation of the node's size and position aren't done immediately, but at the end of a frame
.
frame
is in quotes, because unlike a game, the screen isn't being continuously redrawn. If nothing needs to be drawn, then the CPU/GPU is idle.
Glok never attempts to redraw only parts of a scene, so even a blinking caret causes a complete redraw of the scene. This may sound inefficient, but considering that games often run at 60fps, updating at 1 or 2 fps isn't taxing.
For expensive nodes (such as a view in a 3D CAD program), the node could draw to an off-screen buffer whenever it is stale, and then simply draw that off-screen buffer to the screen within draw.
Position and Size
(0,0)
┌────────────────────────────────────────▶ x
│
│ (sceneX,sceneY)
│ ┌────────────────┐ ▲
│ │ │ │
│ │ node │height
│ │ │ │
│ │ │ │
│ └────────────────┘ ▼
▼ ◀──────width─────▶
y
Every node has an axis aligned bounding defined by its top left corner sceneX, sceneY and its width and height.
The coordinate system has the Y axis pointing downwards. i.e. (0,0) is at the top left.
Nodes are not positioned nor sized directly by the application developer. Instead, each node's parent decides its children's position and size. The only exception to this is the root node, Scene.root, which is always positioned at (0,0)
and is given the size of the window's client area. (i.e. the size of the window, excluding the title bar and borders).
Every node calculates its size requirements via the methods :
nodeMinWidth nodeMaxWidth nodePrefHeight
In addition, every node can ignore the calculations above, and instead use these properties :
overrideMinWidth overrideMaxWidth overridePrefHeight
These are usually null
. If you use these a lot, it might be an indication that you are doing something wrong. Notable exceptions are for heights for nodes such as ListView
, TreeView
and MixedTreeView
, which don't have a natural height.
When you want to interrogate a node's size requires, don't use any of the above and instead use :
evalMinWidth evalMaxWidth evalPrefHeight
These are one-liners which return either the override
if it is set, or otherwise the calculated size.
Inheritors
Properties
The base class Node has no children, so this is an empty list.
If a mouse is clicked on a node, should it request the focus? For controls which can be read-only
(such as TextArea / TextField), we may want to jump over them when pressing Tab
(i.e. focusTraversable = false), but if they are clicked, then they should accept input focus. The user may wish to select, and copy part of the text.
true
when this node has the input focus. Only 1 node has the input focus.
Is this part of the cycle of node that can accept keyboard focus when he user presses the Tab
key (or Shift-Tab
).
On a scale of 0..1, if this Node's parent has extra space compared to its preferred size, how much extra space should be give to this Node relative to its siblings?
The actual height of this node, in LogicalPixels.
Supposedly unique identifier (or blank). However, it is up to the application developer to ensure the id is unique.
The position of this Node, relative to its parent Node in LogicalPixels. The position and size of Nodes are assigned by their parent in layout, using setChildBounds.
The position of this Node, relative to its parent Node in LogicalPixels. The position and size of Nodes are assigned by their parent in layout, using setChildBounds.
A simple way to override the value calculated by nodeMinHeight. Most of the time, this value is null
, and therefore nodeMinHeight is used.
A simple way to override the value calculated by nodeMinWidth. Most of the time, this value is null
, and therefore nodeMinWidth is used.
A simple way to override the value calculated by nodePrefHeight. Most of the time, this value is null
, and therefore nodePrefHeight is used.
A simple way to override the value calculated by nodeMinWidth. Most of the time, this value is null
, and therefore nodeMinWidth is used.
Similar to styles, but used for temporary styles, such as :hover
.
An ObservableOptionalFont, whose value is Theme.defaultFont. To access this is quite convoluted, because both Node.scene and Scene.theme can change.
The X position of the Node relative to the top left of the window in LogicalPixels. The position and size of Nodes are assigned by their parent in layout, using setChildBounds.
The Y position of the Node relative to the top left of the window in LogicalPixels. The position and size of Nodes are assigned by their parent in layout, using setChildBounds.
To help navigating a scene using keyboard shortcuts (not using a mouse), it is helpful to jump to different sections of the scene. The keyboard shortcut F6
is similar to TAB
, but instead of moving one Node at a time, it jumps to the next node, where this is true
. Shift+F6
navigates in the opposite direction.
On a scale of 0..1, if this Node's parent has less space compared to its preferred size, how much should this node shrink by compared to its siblings.
Used by the Theme to determine how this node should be styled. Similar in concept to CSS's class
attribute.
Defines a popup that appears when the user hover the mouse over this node for a period of time. Typically, containing help text and a KeyCombination.displayText (if this node can be activated using a keyboard shortcut).
When false
, this node will not appear in the scene, and will not take up any spaces.
The actual width of this node, in LogicalPixels.
Functions
Consider using these convenience functions instead : onMousePressed, onMouseReleased, onPopupTrigger, onMouseClicked, onMouseDragged, onMouseMoved, onMouseEntered, onMouseExited, onKeyPressed, onKeyReleased.
Converts em
units to LogicalPixels.
If overrideMaxHeight is set, then return that, otherwise return nodeMaxHeight. Caching is used to improve speed, as calculating sizes can be relatively expensive.
If overrideMaxWidth is set, then return that, otherwise return nodeMaxWidth. Caching is used to improve speed, as calculating sizes can be relatively expensive.
If overrideMinWidth is set, then return that, otherwise return nodeMinHeight. Caching is used to improve speed, as calculating sizes can be relatively expensive.
If overrideMinWidth is set, then return that, otherwise return nodeMinWidth. Caching is used to improve speed, as calculating sizes can be relatively expensive.
If overridePrefWidth is set, then return that, otherwise return nodePrefHeight. Caching is used to improve speed, as calculating sizes can be relatively expensive.
If overridePrefWidth is set, then return that, otherwise return nodePrefWidth. Caching is used to improve speed, as calculating sizes can be relatively expensive.
@return this
if none of my children are at sceneX,sceneY. Otherwise, the child (or one of its ancestors).
Checks this node, and all descendants for a matching id. @return The first node which matches, or null if none match.
Tests each node from this one to the root node. When filter hold true, that node is returned, stopping the iteration. If none are found, returns null.
Applies a block of code on this node, and all of its ancestors, starting at the root node and working downwards to this node.
Applies a block of code on this node, and all of its ancestors, starting at this node and working up to the root node.
The default implementation returns NO_MAXIMUM (an arbitrary large number : 100,000).
The default implementation returns NO_MAXIMUM (an arbitrary large number : 100,000).
Each subclass should override this, to calculate the minimum height it requires. In general, do not call this, and instead call evalMinHeight.
Each subclass should override this to calculate the minimum width it requires. In general, do not call this, and instead call evalMinWidth.
Each subclass much override this to calculate its preferred height. In general, do not call this, and instead call evalPrefHeight.
Each subclass much override this to calculate its preferred width. In general, do not call this, and instead call evalPrefWidth.
A more convenient version of addEventHandler for EventType.FILES_DROPPED.
A more convenient version of addEventHandler for EventType.KEY_PRESSED.
A more convenient version of addEventHandler for EventType.KEY_RELEASED.
A more convenient version of addEventHandler for EventType.KEY_TYPED.
A more convenient version of addEventHandler for EventType.MOUSE_CLICKED.
A more convenient version of addEventHandler for EventType.MOUSE_DRAGGED.
A more convenient version of addEventHandler for EventType.MOUSE_ENTERED.
A more convenient version of addEventHandler for EventType.MOUSE_EXITED.
A more convenient version of addEventHandler for EventType.MOUSE_MOVED.
A more convenient version of addEventHandler for EventType.MOUSE_PRESSED.
A more convenient version of addEventHandler for EventType.MOUSE_RELEASED.
handler will fire when the secondary mouse button is pressed/released depending on the platform.
A more convenient version of addEventHandler for EventType.SCROLL.
Adds a style to Node.pseudoStyle
Adds or removes the pseudoStyle depending on test. See Node.pseudoStyles
When test is true
, trueStyle is added, and falseStyle is removed from Node.pseudoStyles.
Gives the input focus to this node, so that keyboard events are sent to it.
Informs all ancestors that the pref/min/max size of this node has changed, and therefore layoutChildren needs to be called again before the scene is rendered. Cached data, such as prefWidth/height should be invalidated.
Informs that this node needs to be redrawn. Currently, this causes the whole scene to be redrawn.
Ensure that this node is visible, by asking all ancestor nodes, which are Scrollable, to scroll to this node. ScrollPanes will adjust their scroll bars, TabPanes will select the appropriate tab, TitledPanes will open their content etc.
Adds a style to Node.styles
Adds a thin bar below this node. Dragging the bar changes the Node.overridePrefHeight of the node, therefore the node grows/shrinks.