< prev index next >

modules/javafx.controls/src/main/java/javafx/scene/control/TextInputControl.java

Print this page




  70 import com.sun.javafx.util.Utils;
  71 import com.sun.javafx.binding.ExpressionHelper;
  72 import com.sun.javafx.scene.NodeHelper;
  73 import javafx.util.StringConverter;
  74 
  75 /**
  76  * Abstract base class for text input controls.
  77  * @since JavaFX 2.0
  78  */
  79 @DefaultProperty("text")
  80 public abstract class TextInputControl extends Control {
  81     /**
  82      * Interface representing a text input's content. Since it is an ObservableStringValue,
  83      * you can also bind to, or observe the content.
  84      * @since JavaFX 2.0
  85      */
  86     protected interface Content extends ObservableStringValue {
  87         /**
  88          * Retrieves a subset of the content.
  89          *
  90          * @param start
  91          * @param end

  92          */
  93         public String get(int start, int end);
  94 
  95         /**
  96          * Inserts a sequence of characters into the content.
  97          *
  98          * @param index
  99          * @param text

 100          * @since JavaFX 2.1
 101          */
 102         public void insert(int index, String text, boolean notifyListeners);
 103 
 104         /**
 105          * Removes a sequence of characters from the content.
 106          *
 107          * @param start
 108          * @param end

 109          * @since JavaFX 2.1
 110          */
 111         public void delete(int start, int end, boolean notifyListeners);
 112 
 113         /**
 114          * Returns the number of characters represented by the content.

 115          */
 116         public int length();
 117     }
 118 
 119     /***************************************************************************
 120      *                                                                         *
 121      * Constructors                                                            *
 122      *                                                                         *
 123      **************************************************************************/
 124 
 125     /**
 126      * Creates a new TextInputControl. The content is an immutable property and
 127      * must be specified (as non-null) at the time of construction.
 128      *
 129      * @param content a non-null implementation of Content.
 130      */
 131     protected TextInputControl(final Content content) {
 132         this.content = content;
 133 
 134         // Add a listener so that whenever the Content is changed, we notify


 174             } else {
 175                 commitValue();
 176             }
 177         });
 178 
 179         // Specify the default style class
 180         getStyleClass().add("text-input");
 181     }
 182 
 183     /***************************************************************************
 184      *                                                                         *
 185      * Properties                                                              *
 186      *                                                                         *
 187      **************************************************************************/
 188 
 189     /**
 190      * The default font to use for text in the TextInputControl. If the TextInputControl's text is
 191      * rich text then this font may or may not be used depending on the font
 192      * information embedded in the rich text, but in any case where a default
 193      * font is required, this font will be used.

 194      * @since JavaFX 8.0
 195      */
 196     public final ObjectProperty<Font> fontProperty() {
 197         if (font == null) {
 198             font = new StyleableObjectProperty<Font>(Font.getDefault()) {
 199 
 200 
 201                 private boolean fontSetByCss = false;
 202 
 203                 @Override
 204                 public void applyStyle(StyleOrigin newOrigin, Font value) {
 205 
 206                     //
 207                     // RT-20727 - if CSS is setting the font, then make sure invalidate doesn't call NodeHelper.reapplyCSS
 208                     //
 209                     try {
 210                         // super.applyStyle calls set which might throw if value is bound.
 211                         // Have to make sure fontSetByCss is reset.
 212                         fontSetByCss = true;
 213                         super.applyStyle(newOrigin, value);


 322                     if (!isFocused()) {
 323                         updateText(get());
 324                     }
 325                 }
 326 
 327                 if (oldFormatter != null) {
 328                     oldFormatter.unbindFromControl();
 329                 }
 330             } finally {
 331                 oldFormatter = formatter;
 332             }
 333         }
 334     };
 335     public final ObjectProperty<TextFormatter<?>> textFormatterProperty() { return textFormatter; }
 336     public final TextFormatter<?> getTextFormatter() { return textFormatter.get(); }
 337     public final void setTextFormatter(TextFormatter<?> value) { textFormatter.set(value); }
 338 
 339     private final Content content;
 340     /**
 341      * Returns the text input's content model.

 342      */
 343     protected final Content getContent() {
 344         return content;
 345     }
 346 
 347     /**
 348      * The textual content of this TextInputControl.
 349      */
 350     private TextProperty text = new TextProperty();
 351     public final String getText() { return text.get(); }
 352     public final void setText(String value) { text.set(value); }
 353     public final StringProperty textProperty() { return text; }
 354 
 355     /**
 356      * The number of characters in the text input.
 357      */
 358     private ReadOnlyIntegerWrapper length = new ReadOnlyIntegerWrapper(this, "length");
 359     public final int getLength() { return length.get(); }
 360     public final ReadOnlyIntegerProperty lengthProperty() { return length.getReadOnlyProperty(); }
 361 


 426     /**
 427      * The property describes if it's currently possible to redo the latest change of the content that was undone.
 428      * @defaultValue false
 429      * @since JavaFX 8u40
 430      */
 431     private final ReadOnlyBooleanWrapper redoable = new ReadOnlyBooleanWrapper(this, "redoable", false);
 432     public final boolean isRedoable() { return redoable.get(); }
 433     public final ReadOnlyBooleanProperty redoableProperty() { return redoable.getReadOnlyProperty(); }
 434 
 435     /***************************************************************************
 436      *                                                                         *
 437      * Methods                                                                 *
 438      *                                                                         *
 439      **************************************************************************/
 440 
 441     /**
 442      * Returns a subset of the text input's content.
 443      *
 444      * @param start must be a value between 0 and end - 1.
 445      * @param end must be less than or equal to the length

 446      */
 447     public String getText(int start, int end) {
 448         if (start > end) {
 449             throw new IllegalArgumentException("The start must be <= the end");
 450         }
 451 
 452         if (start < 0
 453             || end > getLength()) {
 454             throw new IndexOutOfBoundsException();
 455         }
 456 
 457         return getContent().get(start, end);
 458     }
 459 
 460     /**
 461      * Appends a sequence of characters to the content.
 462      *
 463      * @param text a non null String
 464      */
 465     public void appendText(String text) {


 863      * caretPosition is moved to before the first char.
 864      */
 865     public void selectHome() {
 866         selectRange(getAnchor(), 0);
 867     }
 868 
 869     /**
 870      * Moves the caret to after the last char of text. This does not cause
 871      * the selection to be cleared. Rather, the anchor stays put and the
 872      * caretPosition is moved to after the last char.
 873      */
 874     public void selectEnd() {
 875         final int textLength = getLength();
 876         if (textLength > 0) selectRange(getAnchor(), textLength);
 877     }
 878 
 879     /**
 880      * Deletes the character that precedes the current caret position from the
 881      * text if there is no selection, or deletes the selection if there is one.
 882      * This function returns true if the deletion succeeded, false otherwise.

 883      */
 884     public boolean deletePreviousChar() {
 885         boolean failed = true;
 886         if (isEditable() && !isDisabled()) {
 887             final String text = getText();
 888             final int dot = getCaretPosition();
 889             final int mark = getAnchor();
 890             if (dot != mark) {
 891                 // there is a selection of text to remove
 892                 replaceSelection("");
 893                 failed = false;
 894             } else if (dot > 0) {
 895                 // The caret is not at the beginning, so remove some characters.
 896                 // Typically you'd only be removing a single character, but
 897                 // in some cases you must remove two depending on the unicode
 898                 // characters
 899                 // Note: Do not use charIterator here, because we do want to
 900                 // break up clusters when deleting backwards.
 901                 int p = Character.offsetByCodePoints(text, dot, -1);
 902                 deleteText(p, dot);
 903                 failed = false;
 904             }
 905         }
 906         return !failed;
 907     }
 908 
 909     /**
 910      * Deletes the character that follows the current caret position from the
 911      * text if there is no selection, or deletes the selection if there is one.
 912      * This function returns true if the deletion succeeded, false otherwise.

 913      */
 914     public boolean deleteNextChar() {
 915         boolean failed = true;
 916         if (isEditable() && !isDisabled()) {
 917             final int textLength = getLength();
 918             final String text = getText();
 919             final int dot = getCaretPosition();
 920             final int mark = getAnchor();
 921             if (dot != mark) {
 922                 // there is a selection of text to remove
 923                 replaceSelection("");
 924                 failed = false;
 925             } else if (textLength > 0 && dot < textLength) {
 926                 // The caret is not at the end, so remove some characters.
 927                 // Typically you'd only be removing a single character, but
 928                 // in some cases you must remove two depending on the unicode
 929                 // characters
 930                 if (charIterator == null) {
 931                     charIterator = BreakIterator.getCharacterInstance();
 932                 }


 953         if (dot != mark) {
 954             int pos = Math.max(dot, mark);
 955             selectRange(pos, pos);
 956         } else if (dot < textLength && textLength > 0) {
 957             if (charIterator == null) {
 958                 charIterator = BreakIterator.getCharacterInstance();
 959             }
 960             charIterator.setText(getText());
 961             int pos = charIterator.following(dot);
 962             selectRange(pos, pos);
 963         }
 964         deselect();
 965     }
 966 
 967     /**
 968      * Moves the caret position backward. If there is no selection, then the
 969      * caret position is moved one character backward. If there is a selection,
 970      * then the caret position is moved to the beginning of the selection and
 971      * the selection cleared.
 972      *
 973      * @expert This function is intended to be used by experts, primarily
 974      *         by those implementing new Skins or Behaviors. It is not common
 975      *         for developers or designers to access this function directly.
 976      */
 977     public void backward() {
 978         // user has moved caret to the left
 979         final int textLength = getLength();
 980         final int dot = getCaretPosition();
 981         final int mark = getAnchor();
 982         if (dot != mark) {
 983             int pos = Math.min(dot, mark);
 984             selectRange(pos, pos);
 985         } else if (dot > 0 && textLength > 0) {
 986             if (charIterator == null) {
 987                 charIterator = BreakIterator.getCharacterInstance();
 988             }
 989             charIterator.setText(getText());
 990             int pos = charIterator.preceding(dot);
 991             selectRange(pos, pos);
 992         }
 993         deselect();
 994     }
 995 
 996     /**
 997      * Positions the caret to the position indicated by {@code pos}. This
 998      * function will also clear the selection.

 999      */
1000     public void positionCaret(int pos) {
1001         final int p = Utils.clamp(0, pos, getLength());
1002         selectRange(p, p);
1003     }
1004 
1005     /**
1006      * Positions the caret to the position indicated by {@code pos} and extends
1007      * the selection, if there is one. If there is no selection, then a
1008      * selection is formed where the anchor is at the current caret position
1009      * and the caretPosition is moved to pos.

1010      */
1011     public void selectPositionCaret(int pos) {
1012         selectRange(getAnchor(), Utils.clamp(0, pos, getLength()));
1013     }
1014 
1015     /**
1016      * Positions the anchor and caretPosition explicitly.


1017      */
1018     public void selectRange(int anchor, int caretPosition) {
1019         caretPosition = Utils.clamp(0, caretPosition, getLength());
1020         anchor = Utils.clamp(0, anchor, getLength());
1021 
1022         TextFormatter.Change change = new TextFormatter.Change(this, getFormatterAccessor(), anchor, caretPosition);
1023         TextFormatter<?> formatter = getTextFormatter();
1024         if (formatter != null && formatter.getFilter() != null) {
1025             change = formatter.getFilter().apply(change);
1026             if (change == null) {
1027                 return;
1028             }
1029         }
1030 
1031         updateContent(change, false);
1032     }
1033 
1034     private void doSelectRange(int anchor, int caretPosition) {
1035         this.caretPosition.set(Utils.clamp(0, caretPosition, getLength()));
1036         this.anchor.set(Utils.clamp(0, anchor, getLength()));
1037         this.selection.set(IndexRange.normalize(getAnchor(), getCaretPosition()));
1038         notifyAccessibleAttributeChanged(AccessibleAttribute.SELECTION_START);
1039     }
1040 
1041     /**
1042      * This function will extend the selection to include the specified pos.
1043      * This is different from selectPositionCaret in that it does not simply
1044      * move the caret. Rather, it will reposition the caret and anchor as necessary
1045      * to ensure that pos becomes the new caret and the far other end of the
1046      * selection becomes the anchor.

1047      */
1048     public void extendSelection(int pos) {
1049         final int p = Utils.clamp(0, pos, getLength());
1050         final int dot = getCaretPosition();
1051         final int mark = getAnchor();
1052         int start = Math.min(dot, mark);
1053         int end = Math.max(dot, mark);
1054         if (p < start) {
1055             selectRange(end, p);
1056         } else {
1057             selectRange(start, p);
1058         }
1059     }
1060 
1061     /**
1062      * Clears the text.
1063      */
1064     public void clear() {
1065         deselect();
1066         if (!text.isBound()) {
1067             setText("");
1068         }
1069     }
1070 
1071     /**
1072      * Clears the selection.
1073      */
1074     public void deselect() {
1075         // set the anchor equal to the caret position, which clears the selection
1076         // while also preserving the caret position
1077         selectRange(getCaretPosition(), getCaretPosition());
1078     }
1079 
1080     /**
1081      * Replaces the selection with the given replacement String. If there is
1082      * no selection, then the replacement text is simply inserted at the current
1083      * caret position. If there was a selection, then the selection is cleared
1084      * and the given replacement text inserted.

1085      */
1086     public void replaceSelection(String replacement) {
1087         replaceText(getSelection(), replacement);
1088     }
1089 
1090     /**
1091      * If possible, undoes the last modification. If {@link #isUndoable()} returns
1092      * false, then calling this method has no effect.
1093      * @since JavaFX 8u40
1094      */
1095     public final void undo() {
1096         if (isUndoable()) {
1097             // Apply reverse change here
1098             final int start = undoChange.start;
1099             final String newText = undoChange.newText;
1100             final String oldText = undoChange.oldText;
1101 
1102             if (newText != null) {
1103                 getContent().delete(start, start + newText.length(), oldText.isEmpty());
1104             }




  70 import com.sun.javafx.util.Utils;
  71 import com.sun.javafx.binding.ExpressionHelper;
  72 import com.sun.javafx.scene.NodeHelper;
  73 import javafx.util.StringConverter;
  74 
  75 /**
  76  * Abstract base class for text input controls.
  77  * @since JavaFX 2.0
  78  */
  79 @DefaultProperty("text")
  80 public abstract class TextInputControl extends Control {
  81     /**
  82      * Interface representing a text input's content. Since it is an ObservableStringValue,
  83      * you can also bind to, or observe the content.
  84      * @since JavaFX 2.0
  85      */
  86     protected interface Content extends ObservableStringValue {
  87         /**
  88          * Retrieves a subset of the content.
  89          *
  90          * @param start the start
  91          * @param end the end
  92          * @return a subset of the content
  93          */
  94         public String get(int start, int end);
  95 
  96         /**
  97          * Inserts a sequence of characters into the content.
  98          *
  99          * @param index the index
 100          * @param text the text string
 101          * @param notifyListeners the notify listener flag
 102          * @since JavaFX 2.1
 103          */
 104         public void insert(int index, String text, boolean notifyListeners);
 105 
 106         /**
 107          * Removes a sequence of characters from the content.
 108          *
 109          * @param start the start
 110          * @param end the end
 111          * @param notifyListeners the notify listener flag
 112          * @since JavaFX 2.1
 113          */
 114         public void delete(int start, int end, boolean notifyListeners);
 115 
 116         /**
 117          * Returns the number of characters represented by the content.
 118          * @return the number of characters
 119          */
 120         public int length();
 121     }
 122 
 123     /***************************************************************************
 124      *                                                                         *
 125      * Constructors                                                            *
 126      *                                                                         *
 127      **************************************************************************/
 128 
 129     /**
 130      * Creates a new TextInputControl. The content is an immutable property and
 131      * must be specified (as non-null) at the time of construction.
 132      *
 133      * @param content a non-null implementation of Content.
 134      */
 135     protected TextInputControl(final Content content) {
 136         this.content = content;
 137 
 138         // Add a listener so that whenever the Content is changed, we notify


 178             } else {
 179                 commitValue();
 180             }
 181         });
 182 
 183         // Specify the default style class
 184         getStyleClass().add("text-input");
 185     }
 186 
 187     /***************************************************************************
 188      *                                                                         *
 189      * Properties                                                              *
 190      *                                                                         *
 191      **************************************************************************/
 192 
 193     /**
 194      * The default font to use for text in the TextInputControl. If the TextInputControl's text is
 195      * rich text then this font may or may not be used depending on the font
 196      * information embedded in the rich text, but in any case where a default
 197      * font is required, this font will be used.
 198      * @return the font property
 199      * @since JavaFX 8.0
 200      */
 201     public final ObjectProperty<Font> fontProperty() {
 202         if (font == null) {
 203             font = new StyleableObjectProperty<Font>(Font.getDefault()) {
 204 
 205 
 206                 private boolean fontSetByCss = false;
 207 
 208                 @Override
 209                 public void applyStyle(StyleOrigin newOrigin, Font value) {
 210 
 211                     //
 212                     // RT-20727 - if CSS is setting the font, then make sure invalidate doesn't call NodeHelper.reapplyCSS
 213                     //
 214                     try {
 215                         // super.applyStyle calls set which might throw if value is bound.
 216                         // Have to make sure fontSetByCss is reset.
 217                         fontSetByCss = true;
 218                         super.applyStyle(newOrigin, value);


 327                     if (!isFocused()) {
 328                         updateText(get());
 329                     }
 330                 }
 331 
 332                 if (oldFormatter != null) {
 333                     oldFormatter.unbindFromControl();
 334                 }
 335             } finally {
 336                 oldFormatter = formatter;
 337             }
 338         }
 339     };
 340     public final ObjectProperty<TextFormatter<?>> textFormatterProperty() { return textFormatter; }
 341     public final TextFormatter<?> getTextFormatter() { return textFormatter.get(); }
 342     public final void setTextFormatter(TextFormatter<?> value) { textFormatter.set(value); }
 343 
 344     private final Content content;
 345     /**
 346      * Returns the text input's content model.
 347      * @return the text input's content model
 348      */
 349     protected final Content getContent() {
 350         return content;
 351     }
 352 
 353     /**
 354      * The textual content of this TextInputControl.
 355      */
 356     private TextProperty text = new TextProperty();
 357     public final String getText() { return text.get(); }
 358     public final void setText(String value) { text.set(value); }
 359     public final StringProperty textProperty() { return text; }
 360 
 361     /**
 362      * The number of characters in the text input.
 363      */
 364     private ReadOnlyIntegerWrapper length = new ReadOnlyIntegerWrapper(this, "length");
 365     public final int getLength() { return length.get(); }
 366     public final ReadOnlyIntegerProperty lengthProperty() { return length.getReadOnlyProperty(); }
 367 


 432     /**
 433      * The property describes if it's currently possible to redo the latest change of the content that was undone.
 434      * @defaultValue false
 435      * @since JavaFX 8u40
 436      */
 437     private final ReadOnlyBooleanWrapper redoable = new ReadOnlyBooleanWrapper(this, "redoable", false);
 438     public final boolean isRedoable() { return redoable.get(); }
 439     public final ReadOnlyBooleanProperty redoableProperty() { return redoable.getReadOnlyProperty(); }
 440 
 441     /***************************************************************************
 442      *                                                                         *
 443      * Methods                                                                 *
 444      *                                                                         *
 445      **************************************************************************/
 446 
 447     /**
 448      * Returns a subset of the text input's content.
 449      *
 450      * @param start must be a value between 0 and end - 1.
 451      * @param end must be less than or equal to the length
 452      * @return the subset of the text input's content
 453      */
 454     public String getText(int start, int end) {
 455         if (start > end) {
 456             throw new IllegalArgumentException("The start must be <= the end");
 457         }
 458 
 459         if (start < 0
 460             || end > getLength()) {
 461             throw new IndexOutOfBoundsException();
 462         }
 463 
 464         return getContent().get(start, end);
 465     }
 466 
 467     /**
 468      * Appends a sequence of characters to the content.
 469      *
 470      * @param text a non null String
 471      */
 472     public void appendText(String text) {


 870      * caretPosition is moved to before the first char.
 871      */
 872     public void selectHome() {
 873         selectRange(getAnchor(), 0);
 874     }
 875 
 876     /**
 877      * Moves the caret to after the last char of text. This does not cause
 878      * the selection to be cleared. Rather, the anchor stays put and the
 879      * caretPosition is moved to after the last char.
 880      */
 881     public void selectEnd() {
 882         final int textLength = getLength();
 883         if (textLength > 0) selectRange(getAnchor(), textLength);
 884     }
 885 
 886     /**
 887      * Deletes the character that precedes the current caret position from the
 888      * text if there is no selection, or deletes the selection if there is one.
 889      * This function returns true if the deletion succeeded, false otherwise.
 890      * @return true if the deletion succeeded, false otherwise
 891      */
 892     public boolean deletePreviousChar() {
 893         boolean failed = true;
 894         if (isEditable() && !isDisabled()) {
 895             final String text = getText();
 896             final int dot = getCaretPosition();
 897             final int mark = getAnchor();
 898             if (dot != mark) {
 899                 // there is a selection of text to remove
 900                 replaceSelection("");
 901                 failed = false;
 902             } else if (dot > 0) {
 903                 // The caret is not at the beginning, so remove some characters.
 904                 // Typically you'd only be removing a single character, but
 905                 // in some cases you must remove two depending on the unicode
 906                 // characters
 907                 // Note: Do not use charIterator here, because we do want to
 908                 // break up clusters when deleting backwards.
 909                 int p = Character.offsetByCodePoints(text, dot, -1);
 910                 deleteText(p, dot);
 911                 failed = false;
 912             }
 913         }
 914         return !failed;
 915     }
 916 
 917     /**
 918      * Deletes the character that follows the current caret position from the
 919      * text if there is no selection, or deletes the selection if there is one.
 920      * This function returns true if the deletion succeeded, false otherwise.
 921      * @return true if the deletion succeeded, false otherwise
 922      */
 923     public boolean deleteNextChar() {
 924         boolean failed = true;
 925         if (isEditable() && !isDisabled()) {
 926             final int textLength = getLength();
 927             final String text = getText();
 928             final int dot = getCaretPosition();
 929             final int mark = getAnchor();
 930             if (dot != mark) {
 931                 // there is a selection of text to remove
 932                 replaceSelection("");
 933                 failed = false;
 934             } else if (textLength > 0 && dot < textLength) {
 935                 // The caret is not at the end, so remove some characters.
 936                 // Typically you'd only be removing a single character, but
 937                 // in some cases you must remove two depending on the unicode
 938                 // characters
 939                 if (charIterator == null) {
 940                     charIterator = BreakIterator.getCharacterInstance();
 941                 }


 962         if (dot != mark) {
 963             int pos = Math.max(dot, mark);
 964             selectRange(pos, pos);
 965         } else if (dot < textLength && textLength > 0) {
 966             if (charIterator == null) {
 967                 charIterator = BreakIterator.getCharacterInstance();
 968             }
 969             charIterator.setText(getText());
 970             int pos = charIterator.following(dot);
 971             selectRange(pos, pos);
 972         }
 973         deselect();
 974     }
 975 
 976     /**
 977      * Moves the caret position backward. If there is no selection, then the
 978      * caret position is moved one character backward. If there is a selection,
 979      * then the caret position is moved to the beginning of the selection and
 980      * the selection cleared.
 981      *
 982      * Note: This function is intended to be used by experts, primarily
 983      *       by those implementing new Skins or Behaviors. It is not common
 984      *       for developers or designers to access this function directly.
 985      */
 986     public void backward() {
 987         // user has moved caret to the left
 988         final int textLength = getLength();
 989         final int dot = getCaretPosition();
 990         final int mark = getAnchor();
 991         if (dot != mark) {
 992             int pos = Math.min(dot, mark);
 993             selectRange(pos, pos);
 994         } else if (dot > 0 && textLength > 0) {
 995             if (charIterator == null) {
 996                 charIterator = BreakIterator.getCharacterInstance();
 997             }
 998             charIterator.setText(getText());
 999             int pos = charIterator.preceding(dot);
1000             selectRange(pos, pos);
1001         }
1002         deselect();
1003     }
1004 
1005     /**
1006      * Positions the caret to the position indicated by {@code pos}. This
1007      * function will also clear the selection.
1008      * @param pos the position
1009      */
1010     public void positionCaret(int pos) {
1011         final int p = Utils.clamp(0, pos, getLength());
1012         selectRange(p, p);
1013     }
1014 
1015     /**
1016      * Positions the caret to the position indicated by {@code pos} and extends
1017      * the selection, if there is one. If there is no selection, then a
1018      * selection is formed where the anchor is at the current caret position
1019      * and the caretPosition is moved to pos.
1020      * @param pos the position
1021      */
1022     public void selectPositionCaret(int pos) {
1023         selectRange(getAnchor(), Utils.clamp(0, pos, getLength()));
1024     }
1025 
1026     /**
1027      * Positions the anchor and caretPosition explicitly.
1028      * @param anchor the anchor
1029      * @param caretPosition the caretPosition
1030      */
1031     public void selectRange(int anchor, int caretPosition) {
1032         caretPosition = Utils.clamp(0, caretPosition, getLength());
1033         anchor = Utils.clamp(0, anchor, getLength());
1034 
1035         TextFormatter.Change change = new TextFormatter.Change(this, getFormatterAccessor(), anchor, caretPosition);
1036         TextFormatter<?> formatter = getTextFormatter();
1037         if (formatter != null && formatter.getFilter() != null) {
1038             change = formatter.getFilter().apply(change);
1039             if (change == null) {
1040                 return;
1041             }
1042         }
1043 
1044         updateContent(change, false);
1045     }
1046 
1047     private void doSelectRange(int anchor, int caretPosition) {
1048         this.caretPosition.set(Utils.clamp(0, caretPosition, getLength()));
1049         this.anchor.set(Utils.clamp(0, anchor, getLength()));
1050         this.selection.set(IndexRange.normalize(getAnchor(), getCaretPosition()));
1051         notifyAccessibleAttributeChanged(AccessibleAttribute.SELECTION_START);
1052     }
1053 
1054     /**
1055      * This function will extend the selection to include the specified pos.
1056      * This is different from selectPositionCaret in that it does not simply
1057      * move the caret. Rather, it will reposition the caret and anchor as necessary
1058      * to ensure that pos becomes the new caret and the far other end of the
1059      * selection becomes the anchor.
1060      * @param pos the position
1061      */
1062     public void extendSelection(int pos) {
1063         final int p = Utils.clamp(0, pos, getLength());
1064         final int dot = getCaretPosition();
1065         final int mark = getAnchor();
1066         int start = Math.min(dot, mark);
1067         int end = Math.max(dot, mark);
1068         if (p < start) {
1069             selectRange(end, p);
1070         } else {
1071             selectRange(start, p);
1072         }
1073     }
1074 
1075     /**
1076      * Clears the text.
1077      */
1078     public void clear() {
1079         deselect();
1080         if (!text.isBound()) {
1081             setText("");
1082         }
1083     }
1084 
1085     /**
1086      * Clears the selection.
1087      */
1088     public void deselect() {
1089         // set the anchor equal to the caret position, which clears the selection
1090         // while also preserving the caret position
1091         selectRange(getCaretPosition(), getCaretPosition());
1092     }
1093 
1094     /**
1095      * Replaces the selection with the given replacement String. If there is
1096      * no selection, then the replacement text is simply inserted at the current
1097      * caret position. If there was a selection, then the selection is cleared
1098      * and the given replacement text inserted.
1099      * @param replacement the replacement string
1100      */
1101     public void replaceSelection(String replacement) {
1102         replaceText(getSelection(), replacement);
1103     }
1104 
1105     /**
1106      * If possible, undoes the last modification. If {@link #isUndoable()} returns
1107      * false, then calling this method has no effect.
1108      * @since JavaFX 8u40
1109      */
1110     public final void undo() {
1111         if (isUndoable()) {
1112             // Apply reverse change here
1113             final int start = undoChange.start;
1114             final String newText = undoChange.newText;
1115             final String oldText = undoChange.oldText;
1116 
1117             if (newText != null) {
1118                 getContent().delete(start, start + newText.length(), oldText.isEmpty());
1119             }


< prev index next >