Class TextField

java.lang.Object
limn.scene.Widget<TextField>
limn.components.TextField
Direct Known Subclasses:
PasswordField, SearchField

public sealed class TextField extends Widget<TextField> permits PasswordField, SearchField (not exhaustive)
Single-line text input: blinking cursor (frame-clock ticker), mouse and Shift+arrow selection, Home/End, Ctrl/Cmd+A/C/V/X through the system clipboard, placeholder, and horizontal scrolling that keeps the cursor visible when the text overflows. Colors come from the Theme, metrics from the SizeTokens row of the step resolved on this widget, and every stroke from Strokes, which is why a focus ring is the same weight at XSMALL and XLARGE.

The reference implementation for the text cluster: PasswordField and SearchField inherit all of this geometry and declare none of their own.

Every horizontal coordinate here comes from one shaped line, held in a field and re-shaped only when its inputs change. Caret x is ShapedText.caretX(limn.graphics.ShapedText.Position), a click is ShapedText.hitTest(float), the selection band is the N boxes selection returns, and the arrow keys step through ShapedText.caretLeft(limn.graphics.ShapedText.Position)/ShapedText.caretRight(limn.graphics.ShapedText.Position). None of it is the width of a prefix of the string, because with a shaper in the pipeline that width is not a thing that exists: inside their line characters join, ligate, kern and reorder differently than they do alone, so a prefix measurement is not a slower way to place a caret but a wrong one. shapeDisplay(java.lang.String, limn.graphics.Font) is where a subclass substitutes a display form, and its index space is the model's, which is what lets the substitution happen without any index arithmetic at all.

  • Constructor Details

    • TextField

      public TextField()
      An empty single-line field.
  • Method Details

    • text

      public String text()
      The current contents.
    • setText

      public TextField setText(@Nullable String text)
      Replaces the contents, clearing the selection and undo history. Announces a TEXT edit as CODE when the text moved, and reaches no handler; the undo history and the caret are reset even when it is handed the string it already holds, because the guard is on the announcement and not on the call. UI thread only.
      Parameters:
      text - the new contents; null is the empty string
      Returns:
      this field
    • setPlaceholder

      public TextField setPlaceholder(String newPlaceholder)
      Sets a fixed placeholder, shown only while the field is empty.
    • setPlaceholder

      public TextField setPlaceholder(I18nString newPlaceholder)
      Sets a placeholder that follows the UI language. A subclass shipping a default one (see SearchField) simply calls this in its constructor: an application's own setPlaceholder replaces the value, so there is no "did the app override it" state to track.
    • placeholder

      public String placeholder()
      The placeholder as it currently reads.
    • setMask

      public TextField setMask(@Nullable String pattern)
      Fits what is typed to a pattern: 0 takes a digit, A a letter, * any character, and every other character is a literal the field writes by itself as the next position is filled, so "000.000.000-00" turns 12345678900 into 123.456.789-00; the literals that end a pattern arrive with its last position, so "00 kg" turns 12 into 12 kg. Characters a position does not take are passed over, and pasting a value with its literals or without them comes out the same. A literal typed by hand shows as it is typed, when it is a character the next position would refuse or follows one: the D and then the E of "'DE'00", the +1 of "+1 (000)"; Backspace takes such literals back one at a time, and typing the literal under the caret, anywhere in the text, steps over it. While the field has the keyboard, the positions still to fill show as a guide (___.___.___-__), and the caret at the end of the text is drawn where the next character will appear, past the literals the guide shows before it (after DE in an empty "'DE'00"); the text holds no literal it has not written. Without the keyboard, an empty field shows its placeholder. A reader hears the text with its literals but not the pattern, which is syntax and not words: say what the field expects in the user's language with a tooltip or Widget.setAccessibleDescription(I18nString).

      Text between single quotes is literal, so a 0, an A or a * can be one: "+'0' 000" writes +0 before three digits. Two single quotes are one apostrophe, inside quotes and out ("'o''clock' 00"). This is the quoting of SimpleDateFormat.

      A character a position takes is never lost to a literal that happens to be the same character: under "+55 (00) 00000-0000", 51987654321 keeps its area code 51 and reads +55 (51) 98765-4321, which reads back as the same value. A text is read with its literals when it carries them, and a literal no position would take (+, a space, a parenthesis) is what shows it does. A run of literals made only of characters its position takes ("'55'00000") is the one case the text cannot tell: a value that begins with that run is read as carrying it, so set such a field from its formatted text.

      An edit before the end of the text is made to the value: the characters it takes go, those typed or pasted go in where the caret is, and the text is written again, so the literals stay where the pattern has them however the edit shifts what follows, and none of them is ever read as a character typed into a position. An edit never pushes characters already typed off the end: typing or pasting into a field with no position free changes nothing, as typing at the end of a full field does, and what finds no free position of a longer paste is dropped. To replace characters, select them and type over them: typing or pasting over a selection that holds positions overwrites them one by one from the first, and nothing moves. With 12 of ABC-1234-XY selected, a 5 reads ABC-5234-XY with the 2 still selected, and a 6 then ABC-5634-XY with the caret after it; stopping midway leaves what is still selected as it was, in the direction it was made. A key goes to the first selected position even when the selection begins on a literal that is the same character: the 1 typed over 1 (4 of +1 (415) is the area code's. A character the next selected position does not take is refused, the selection unchanged. A paste fills the selected positions in order with the characters each takes and leaves those it does not reach as they were and still selected; what is left of it is dropped where a character of the value follows the selection, and where none does, the selection ends the value and what is left fills the free positions after it, which moves nothing: +1 (415) 5 with the 5 selected and 9990123 pasted reads +1 (415) 999-0123. Each keystroke is an undo step of its own. A selection that holds every position the text fills, with or without the literals around them (Ctrl+A, or the digits alone of +1 (555) 123-4567), is the whole value: typing or pasting over it starts a new value, as in any field, fitted afresh, so a literal typed by hand begins it as typing it into an empty field would (Ctrl+A, then +, leaves +); one from which no position takes anything and no literal is written is refused.

      An edit that is not an overwrite (a Backspace, a Delete, a Cut, typing with nothing selected or over literals alone) moves the characters after it by as many positions as it inserts more, or fewer, than it takes. On a pattern whose positions are all of one kind each still lands in a position that takes it. On one that mixes them ("AAA-0000-**"), an edit that would move a character into a position that does not take it, where it would be lost, is refused: ABC-1234-X with a Q typed after the B, or ABC-1234-XY with Backspace among the digits, stays as it is. A digit moving within its run of digits with nothing of another kind after it, or on into an any position, still fits, and that edit is made: ABC-1234-X with a 5 typed after the 3 reads ABC-1235-4X. A refused edit, here or in a full field, does nothing: the text, the caret and the selection stay, no handler runs, no watcher hears of it, no undo step is left, and a refused Cut leaves the clipboard as it was. A Cut of literals alone, which the field writes back at once, copies nothing either, and leaves the caret where the selection began.

      A masked field lays its text out left to right in every language, since what it holds is a code or a number written in a fixed shape: its groups, the stretches between literals, run left to right in the order they are written, whatever script their characters are in. In an Arabic or a Hebrew layout a card reads 4111 1111 1111 1112, and in Arabic-Indic digits ٤١١١ ١١١١ ١١١١ ١١١٢, its first group on the left, and a phone +1 (415) 555-0123, not their groups reversed. Inside a group each script keeps its own direction: a group of Hebrew letters under "AAA-AAA" reads right to left within its box, and the second group follows it on the right. One shape is left to the bidirectional algorithm: a quoted literal of right-to-left letters that touches a group of them, with no space or punctuation between, is read with it as one right-to-left run, so under "AAA'ש'AAA" the second group stands on the left of the first. The text starts at the left edge of the box, where the caret, the selection, a click, a double click and the arrow keys follow it and the guide continues it to the right, so each position stays where it is as it fills; a placeholder stands there too, laid out as the text when the pattern would write it (an example value, or the pattern itself), and otherwise left to right unless its own words say otherwise. The field's icons, its trailing button and its pads still follow the layout direction.

      The text already in the field is fitted at once. When fitting changes it, the text is replaced as setText(java.lang.String) replaces it: the undo history starts again from the fitted text, and the caret goes to its end; a text that already fits is left alone, history and caret included. null takes the mask away and leaves the text as it is.

      Parameters:
      pattern - the pattern, or null
      Returns:
      this field
      Throws:
      IllegalArgumentException - if the pattern has no position to fill outside quotes, or opens a quote it never closes; the message names the pattern, and the field keeps the mask it had
    • mask

      public @Nullable String mask()
      Returns:
      the pattern the text is fitted to, or null
    • unmaskedText

      public String unmaskedText()
      Returns:
      the characters typed into the positions of the mask, without its literals: the 12345678900 of 123.456.789-00. Without a mask, the text
    • isMaskComplete

      public boolean isMaskComplete()
      Returns:
      whether every position of the mask holds a character typed, pasted or set into it, never a literal; without a mask, true
    • onChange

      public TextField onChange(@Nullable Consumer<String> listener)
      The application's response to the user editing the text: typing, pasting, undo and redo, an IME commit, an assistive technology's set. Never for setText(java.lang.String) or insertText(java.lang.String), which are a caller's writes; to hear every edit whatever caused it, watch the field, which also hands over the edit's offsets.
      Parameters:
      listener - the handler, or null to clear the slot
      Returns:
      this field
      Throws:
      IllegalStateException - if a handler is already registered
    • onSubmit

      public TextField onSubmit(@Nullable Consumer<String> listener)
      The application's response to the user pressing Enter in the field, called with the text. Announced to the watchers as SUBMITTED first. Without a handler Enter is left alone, so a Dialog's default button still answers it, and it is never taken while an input method is composing, where Enter commits the composition.

      What a subclass overriding the key hook used to do, before this class was sealed: the route the forms guide taught for submitting on Enter.

      Parameters:
      listener - the handler, or null to clear the slot
      Returns:
      this field
      Throws:
      IllegalStateException - if a handler is already registered
    • handleUserChange

      protected void handleUserChange(Change.Aspect aspect)
      Description copied from class: Widget
      Runs this widget's application handler for a change it has just announced. Called by Widget.runHandler(limn.scene.Change), and so by Widget.notifyChange(limn.scene.Change), only for a USER origin and after every watcher has run.

      A component overrides it once and switches on the aspect, reading its own accessors for the payload: a slider passes value(), a combo box selectedIndex(), a text field text(). A component with no handler does not override it.

      An override that does not recognise the aspect must call super, because a subclass of a component that has a handler inherits that component's dispatch through this method: a SearchField that overrode this for its own aspect and did not chain would silently delete TextField's. The ordering lives in the base class, this is the one link in it a subclass can break, and the contract test drives every subclass through its parent's gestures to catch one that does.

      Overrides:
      handleUserChange in class Widget<TextField>
      Parameters:
      aspect - what changed; the origin is USER or this is not called
    • insertText

      public TextField insertText(@Nullable String text)
      Inserts text at the cursor (replacing any selection): a caller's write, announced as a TEXT edit at CODE. UI thread.
    • setPreferredWidth

      public TextField setPreferredWidth(float width)
      Overrides the step's fieldWidth; a negative value restores it.
    • setLeadingIcon

      public TextField setLeadingIcon(@Nullable Icon icon)
      A leading icon inside the field, tinted to the muted text color (null clears). Drawn as authored whichever way the field reads; use setLeadingIcon(Icon, Icon.Mirroring) for an icon that means a direction.
    • setLeadingIcon

      public TextField setLeadingIcon(@Nullable Icon icon, Icon.Mirroring mirroring)
      A leading icon that says whether it turns around when the interface does. Only the code that placed an icon knows whether its arrow means "back" or "download", which is why this is a flag here and never a classification inside the toolkit.
    • setTrailingButton

      public TextField setTrailingButton(@Nullable Icon icon, @Nullable Runnable action)
      A trailing coupled button (icon + action) inside the field, the caret/arrow region idiom of ComboBox. icon == null removes it.

      The button it makes has no name. It is an operable control, so the accessible tree cannot leave it out, and an icon and a callback carry nothing to announce it by; use setTrailingButton(Icon, I18nString, Runnable) for a button a screen reader can name.

    • setTrailingButton

      public TextField setTrailingButton(@Nullable Icon icon, @Nullable Runnable action, Icon.Mirroring mirroring)
      A trailing coupled button whose icon says whether it turns around when the interface does; see setLeadingIcon(Icon, Icon.Mirroring) for why the toolkit does not decide that.

      The button it makes has no name; see setTrailingButton(Icon, Runnable).

    • setTrailingButton

      public TextField setTrailingButton(@Nullable Icon icon, @Nullable I18nString name, @Nullable Runnable action)
      A trailing coupled button with a name: what it does, said in words, for whoever cannot see the icon.

      The other two overloads take an icon and a callback and have nowhere to put one, so the button they make is an operable control the tree publishes unnamed — which the gallery check refuses for any scene that uses it, and rightly.

      Parameters:
      icon - the glyph, or null to remove the button
      name - what the button does, following the UI language; null leaves it unnamed
      action - what to run when it is pressed; null for nothing
      Returns:
      this field
    • setTrailingButton

      public TextField setTrailingButton(@Nullable Icon icon, @Nullable I18nString name, @Nullable Runnable action, Icon.Mirroring mirroring)
      A named trailing button whose icon says whether it turns around when the interface does.

      A second call replaces the button whole — icon, name and action — because the button is configuration and not a handler slot: a field that swaps a search glass for a clear cross as the text changes is the case it serves. The replacement is announced as CHILDREN/CODE, since the button is a child an assistive technology reads.

      Parameters:
      icon - the glyph, or null to remove the button
      name - what the button does; null leaves it unnamed
      action - what to run when it is pressed; null for nothing
      mirroring - whether the icon turns around in a right-to-left interface
      Returns:
      this field
      Throws:
      NullPointerException - if mirroring is null
    • trailingButtonName

      public @Nullable I18nString trailingButtonName()
      Returns:
      what the trailing button does, said in words, or null when it has no name or there is no trailing button
    • setValidation

      public TextField setValidation(Validation state)
      Sets the validation state; colors the border danger/warning/success.
    • setError

      public TextField setError(boolean error)
      Convenience: ERROR when true, NONE when false.
    • validation

      public Validation validation()
      The current validation state, which drives the border and helper colours.
    • caretPosition

      public int caretPosition()
      Returns:
      where the caret is, as a char offset into text()
    • selectionStart

      public int selectionStart()
      Returns:
      where the selection starts, or the caret's offset when nothing is selected
    • selectionEnd

      public int selectionEnd()
      Returns:
      where the selection ends, or the caret's offset when nothing is selected
    • selectedText

      public String selectedText()
      Returns:
      the selected text, empty when nothing is selected
    • setCaretPosition

      public TextField setCaretPosition(int offset)
      Puts the caret at an offset and selects nothing. See select(int, int).
      Parameters:
      offset - a char offset, from 0 to the text's length
      Returns:
      this TextField
      Throws:
      IndexOutOfBoundsException - when offset is outside the text
    • select

      public TextField select(int anchor, int caret)
      Selects from anchor to caret, and the caret ends at caret, so a caret before the anchor is a selection made backwards, as Shift+Left makes one. An offset inside a grapheme cluster (a combining mark, an emoji sequence) moves to the start of that cluster, because a caret is never drawn inside one. Announces SELECTION as CODE when the caret or the selection moved, and reaches no handler. UI thread only.
      Parameters:
      anchor - where the selection starts, a char offset from 0 to the text's length
      caret - where it ends and the caret goes, likewise
      Returns:
      this TextField
      Throws:
      IndexOutOfBoundsException - when either offset is outside the text
    • selectAll

      public TextField selectAll()
      Selects the whole text, the caret at its end. See select(int, int).
      Returns:
      this TextField
    • allowClipboardCopy

      protected boolean allowClipboardCopy()
      Whether copy/cut may export the content (password fields say no).
    • shapeDisplay

      protected ShapedText shapeDisplay(String text, Font font)
      The display form of this field's content as a shaped line: the one place a subclass changes what is drawn and how wide it is.

      Its index space is the model's. ShapedText.caretX(limn.graphics.ShapedText.Position), ShapedText.hitTest(float) and selection on the returned value take and return offsets into text, with no translation anywhere in this component. That is what deletes the prefix arithmetic the caret used to rest on rather than moving it one layer down, and it is the whole contract: an override that returns a line shaped from some other string, with its own boundaries, puts the caret on a neighbour of the character it edits and a click one mark away from the pointer. An override that substitutes marks keeps text as the returned value's ShapedText.text() and changes only the geometry — ShapedText.uniform(java.lang.String, limn.graphics.Font, float, limn.graphics.TextMetrics, long) builds exactly that, from one multiplication, with no glyphs and without the content reaching a shaper at all.

      font is the font this line must be shaped for, and it is half the key the held value is refreshed against, so an override that shapes in some other font makes that value lie about when it is stale. There is deliberately no SizeTokens parameter: the font is the only thing in that row a display line can legitimately depend on, and two ways to reach it is one too many.

      An override whose display form depends on its own state — a reveal toggle — must call invalidateDisplayLine() when that state changes: the key is text, font and ruler epoch, and it cannot see a field it does not know about.

      Parameters:
      text - the model's text, which is the index space of the result
      font - the font the line is drawn in
      Returns:
      the shaped display line; never null
    • paintDisplayText

      protected void paintDisplayText(Canvas canvas, ShapedText display, float x, float baseline, TextMetrics metrics, SizeTokens t, Color ink)
      Draws a display line with its left edge at x: the paint-side twin of shapeDisplay(java.lang.String, limn.graphics.Font). metrics is passed rather than only the baseline so an override can place ink against the same band the caret and the selection fill use: the ink box starts at baseline - metrics.ascent() and is metrics.height() tall.
      Parameters:
      canvas - where to draw
      display - the shaped display line, as shapeDisplay(java.lang.String, limn.graphics.Font) produced it
      x - left edge of the line, in this widget's coordinates
      baseline - the text baseline, in this widget's coordinates
      metrics - the line's vertical band
      t - the size row resolved for this pass
      ink - the colour to draw in
    • invalidateDisplayLine

      protected final void invalidateDisplayLine()
      Drops the held display line, so the next paint rebuilds it through shapeDisplay(java.lang.String, limn.graphics.Font).

      For a subclass whose display form depends on state of its own: the held value is refreshed against the text, the font and the ruler's epoch, and none of those changes when a reveal toggle does.

    • onMeasure

      protected Size onMeasure(Constraints constraints)
      Description copied from class: Widget
      Reports the size this widget wants within constraints. Called once per layout pass, and the result is cached against the constraints and the resolved axes (size step, layout direction, locale), so it must be a pure function of them and of this widget's own state.

      Resolve the ControlSize and the LayoutDirection once each here and thread them down; never read either in a constructor. The locale needs no threading: it is in scope, and I18n.locale() answers it wherever text is resolved.

      Specified by:
      onMeasure in class Widget<TextField>
    • baselineOffset

      protected float baselineOffset()
      Description copied from class: Widget
      Distance from this widget's top edge to its first text baseline, in logical points: the alignment reference for Flex.CrossAlignment.BASELINE. Default height(): align on the bottom edge, the correct fallback for a widget with no text. Text-bearing components override with the expression they already paint with; a single-line control's is textRuler().centredBaseline(font, height()), which stands the line's capitals in the middle of the box.

      Valid only once this widget has been given a box. Flex guarantees that: it lays every child of a BASELINE line out at cross position 0 first, reads the baselines, then repositions with Widget.moveChild(limn.scene.Widget<?>, int), which moves without re-running layout.

      Overrides:
      baselineOffset in class Widget<TextField>
    • onPaint

      protected void onPaint(Canvas canvas)
      Description copied from class: Widget
      Widget's own background/content, in local coordinates.
      Overrides:
      onPaint in class Widget<TextField>
    • onMouseEvent

      protected void onMouseEvent(MouseEvent event)
      Description copied from class: Widget
      Mouse events (bubbling); call event.consume() when handled.
      Overrides:
      onMouseEvent in class Widget<TextField>
    • onCanEdit

      protected boolean onCanEdit(EditCommand command)
      Description copied from class: Widget
      Whether this widget can do an editing command now: copy with something selected, paste with something to paste, undo with something to take back. Scene.canEdit(limn.scene.EditCommand) asks the widget that has the keyboard and then each of its ancestors, and a menu's item of an editing role is enabled by the answer.

      A widget answers for the commands it takes from the keyboard, and does for the command what it does for the key.

      Overrides:
      onCanEdit in class Widget<TextField>
      Returns:
      false here: a widget edits nothing until it says so
    • onEdit

      protected boolean onEdit(EditCommand command)
      Description copied from class: Widget
      Does an editing command, as the user's own act. Called on the first widget, from the one with the keyboard upward, whose Widget.onCanEdit(limn.scene.EditCommand) answered true.
      Overrides:
      onEdit in class Widget<TextField>
      Returns:
      whether it was done
    • onKeyEvent

      protected void onKeyEvent(KeyEvent event)
      Description copied from class: Widget
      Key events (focused widget first, then ancestors).
      Overrides:
      onKeyEvent in class Widget<TextField>
    • onCharTyped

      protected void onCharTyped(CharEvent event)
      Description copied from class: Widget
      Committed text input (focused widget first, then ancestors).
      Overrides:
      onCharTyped in class Widget<TextField>
    • acceptsTextInput

      protected boolean acceptsTextInput()
      Description copied from class: Widget
      Whether this widget edits text and should drive the platform input method (IME): the scene enables the IME while such a widget holds focus and disables it otherwise, so composition never intercepts keys meant for non-text UI. Text widgets override this to true. Default: false.
      Overrides:
      acceptsTextInput in class Widget<TextField>
    • allowsWordJumps

      protected boolean allowsWordJumps()
      Whether modifier+arrow/delete may move word-wise (see PasswordField).
    • composingText

      public String composingText()
      Returns:
      the text currently being composed by the IME (empty when not composing)
    • onPreedit

      protected void onPreedit(PreeditEvent event)
      Description copied from class: Widget
      In-progress IME composition ("preedit") for this widget while it is focused: the still-composing text, shown inline but not yet committed (the commit later arrives as Widget.onCharTyped(limn.scene.event.CharEvent)). Only widgets that accept text input receive it. Default: ignored.
      Overrides:
      onPreedit in class Widget<TextField>
    • caretRect

      protected @Nullable Rect caretRect()
      Description copied from class: Widget
      The caret rectangle in scene coordinates (logical points) used to place the IME candidate window; null when there is no caret to anchor (or the widget is not laid out yet). Consulted by the scene only while this widget is focused and Widget.acceptsTextInput() is true.
      Overrides:
      caretRect in class Widget<TextField>
    • showContextMenu

      protected void showContextMenu(float localX, float localY)
      Raises the Cut/Copy/Paste/Select All menu at a point in this widget's own coordinates.

      Protected so a subclass with different clipboard rules can suppress or replace it; PasswordField does not need to, because allowClipboardCopy() already greys the two rows that would let a secret out.

    • showContextMenuForFocus

      protected void showContextMenuForFocus()
      Raises the same menu for a request that carries no point: the Menu key or Shift+F10, where the caret is the only place the user can have meant. Protected for the same reason as its pointer twin, and a subclass suppressing one has to suppress both.
    • onAccessibility

      protected void onAccessibility(Accessibility a)
      One text field: what it is, what is in it, where the caret and the selection are, and — when there is one — the trailing button as a child node of its own.

      The name is the placeholder, handed over as the I18nString this widget holds and never as a resolved string, and an unset one is I18nString.EMPTY, which names nothing and leaves the walk's tooltip default somewhere to go. The order that falls out is the right one and costs no application a line: an explicit name wins, then a bound Label's caption, then the placeholder — the field's own visible word for what goes in it — and then the tooltip, which becomes the description instead when the placeholder already named the node.

      No description of its own, a mask's pattern included. The pattern is syntax and not words: AA-0000 read aloud is "A A dash zero zero zero zero" where it means two letters and four digits, in every language; the toolkit cannot word a pattern of the application's in the user's language either, since its literals and counts are the application's; and a description set here would take the tooltip's place, which the walk gives only to a node with none. So the field describes nothing, and what it expects is said by the application in its own words, a tooltip or Widget.setAccessibleDescription(limn.i18n.I18nString), while the literals the field writes are read as part of its text. The validation message beside a field is a Label the application owns and binds with Label.setDescriptionFor(limn.scene.Widget<?>), which is what makes it the field's description and gives the field a DESCRIBED_BY relation to it; this widget holds no string for it, and what setValidation(limn.components.Validation) holds is a colour.

      Overrides:
      onAccessibility in class Widget<TextField>
      Parameters:
      a - the node being described; write into it, and never keep it
    • onAccessibilityAction

      protected boolean onAccessibilityAction(Accessible.Action action, Accessible.Argument arg)
      Raises the context menu, replaces the contents, moves the caret or sets the selection, each through the path the user's own gesture takes; the rules are TextAccessibility's.
      Overrides:
      onAccessibilityAction in class Widget<TextField>
      Parameters:
      action - what is being asked
      arg - the text for SET_TEXT and the range for the other two
      Returns:
      whether this widget did it
    • onSyntheticAction

      protected boolean onSyntheticAction(long key, Accessible.Action action, Accessible.Argument arg)
      Presses the trailing button, if there is one and this field is enabled.
      Overrides:
      onSyntheticAction in class Widget<TextField>
      Parameters:
      key - the synthetic child's key
      action - what was asked
      arg - unused; the press takes no argument
      Returns:
      whether this widget did it
    • onFocusGained

      protected void onFocusGained()
      Description copied from class: Widget
      Called when this widget takes keyboard focus. Default: nothing.
      Overrides:
      onFocusGained in class Widget<TextField>
    • onFocusLost

      protected void onFocusLost()
      Description copied from class: Widget
      Called when this widget loses keyboard focus. Default: nothing.
      Overrides:
      onFocusLost in class Widget<TextField>