Interface JTextComponentMixin

All Superinterfaces:
ComponentMixin, ContainerMixin, com.vaadin.flow.component.HasElement, com.vaadin.flow.component.HasEnabled, com.vaadin.flow.component.HasSize, JComponentMixin, Serializable
All Known Implementing Classes:
SJFormattedTextField, SJPasswordField, SJTextArea, SJTextField

public interface JTextComponentMixin extends JComponentMixin
Mixin for JTextComponent (SD_sjtextfield). Layers the JTextComponent surface on top of JComponentMixin. Shared across SJTextField, SJPasswordField, and SJTextArea.

R_vaadin_first stance: Document-as-source-of-truth, R_swing_is_truth sync to peer

Per R_vaadin_first, surrogates reproduce the UI functionality of their Swing originals. The Document model is core JTextComponent functionality — it drives DocumentListener fan-out, holds the editable text, and is what user code mutates. The mixin keeps it as the source of truth and R_swing_is_truth-syncs to a Vaadin TextFieldBase peer (TextField / PasswordField / TextArea all extend it). Highlighter / Keymap / NavigationFilter / editor-kit machinery have no Vaadin counterpart and drop-and-WARN.

The caret and selection do have one: dot/mark live in TextStateStore and reach the browser as a setSelectionRange on the peer's own input element, so the auto-advance and reposition-after-reformat idioms work. The reverse direction is installSelectionBridge(), wired lazily on the first caret listener — without a listener, dot/mark are a write-only mirror and getCaretPosition() can lag a caret the user moved.

R_swing_is_truth Document↔peer sync

