NodeElement
A single unit of a SwingModifier chain: one property write or one installed listener, targeting a component of type T and backed by a stateful Node of type N.
Implement this to expose an arbitrary Swing property or listener the library does not ship a builder for (see docs/CUSTOM-COMPONENTS.md). See targetType for how to declare the component type the element targets; the node's Node.component arrives already typed T.
The element is immutable and throwaway: every pass builds a fresh one carrying the values declared then. The Node is the long-lived side - created once per slot, kept for as long as an element of this type occupies it, and owning the mutable state (the captured original, the installed listener) with its setup and teardown in Node.onAttach/Node.onDetach. An element unequal to the one its slot holds costs one update call and nothing else: the node is not recreated and a listener it installed is not reattached. So a callback written inline as a lambda is the intended style and needs no remember - push it onto the node in update and have the node read it when the event fires.
An element is one of two kinds, selected by additive: a property element (the default), right for a value like background or border, or a subscription element, right for a listener like onHover. See additive and key for how each kind is matched across recompositions.
equals and hashCode are abstract, so every element states its own equality: the slot skips an incoming element equal to the one it holds, unless it is a property element and a property declared before it has already written on this pass - see update for that second occasion. Compare a value structurally - a data class says that in one word - and compare anything the node registers (a listener, a callback, a binding, a slot attachment) with ===, since such a field may carry an equals of its own under which two instances the node must tell apart compare equal, leaving the node holding the one the composition replaced. An element that carries nothing, and one whose write has to be redone whatever the declaration says, are equal only to themselves - this === other. A freshly built instance is then unequal to the one the slot holds and every pass applies it; an element declared as an object hands the slot the same instance each pass, so it is applied once.
Properties
Whether this element accumulates rather than replaces. false (the default) makes it a keyed, last-wins property slot - correct for a value like a color or a border. true makes it a positional subscription slot - correct for a listener, so two applications of the same builder both install and both fire instead of one replacing the other.
What this element declares, under the name each value is declared by. Read on demand and never during an apply, so an element assembles it when asked rather than holding it.
Identifies the property this element owns. Defaults to the element's runtime class, so each element type is its own identity; override only when distinct instances of the same type must be independent slots (e.g. a client property keyed by its property key). Ignored when additive is true (additive elements are matched by position, not by key).
What detaching this element puts back, RestorePolicy.EverythingWritten by default. See RestorePolicy for what each undertakes.
The component type this element targets. The node's Node.component arrives already typed T; a node that is not a T is rejected at apply with a clear error. Use the most general type the element needs: Component::class.java for a universal property, JComponent::class.java for a JComponent-only one, a concrete widget class for a widget-specific listener.
Functions
Sets the component's accessible description - a longer localized explanation assistive technologies can read after the name. null clears any description this modifier set.
Sets the component's accessible name - the short localized string assistive technologies announce for it. null clears any name this modifier set. Mirrors Compose's semantics { contentDescription = ... }.
Sets the command string a button puts on the ActionEvent it fires, read back as event.actionCommand. It is what tells two buttons apart inside one shared listener, and it stays put when the button's text changes with the locale. null restores the default, where a button reports its own text as the command.
Attaches an ActionListener (addActionListener/removeActionListener) to a component that fires action events (AbstractButton - so JButton, JCheckBox, ... -, JTextField, JComboBox, JFileChooser, and the AWT Button, TextField, and List).
Runs onAction on the action event of a component that fires one - the same components actionListener lists.
Runs onAction on the action event of a component of type T that fires one, with that component as this.
Runs onAction on the action event of a component of type targetType that fires one, with that component as this. An event sourced anywhere else is refused; see listener.
Attaches an AdjustmentListener (addAdjustmentListener/removeAdjustmentListener) to a scrollbar (javax.swing.JScrollBar, java.awt.Scrollbar).
Runs onAdjustment whenever a scrollbar's value changes - the scrollbars adjustmentListener lists.
Sets the horizontal alignment along the x axis, where 0.0 aligns to the left, 0.5 centers, and 1.0 aligns to the right. A parent that honors alignment - a vertical BoxLayout - lines its children up by this value, so siblings given the same alignment stay in one column.
Sets the vertical alignment along the y axis, where 0.0 aligns to the top, 0.5 centers, and 1.0 aligns to the bottom. A parent that honors alignment - a horizontal BoxLayout - lines its children up by this value, so siblings given the same alignment stay on one row.
Sets background; on a non-opaque component also declare opaque(true) for it to paint.
Sets border; null removes the border. Requires a JComponent target.
Sets whether a component paints its border. Applies to everything built on a button, including menu items, and to progress bars, tool bars, menu bars and popup menus.
Sets the component's bounds - its position and size within its parent. Effective in a parent that does not lay its children out (a null layout, or a LayeredPane), where each child positions itself.
Enrolls this button in group, so at most one of the buttons declared with it is selected. Requires an AbstractButton target (a radio button, a toggle button, a checkbox, or a button menu item).
Installs caret as the text component's caret - the object that holds the insertion point and the selection, paints them, and answers the focus and mouse gestures that move them. Removing the declaration puts back the caret the component carried before.
How fast the component's caret blinks: the delay in milliseconds between the caret being shown and being hidden again. 0 holds it steady.
Sets the color of the caret in a text component - fields, areas, editor and text panes.
Attaches a CaretListener (addCaretListener/removeCaretListener). Requires a JTextComponent target (JTextField, JTextArea, ...). Each event carries the caret offset and the selection anchor, so one listener observes both the caret position and the selected range.
Runs onCaretUpdate whenever the caret moves or the selection changes. Requires a JTextComponent target.
Sets what the caret does when the document is edited somewhere other than where the caret sits.
Attaches a ChangeListener (addChangeListener/removeChangeListener) to a component that fires change events (JSlider, JSpinner, JTabbedPane, JProgressBar, AbstractButton, JViewport, JColorChooser). A color chooser publishes its change events through its selectionModel, and the registration follows that model when the chooser is given another one.
Runs onChange on the change event of a component that fires one - the widgets changeListener lists.
Runs onChange on the change event of a component of type T that fires one, with that component as this.
Runs onChange on the change event of a component of type targetType that fires one, with that component as this. An event sourced anywhere else is refused; see listener.
Sets a putClientProperty entry - the way to reach look-and-feel styling keys and accessibility hints. Each distinct key is an independent modifier slot; null removes the entry, and removing the declaration puts back the value the component carried before. Requires a JComponent target.
Enables system-clipboard copy/cut export and paste import on the component, over the same transfer handler draggable and dropTarget use.
Attaches a ComponentListener (addComponentListener/removeComponentListener).
Runs onComponentChange whenever the component is resized, moved, shown or hidden. Declare the four separately to tell them apart.
Runs each lambda on the change it is declared for. A change left undeclared reports nowhere.
Sets componentOrientation - the component's left-to-right / right-to-left orientation.
Attaches a ContainerListener (addContainerListener/removeContainerListener). Requires a Container target.
Runs onChildrenChange whenever a child is added to or removed from the container. Requires a Container target.
Runs onComponentAdded when a child joins the container and onComponentRemoved when one leaves. Requires a Container target. A direction left undeclared reports nowhere.
Sets whether a button fills the area behind its content. Applies to everything built on a button.
Sets cursor; null restores the inherited cursor.
Makes this button the default button of the window it is in - the one the look and feel's activation keystroke, Enter in the look and feels the JDK ships, activates wherever the focus sits, as long as the button is an enabled descendant of the root pane at that moment. A component that consumes the activation event itself, a text pane among them, keeps it. The association follows the button when it moves to another window, and is released when default is false or the modifier leaves. Requires a JButton target.
Sets the icon a button displays while it is disabled; null hands the state back to the look and feel, which grays the base icon for it. Applies to every kind of button.
Sets the icon a button displays while it is both disabled and selected; null hands the state back to the look and feel, which grays selectedIcon for it, or falls back to the disabled icon where the button carries no selected icon. Applies to every kind of button.
Sets the color text is drawn in while the component is disabled.
Sets which occurrence of the mnemonic letter in the text is underlined, as a zero-based index into the text; -1 underlines none of them. Use it when the letter appears more than once and the first one is not the one to decorate - displayedMnemonicIndex(5) underlines the A of Save As.
Installs filter on the text component's document so it can inspect, reject, or rewrite every insert, remove, and replace before it is applied. A null filter clears any filter the modifier previously installed. Requires a JTextComponent target whose document is an AbstractDocument. A JFormattedTextField is rejected: its document filter belongs to its formatter, which returns it from JFormattedTextField.AbstractFormatter.getDocumentFilter and reinstalls it whenever the field reformats.
Attaches a DocumentListener to the text component's document (document.addDocumentListener). Requires a JTextComponent target (JTextField, JTextArea, ...). The listener observes the document the component currently holds, following it when the component swaps one in.
Runs onDocumentChange for every change to the text component's document - an insertion, a removal and a change of attributes alike. Requires a JTextComponent target, and observes the document the component currently holds, following it when the component swaps one in - as a JEditorPane does when its content type changes.
Runs onInsert when text enters the text component's document, onRemove when text leaves it, and onChange when its attributes change. Requires a JTextComponent target, and follows the document the component holds across a swap.
Makes the component a drag SOURCE that exports a Transferable when dragged.
Makes the component a drop TARGET that imports a dropped Transferable.
Sets an invisible border occupying insets. See emptyBorder (the four-side form).
Sets an invisible border all pixels wide on every side. See emptyBorder (the four-side form).
Sets isEnabled on this component only - whether it responds to user input and paints in its enabled state. Disabling a container does not disable the components inside it, so disable each child you want disabled.
Sets isFocusable, declaring whether this component can receive keyboard focus.
The key that moves the keyboard focus to this text component when pressed with the platform's accelerator modifier - Alt on Windows and Linux, Ctrl+Alt on macOS. It reaches the component from anywhere in the focused window, so a form's fields can be jumped to without tabbing through it.
Attaches a FocusListener (addFocusListener/removeFocusListener).
Runs onFocusChange whenever the component takes or loses the keyboard focus. Read isFocusOwner to tell which, or declare the two directions separately.
Runs onFocusGained when the component takes the keyboard focus and onFocusLost when it loses it. A direction left undeclared reports nowhere.
Sets whether a button paints the indicator showing it holds keyboard focus. Applies to everything built on a button.
Binds focusRequester to this component, so FocusRequester.requestFocus moves keyboard focus to it. The binding follows the modifier: it ends when the modifier leaves the chain or the component leaves the composition, and a different requester declared on a later recomposition takes the binding over from the previous one.
Assigns this component a position in its container's keyboard focus-traversal order. Lower indices are reached first when tabbing forward. Effective only inside a container that installs the composition-order policy via orderedFocusTraversal; components without an index follow the indexed ones in their natural order.
Sets font; null takes the font from the parent container.
Sets foreground; null takes the color from the parent container.
Attaches a HierarchyListener (addHierarchyListener/removeHierarchyListener).
Runs onHierarchyChange when the component's place in the hierarchy changes - it is handed to a parent, loses one, or starts or stops being on screen. The event's change flags say which.
Sets where a component's content sits along its width, when it is given more width than it needs.
Sets which side of the icon the text is drawn on. Applies to labels and to everything built on a button; a component with no icon lays out the same either way.
Attaches a HyperlinkListener (addHyperlinkListener/removeHyperlinkListener). Requires a JEditorPane target.
Runs onHyperlinkUpdate when the user enters, leaves or activates a link. Requires a JEditorPane target, and reports only while the pane is not editable, as hyperlinkListener describes.
Sets the icon a component displays beside its text; null displays none.
Sets the space between a component's icon and its text. Applies to labels and to everything built on a button.
Declares that this component takes keyboard focus when its window first shows it - the field a form or a dialog opens on.
Gates keyboard focus leaving this component on verify: while it answers false, Swing keeps the focus where it is, whether the user tabs away, clicks another control, or the application requests the move.
Attaches an InternalFrameListener (addInternalFrameListener/removeInternalFrameListener). Requires a JInternalFrame target.
Runs onFrameChange on every change to the internal frame - opened, closing, closed, iconified, deiconified, activated and deactivated alike. Requires a JInternalFrame target. Declare the changes one by one to tell them apart.
Runs each lambda on the change to the internal frame it is declared for. Requires a JInternalFrame target. A change left undeclared reports nowhere.
Attaches an ItemListener (addItemListener/removeItemListener) to a component that fires item events: AbstractButton (JCheckBox, JRadioButton, JToggleButton, JCheckBoxMenuItem, JRadioButtonMenuItem), JComboBox, and the AWT Checkbox, Choice, and List.
Runs onItemStateChange on the item event of a component that fires one - the components itemListener lists, over the same event source, which reports the state a component ends up in however it got there.
Runs onItemStateChange on the item event of a component of type T that fires one, with that component as this.
Runs onItemStateChange on the item event of a component of type targetType that fires one, with that component as this. An event sourced anywhere else is refused; see listener.
Ties this modifier's application to keys. While they stand the modifier is diffed as usual; a key that does not compare equal to the one applied last takes the whole modifier apart and applies it again from scratch.
Attaches a KeyListener (addKeyListener/removeKeyListener).
Runs onKeyEvent for every key event on the component - a press, a release and the character they type alike, so one keystroke reports more than once. Declare the events one by one to tell them apart.
Runs each lambda on the key event it is declared for. An event left undeclared reports nowhere.
Marks this label as the caption for the component bound to target via the labelTarget modifier, wiring JLabel.setLabelFor to that component. Requires a JLabel target.
Places the component in its parent container under constraint - the value Container.add(Component, Object) takes: a BorderLayout region name, a GridBagConstraints, a CardLayout card name, or whatever the enclosing container's layout manager understands.
Installs one library-built listener that reads the caller's callback when an event fires - the seam every builder's lambda overload is built on.
Installs a listener instance on the target component via the modifier mechanism - the by-identity listener seam, the one every builder taking a listener object is built on (the typed instance builders like mouseListener/actionListener and the model builders like changeListener).
Installs one library-built listener that reads the caller's callback, naming the target component type as a value.
Installs a listener instance, naming the target component type as a value.
Renders the items of the component this modifier applies to through renderer.
Attaches a ListSelectionListener (addListSelectionListener/removeListSelectionListener). Requires a JList target.
Runs onSelectionChange whenever the list's selection changes. Requires a JList target.
Runs onSelectionChange on the selection event of a list of type T, with that list as this.
Runs onSelectionChange on the selection event of a list of type targetType, with that list as this. An event sourced anywhere else is refused; see listener.
Sets the space a component keeps between its border and its content. Applies to everything built on a button, and to text components.
Sets maximumSize and relays out; null restores the layout-computed maximum size.
Sets maximumSize to Dimension(width, height) and relays out.
Sets minimumSize and relays out; null restores the layout-computed minimum size.
Sets minimumSize to Dimension(width, height) and relays out.
Sets the keyboard mnemonic to the key that types mnemonic, resolved with KeyEvent.getExtendedKeyCodeForChar - so 's' and 'S' both declare the S key. A character that appears on no known keyboard layout resolves to KeyEvent.VK_UNDEFINED, declaring no mnemonic.
Sets the keyboard mnemonic to the key identified by keyCode, a KeyEvent.VK_* value. KeyEvent.VK_UNDEFINED declares no mnemonic.
Attaches a MouseListener (addMouseListener/removeMouseListener).
Runs onMouseEvent for every mouse event on the component - a click, a press, a release, the pointer entering and the pointer leaving alike, so one interaction reports more than once. Declare the events one by one to tell them apart.
Runs each lambda on the mouse event it is declared for. An event left undeclared reports nowhere.
Attaches a MouseMotionListener (addMouseMotionListener/removeMouseMotionListener).
Runs onMouseMove whenever the pointer moves over the component, whether or not a button is held.
Runs onMouseDragged while the pointer moves with a button held, and onMouseMoved while it moves with none. A movement left undeclared reports nowhere.
Attaches a MouseWheelListener (addMouseWheelListener/removeMouseWheelListener).
Runs onMouseWheel when the wheel turns over the component.
Sets name - the key components are looked up by in tests and automation; null clears it.
Installs filter on the text component so it decides where the caret lands before every move: an arrow key, a click, and a selection assigned in code all pass through it, and each may be redirected to another offset or left where it is. A null filter leaves the caret free to go anywhere in the document.
Runs onAccept when this text field accepts its value - the field's own action event, the one its Enter binding fires - so a search box, a command entry or a login form acts on the keyboard.
Registers a callback told the outcome of every export a draggable or clipboard source declared on this component produces: once a drag ends or a clipboard copy/cut completes, onExportDone receives the exported data and the TransferAction that occurred - TransferHandler.COPY, TransferHandler.MOVE, or TransferHandler.NONE when nothing was transferred, in which case the data is whatever the export offered, or null where it produced none. A source offering MOVE implements move semantics here: on a reported MOVE it removes the moved data. With no callback registered a completed export removes nothing, like TransferHandler.exportDone itself.
Installs focus gained/lost handlers.
Installs mouse enter/exit handlers.
Installs a KeyListener whose every event is forwarded to onKeyEvent.
Binds a single KeyStroke to onAction via the component's InputMap/ActionMap - the idiomatic Swing path for shortcuts. condition selects the focus scope (a FocusCondition JComponent.WHEN_* value) and defaults to JComponent.WHEN_FOCUSED.
Convenience overload of onKeyStroke that parses keyStroke via KeyStroke.getKeyStroke(String) (e.g. "ctrl S", "meta shift Z"). Throws at install if the string is not a valid key-stroke descriptor.
Installs mouse press/release/click handlers. onPress fires on MOUSE_PRESSED, onRelease on MOUSE_RELEASED, and onClick on a completed click; each receives the MouseEvent (button, click count, point, modifiers). This is the low-level complement to a widget's domain onClick: use it for arbitrary components (a Label, a FlowPanel) or for right/middle-button handling.
Sets isOpaque - required for background to actually paint. Requires a JComponent target.
Makes this container a focus-cycle root whose Tab order follows its children's focusTraversalIndex values (ascending), rather than their on-screen geometry. Children without an index are visited after the indexed ones. Requires a JComponent target.
Binds anchor to this component, so a menu declared against that anchor opens over it. The binding follows the modifier: it ends when the modifier leaves the chain or the component leaves the composition, and a different anchor declared on a later recomposition takes the binding over from the previous one.
Sets preferredSize and relays out; null restores the layout-computed preferred size.
Sets preferredSize to Dimension(width, height) and relays out.
Sets the icon a button displays while it is held down; null falls back to the base icon. Applies to every kind of button.
Declares one Swing property on the component. The property is read as the declaration arrives and written back when the declaration leaves, so a widget that outlives it carries what it did before. Fold the element in only while a value is declared:
Declares one Swing property on the component, naming the component type as a value.
Attaches an unbound PropertyChangeListener (addPropertyChangeListener), notified of every bound property change. For a single property, prefer the name overload.
Runs onPropertyChange on every bound property change of the component. For a single property, prefer the name overload.
Attaches a PropertyChangeListener bound to the property name (addPropertyChangeListener(name, listener)), notified only of changes to that property.
Runs onPropertyChange on changes to the property name only.
Runs onPropertyChange on changes to the property name of a component of type T, with that component as this.
Runs onPropertyChange on changes to the property name of a component of type targetType, with that component as this. An event sourced anywhere else is refused; see listener.
Sets whether a button paints its rollover state - the look it takes while the pointer is over it. Applies to everything built on a button.
Sets the icon a button displays while the pointer is over it; null falls back to the base icon. Declaring it switches rolloverEnabled on. Applies to every kind of button.
Sets the icon a button displays while the pointer is over it and it is selected; null falls back to selectedIcon. Declaring it switches rolloverEnabled on. Applies to every kind of button.
Sets the icon a button displays while it is selected - a checked check box, an on toggle button; null falls back to the base icon. Applies to every kind of button.
Sets the color selected text is drawn in.
Sets the background painted behind selected text in a text component.
Sets the component's actual size to size, like setSize. See size (the Int overload) for when this takes effect and how size/width/height compose.
Sets the component's actual size to width by height, like setSize. A layout manager overrides this on its next layout pass, so it takes effect for components positioned by themselves - those in a null layout or a JLayeredPane. To influence a managed layout, use preferredSize, minimumSize, or maximumSize instead.
Installs the component into its parent through attachment - one of the host's own dedicated setters rather than the generic Container.add (e.g. a JScrollPane region reached via setViewportView). The attachment belongs to the host: a container composable wrapping such a host is what hands each of its regions the attachment that installs a component there and takes it out again.
Tags the component with tag so it can be located in tests independently of its name.
Returns a modifier that applies this one and then other. For two non-additive elements sharing a NodeElement.key, the later one wins; two additive elements each keep their own slot and both stay installed.
Sets the tooltip per pointer location: text is asked for the tooltip belonging to the place the pointer is over, and answers null where the component has none there. Requires a JComponent target.
Sets toolTipText - the tooltip the component shows wherever the pointer rests on it; null clears it. Requires a JComponent target.
Attaches a TreeExpansionListener (addTreeExpansionListener/removeTreeExpansionListener). Requires a javax.swing.JTree target.
Runs onExpansionChange whenever a node of the tree opens or closes. Requires a javax.swing.JTree target.
Runs onTreeExpanded when a node opens and onTreeCollapsed when one closes. Requires a javax.swing.JTree target. A direction left undeclared reports nowhere.
Attaches a TreeSelectionListener (addTreeSelectionListener/removeTreeSelectionListener). Requires a javax.swing.JTree target.
Runs onSelectionChange whenever the tree's selection changes. Requires a javax.swing.JTree target.
Attaches a TreeWillExpandListener (addTreeWillExpandListener/removeTreeWillExpandListener), notified before a node opens or closes. Requires a javax.swing.JTree target.
Asks onWillChange before a node of the tree opens or closes whether it may: answering false leaves the node as it was and no expansion event follows. Requires a javax.swing.JTree target.
Asks onWillExpand before a node opens, and onWillCollapse before one closes, whether the change may happen: answering false leaves the node as it was and no expansion event follows. Requires a javax.swing.JTree target. A direction left undeclared allows the change.
Whether the inputVerifier of the component that currently holds the keyboard is consulted before focus moves to this component. Swing's own value is true; declare false on a control that must act regardless of what the focused field holds, such as a Cancel button or a scrollbar.
Sets where a component's content sits along its height, when it is given more height than it needs.
Sets whether the text is drawn above, across or below the icon. Applies to labels and to everything built on a button; a component with no icon lays out the same either way.
Sets isVisible - whether the component is shown in its parent's layout.