The two-way bridge mirrors the :emulators.swing.text.JTextComponent implementation verbatim — same code shape, surrogate-side state holder:
  • installTextComponentBindings() (called from concrete's ctor) installs the default PlainDocument via createDefaultDocument(), attaches the internal docToPeer DocumentListener, and (when the peer is a TextFieldBase) sets ValueChangeMode.EAGER + wires the peer's addValueChangeListener to mirror back.
  • The internal docToPeer listener fires on insert/remove. If preventPeerEvents is set, it bails; else it sets the flag, calls peer.setValue(readDocument()), clears in finally.
  • The peer ValueChangeListener fires on user keystrokes (eager). Same flag check; mutates the Document under the flag.
  • setDocument(Document) swaps the Document, unhooks the listener from old, attaches to new, fires "document" PCE, then calls the internal mutation hook so the new doc's text reaches the peer.

getUI dropped — Vaadin Optional<UI> signature clash

Same shape SD_sjbutton records for Button.getIcon() and SD_sjpanel records for JPanel.getUI(): Vaadin Component.getUI() returns Optional<UI>, JDK JTextComponent.getUI() returns TextUI. The mixin doesn't declare a JDK-shaped getter. setUI(javax.swing.plaf.TextUI) survives as overload-safe (no clash on parameter type).
  • Method Details

    • installTextComponentBindings

      default void installTextComponentBindings()
      Install the default Document, attach the docToPeer listener, and wire the peer's ValueChangeListener if the peer is a TextFieldBase. Idempotent: a second call is a no-op once a Document is installed (same guard shape as AbstractButtonMixin.installButtonBindings).
    • createDefaultDocument

      default Document createDefaultDocument()
      Factory hook for the default Document. Subclasses override to pick richer Document models. PlainDocument matches what JTextField / JTextArea / JPasswordField all use.
    • getDocument

      default Document getDocument()
    • setDocument

      default void setDocument(Document doc)
      Swap the Document. Detaches the docToPeer listener from the old Document, attaches to the new, fires "document" PCE, then mirrors the new doc's text to the peer so the UI reflects the swap immediately. Null is legal per JDK.
    • getText

      default String getText()
    • getText

      default String getText(int offs, int len) throws BadLocationException
      Throws:
      BadLocationException
    • setText

      default void setText(String t)
      Replace the Document's contents. Null normalises to empty string — JDK's AbstractDocument early-returns on null/empty, we make that explicit. BadLocationException on (0, length) of a live Document is effectively unreachable; swallow-and-warn per D_never_fail_on_gaps.
    • isEditable

      default boolean isEditable()
      Reads peer.isReadOnly() (negated) when peer is a TextFieldBase. Non-TextFieldBase peers always report true — accepted lossy direction per R_vaadin_first (no reflection).
    • setEditable

      default void setEditable(boolean b)
      Propagate to peer.setReadOnly, fire "editable" PCE. No shadow store per R_vaadin_first Vaadin-first; readback via isEditable(). Equality short-circuit reads the current peer state to avoid spurious PCE.
    • copy

      default void copy()
    • cut

      default void cut()
    • paste

      default void paste()
    • getSelectionStart

      default int getSelectionStart()
    • getSelectionEnd

      default int getSelectionEnd()
    • setSelectionStart

      default void setSelectionStart(int start)
    • setSelectionEnd

      default void setSelectionEnd(int end)
    • select

      default void select(int start, int end)
      Selects [start, end), leaving the caret at end.

      Out-of-range arguments clamp rather than throw, and an end below start collapses to start — the JDK's own JTextComponent.select(int, int) contract, and the reason this method can't just delegate to setCaretPosition(int), which throws instead.

    • selectAll

      default void selectAll()
    • getSelectedText

      default String getSelectedText()
      Returns:
      the selected text, or null when nothing is selected — the JDK's contract, not the empty string.
    • replaceSelection

      default void replaceSelection(String content)
      Replaces the selection with content (deleting it when content is null or empty), then leaves the caret after what was inserted.

      Runs through the Document, so DocumentListeners fire and the R_swing_is_truth sync carries the new text to the peer — no separate value push.

    • getCaretPosition

      default int getCaretPosition()
      Returns:
      the caret offset — the value last written here, clamped to the Document, not a reading of where the browser's caret actually sits. A caret the user moved by clicking or arrowing is not observable server-side, so this lags in exactly that case.
    • setCaretPosition

      default void setCaretPosition(int position)
      Throws:
      IllegalArgumentException - if position is negative or past the end of the Document, per JTextComponent.setCaretPosition(int) (R_match_swing_errors — Swing throws here, so we do)
    • moveCaretPosition

      default void moveCaretPosition(int pos)
      Moves the caret to pos while leaving the mark where it is, so the selection grows or shrinks.
      Throws:
      IllegalArgumentException - if pos is outside the Document
    • getCaretMark

      default int getCaretMark()
      The anchored end of the selection — Swing reaches it only through Caret.getMark(), which is why this accessor has no JDK counterpart on JTextComponent itself.
    • getCaret

      default Caret getCaret()
      Returns:
      the same live view on every call, as Swing does; never null, so getCaret().setDot(n) is safe to chain.
    • setCaret

      default void setCaret(Caret caret)
      WARNs and discards. A user-supplied Caret exists to *paint* a caret, which is R_match_swing_errors sub-bucket (b) territory, and the browser draws its input's caret regardless of what we store. Honouring the setter would mean getCaret() handing back an object whose dot/mark no longer drive anything.
    • addCaretListener

      default void addCaretListener(CaretListener l)
      Fires on every caret move, including the ones the user makes — clicking into the text, arrowing, drag-selecting — which arrive over the emul-selection bridge installSelectionBridge() sets up.
    • removeCaretListener

      default void removeCaretListener(CaretListener l)
    • getCaretListeners

      default CaretListener[] getCaretListeners()
    • addCaretChangeListener

      default void addCaretChangeListener(ChangeListener l)
      Registers a listener on the Caret rather than on the component; same fan-out.
    • removeCaretChangeListener

      default void removeCaretChangeListener(ChangeListener l)
    • installSelectionBridge

      default void installSelectionBridge()
      Wires the browser's caret back to dot/mark, so a caret the *user* moved is readable server-side and fires listeners.

      Installed lazily on the first listener registration rather than in installTextComponentBindings(): it costs a round trip per caret move, and a component nobody is listening to should not pay it. fireCaretUpdate(int, int) dedupes an unchanged dot/mark, which is what breaks the echo from our own setSelectionRange push.

    • addSelectionReportListener

      default com.vaadin.flow.shared.Registration addSelectionReportListener(SelectionReportListener listener, int debounceMillis)
      Reports the browser's selection to a caller that keeps its own caret model, without touching this component's dot and mark:
      Registration r = field.addSelectionReportListener(
              (start, end, backward) -> caret.setDot(backward ? end : start), 1000);
      

      Two reports reach it. A move — a click, an arrow key, a drag, the caret advancing as the user types — is held for debounceMillis of browser idleness, and Flow sends a held event ahead of any other DOM event the browser fires, so a click or key listener on the server already sees where the caret was. A pre-edit report goes at once on every beforeinput, carrying the selection the edit is about to replace; it reaches the server ahead of the value change, so a Document filter reading the caret sees where the user typed.

      Parameters:
      debounceMillis - 0 to report every move as it happens
      Returns:
      removes both listeners; the client-side reporter stays, and costs nothing without them
    • renderSelection

      default void renderSelection(int start, int end, boolean backward)
      Shows [start, end] selected in the peer's input, the caret at start when backward. Render-only: this component's own dot and mark stay as they are and nothing fires, which is what a caller with its own caret model needs.
    • getCaretColor

      default Color getCaretColor()
    • setCaretColor

      default void setCaretColor(Color c)
    • getSelectionColor

      default Color getSelectionColor()
    • setSelectionColor

      default void setSelectionColor(Color c)
    • getSelectedTextColor

      default Color getSelectedTextColor()
    • setSelectedTextColor

      default void setSelectedTextColor(Color c)
    • getDisabledTextColor

      default Color getDisabledTextColor()
    • setDisabledTextColor

      default void setDisabledTextColor(Color c)
    • getHighlighter

      default Highlighter getHighlighter()
    • setHighlighter

      default void setHighlighter(Highlighter h)
    • getKeymap

      default Keymap getKeymap()
    • setKeymap

      default void setKeymap(Keymap k)
    • getNavigationFilter

      default NavigationFilter getNavigationFilter()
    • setNavigationFilter

      default void setNavigationFilter(NavigationFilter f)
    • getMargin

      default Insets getMargin()
    • setMargin

      default void setMargin(Insets m)
    • getFocusAccelerator

      default char getFocusAccelerator()
    • setFocusAccelerator

      default void setFocusAccelerator(char c)
    • getDragEnabled

      default boolean getDragEnabled()
    • setDragEnabled

      default void setDragEnabled(boolean enabled)
    • getDropMode

      default DropMode getDropMode()
    • setDropMode

      default void setDropMode(DropMode m)
    • getActions

      default Action[] getActions()
    • viewToModel

      default int viewToModel(Point p)
    • viewToModel2D

      default int viewToModel2D(Point2D p)
    • modelToView

      default Rectangle modelToView(int pos) throws BadLocationException
      Throws:
      BadLocationException
    • modelToView2D

      default Rectangle2D modelToView2D(int pos) throws BadLocationException
      Throws:
      BadLocationException
    • print

      default boolean print() throws PrinterException
      Throws:
      PrinterException
    • read

      default void read(Reader r, Object desc) throws IOException
      Throws:
      IOException
    • write

      default void write(Writer w) throws IOException
      Throws:
      IOException
    • updateUI

      default void updateUI()
      Description copied from interface: JComponentMixin
      Deliberate no-op — L&F dispatch isn't modelled.
      Specified by:
      updateUI in interface JComponentMixin
    • setUI

      default void setUI(TextUI ui)