modules/controls/src/main/java/com/sun/javafx/scene/control/behavior/TextFieldBehavior.java

Print this page
rev 9240 : 8076423: JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization

*** 23,32 **** --- 23,33 ---- * questions. */ package com.sun.javafx.scene.control.behavior; + import com.sun.javafx.scene.control.Properties; import javafx.beans.value.ChangeListener; import javafx.beans.value.WeakChangeListener; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Bounds;
*** 34,52 **** import javafx.geometry.Rectangle2D; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.ContextMenu; import javafx.scene.control.TextField; import javafx.scene.input.ContextMenuEvent; import javafx.scene.input.KeyEvent; import javafx.scene.input.MouseEvent; import javafx.stage.Screen; import javafx.stage.Window; import com.sun.javafx.PlatformUtil; import com.sun.javafx.geom.transform.Affine3D; ! import com.sun.javafx.scene.control.skin.TextFieldSkin; ! import com.sun.javafx.scene.text.HitInfo; import static com.sun.javafx.PlatformUtil.isMac; import static com.sun.javafx.PlatformUtil.isWindows; /** * Text field behavior. --- 35,55 ---- import javafx.geometry.Rectangle2D; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.ContextMenu; import javafx.scene.control.TextField; + import javafx.scene.control.skin.TextFieldSkin; + import com.sun.javafx.scene.control.skin.Utils; import javafx.scene.input.ContextMenuEvent; import javafx.scene.input.KeyEvent; import javafx.scene.input.MouseEvent; import javafx.stage.Screen; import javafx.stage.Window; import com.sun.javafx.PlatformUtil; import com.sun.javafx.geom.transform.Affine3D; ! ! import static javafx.scene.control.skin.TextFieldSkin.TextPosInfo; import static com.sun.javafx.PlatformUtil.isMac; import static com.sun.javafx.PlatformUtil.isWindows; /** * Text field behavior.
*** 57,70 **** private TwoLevelFocusBehavior tlFocus; private ChangeListener<Scene> sceneListener; private ChangeListener<Node> focusOwnerListener; public TextFieldBehavior(final TextField textField) { ! super(textField, TEXT_INPUT_BINDINGS); contextMenu = new ContextMenu(); ! if (IS_TOUCH_SUPPORTED) { contextMenu.getStyleClass().add("text-input-context-menu"); } handleFocusChange(); --- 60,73 ---- private TwoLevelFocusBehavior tlFocus; private ChangeListener<Scene> sceneListener; private ChangeListener<Node> focusOwnerListener; public TextFieldBehavior(final TextField textField) { ! super(textField); contextMenu = new ContextMenu(); ! if (Properties.IS_TOUCH_SUPPORTED) { contextMenu.getStyleClass().add("text-input-context-menu"); } handleFocusChange();
*** 101,122 **** if (textField.getScene() != null) { textField.getScene().focusOwnerProperty().addListener(weakFocusOwnerListener); } // Only add this if we're on an embedded platform that supports 5-button navigation ! if (com.sun.javafx.scene.control.skin.Utils.isTwoLevelFocus()) { tlFocus = new TwoLevelFocusBehavior(textField); // needs to be last. } } @Override public void dispose() { if (tlFocus != null) tlFocus.dispose(); super.dispose(); } private void handleFocusChange() { ! TextField textField = getControl(); if (textField.isFocused()) { if (PlatformUtil.isIOS()) { // special handling of focus on iOS is required to allow to // control native keyboard, because nat. keyboard is poped-up only when native --- 104,125 ---- if (textField.getScene() != null) { textField.getScene().focusOwnerProperty().addListener(weakFocusOwnerListener); } // Only add this if we're on an embedded platform that supports 5-button navigation ! if (Utils.isTwoLevelFocus()) { tlFocus = new TwoLevelFocusBehavior(textField); // needs to be last. } } @Override public void dispose() { if (tlFocus != null) tlFocus.dispose(); super.dispose(); } private void handleFocusChange() { ! TextField textField = getNode(); if (textField.isFocused()) { if (PlatformUtil.isIOS()) { // special handling of focus on iOS is required to allow to // control native keyboard, because nat. keyboard is poped-up only when native
*** 170,180 **** public void setTextFieldSkin(TextFieldSkin skin) { this.skin = skin; } @Override protected void fire(KeyEvent event) { ! TextField textField = getControl(); EventHandler<ActionEvent> onAction = textField.getOnAction(); ActionEvent actionEvent = new ActionEvent(textField, null); textField.fireEvent(actionEvent); textField.commitValue(); --- 173,183 ---- public void setTextFieldSkin(TextFieldSkin skin) { this.skin = skin; } @Override protected void fire(KeyEvent event) { ! TextField textField = getNode(); EventHandler<ActionEvent> onAction = textField.getOnAction(); ActionEvent actionEvent = new ActionEvent(textField, null); textField.fireEvent(actionEvent); textField.commitValue();
*** 184,194 **** } } @Override protected void cancelEdit(KeyEvent event) { ! TextField textField = getControl(); if (textField.getTextFormatter() != null) { textField.cancelEdit(); } else { forwardToParent(event); } --- 187,197 ---- } } @Override protected void cancelEdit(KeyEvent event) { ! TextField textField = getNode(); if (textField.getTextFormatter() != null) { textField.cancelEdit(); } else { forwardToParent(event); }
*** 201,211 **** @Override protected void replaceText(int start, int end, String txt) { skin.replaceText(start, end, txt); } @Override protected void deleteFromLineStart() { ! TextField textField = getControl(); int end = textField.getCaretPosition(); if (end > 0) { replaceText(0, end, ""); } --- 204,214 ---- @Override protected void replaceText(int start, int end, String txt) { skin.replaceText(start, end, txt); } @Override protected void deleteFromLineStart() { ! TextField textField = getNode(); int end = textField.getCaretPosition(); if (end > 0) { replaceText(0, end, ""); }
*** 233,244 **** private boolean focusGainedByMouseClick = false; private boolean shiftDown = false; private boolean deferClick = false; @Override public void mousePressed(MouseEvent e) { ! TextField textField = getControl(); ! super.mousePressed(e); // We never respond to events if disabled if (!textField.isDisabled()) { // If the text field doesn't have focus, then we'll attempt to set // the focus and we'll indicate that we gained focus by a mouse // click, which will then NOT honor the selectOnFocus variable --- 236,246 ---- private boolean focusGainedByMouseClick = false; private boolean shiftDown = false; private boolean deferClick = false; @Override public void mousePressed(MouseEvent e) { ! TextField textField = getNode(); // We never respond to events if disabled if (!textField.isDisabled()) { // If the text field doesn't have focus, then we'll attempt to set // the focus and we'll indicate that we gained focus by a mouse // click, which will then NOT honor the selectOnFocus variable
*** 253,269 **** // only if there is no selection should we see the caret // setCaretOpacity(if (textInputControl.dot == textInputControl.mark) then 1.0 else 0.0); // if the primary button was pressed if (e.isPrimaryButtonDown() && !(e.isMiddleButtonDown() || e.isSecondaryButtonDown())) { ! HitInfo hit = skin.getIndex(e.getX(), e.getY()); String text = textField.textProperty().getValueSafe(); ! int i = com.sun.javafx.scene.control.skin.Utils.getHitInsertionIndex(hit, text); final int anchor = textField.getAnchor(); final int caretPosition = textField.getCaretPosition(); if (e.getClickCount() < 2 && ! (IS_TOUCH_SUPPORTED || (anchor != caretPosition && ((i > anchor && i < caretPosition) || (i < anchor && i > caretPosition))))) { // if there is a selection, then we will NOT handle the // press now, but will defer until the release. If you // select some text and then press down, we change the --- 255,271 ---- // only if there is no selection should we see the caret // setCaretOpacity(if (textInputControl.dot == textInputControl.mark) then 1.0 else 0.0); // if the primary button was pressed if (e.isPrimaryButtonDown() && !(e.isMiddleButtonDown() || e.isSecondaryButtonDown())) { ! TextPosInfo hit = skin.getIndex(e.getX(), e.getY()); String text = textField.textProperty().getValueSafe(); ! int i = Utils.getHitInsertionIndex(hit, text); final int anchor = textField.getAnchor(); final int caretPosition = textField.getCaretPosition(); if (e.getClickCount() < 2 && ! (Properties.IS_TOUCH_SUPPORTED || (anchor != caretPosition && ((i > anchor && i < caretPosition) || (i < anchor && i > caretPosition))))) { // if there is a selection, then we will NOT handle the // press now, but will defer until the release. If you // select some text and then press down, we change the
*** 305,315 **** contextMenu.hide(); } } @Override public void mouseDragged(MouseEvent e) { ! final TextField textField = getControl(); // we never respond to events if disabled, but we do notify any onXXX // event listeners on the control if (!textField.isDisabled() && !deferClick) { if (e.isPrimaryButtonDown() && !(e.isMiddleButtonDown() || e.isSecondaryButtonDown())) { if (!(e.isControlDown() || e.isAltDown() || e.isShiftDown() || e.isMetaDown())) { --- 307,317 ---- contextMenu.hide(); } } @Override public void mouseDragged(MouseEvent e) { ! final TextField textField = getNode(); // we never respond to events if disabled, but we do notify any onXXX // event listeners on the control if (!textField.isDisabled() && !deferClick) { if (e.isPrimaryButtonDown() && !(e.isMiddleButtonDown() || e.isSecondaryButtonDown())) { if (!(e.isControlDown() || e.isAltDown() || e.isShiftDown() || e.isMetaDown())) {
*** 318,329 **** } } } @Override public void mouseReleased(MouseEvent e) { ! final TextField textField = getControl(); ! super.mouseReleased(e); // we never respond to events if disabled, but we do notify any onXXX // event listeners on the control if (!textField.isDisabled()) { setCaretAnimating(false); if (deferClick) { --- 320,330 ---- } } } @Override public void mouseReleased(MouseEvent e) { ! final TextField textField = getNode(); // we never respond to events if disabled, but we do notify any onXXX // event listeners on the control if (!textField.isDisabled()) { setCaretAnimating(false); if (deferClick) {
*** 334,353 **** setCaretAnimating(true); } } @Override public void contextMenuRequested(ContextMenuEvent e) { ! final TextField textField = getControl(); if (contextMenu.isShowing()) { contextMenu.hide(); } else if (textField.getContextMenu() == null) { double screenX = e.getScreenX(); double screenY = e.getScreenY(); double sceneX = e.getSceneX(); ! if (IS_TOUCH_SUPPORTED) { Point2D menuPos; if (textField.getSelection().getLength() == 0) { skin.positionCaret(skin.getIndex(e.getX(), e.getY()), false); menuPos = skin.getMenuPosition(); } else { --- 335,354 ---- setCaretAnimating(true); } } @Override public void contextMenuRequested(ContextMenuEvent e) { ! final TextField textField = getNode(); if (contextMenu.isShowing()) { contextMenu.hide(); } else if (textField.getContextMenu() == null) { double screenX = e.getScreenX(); double screenY = e.getScreenY(); double sceneX = e.getSceneX(); ! if (Properties.IS_TOUCH_SUPPORTED) { Point2D menuPos; if (textField.getSelection().getLength() == 0) { skin.positionCaret(skin.getIndex(e.getX(), e.getY()), false); menuPos = skin.getMenuPosition(); } else {
*** 357,442 **** menuPos = skin.getMenuPosition(); } } if (menuPos != null) { ! Point2D p = getControl().localToScene(menuPos); ! Scene scene = getControl().getScene(); Window window = scene.getWindow(); Point2D location = new Point2D(window.getX() + scene.getX() + p.getX(), window.getY() + scene.getY() + p.getY()); screenX = location.getX(); sceneX = p.getX(); screenY = location.getY(); } } ! skin.populateContextMenu(contextMenu); double menuWidth = contextMenu.prefWidth(-1); ! double menuX = screenX - (IS_TOUCH_SUPPORTED ? (menuWidth / 2) : 0); Screen currentScreen = com.sun.javafx.util.Utils.getScreenForPoint(screenX, 0); Rectangle2D bounds = currentScreen.getBounds(); if (menuX < bounds.getMinX()) { ! getControl().getProperties().put("CONTEXT_MENU_SCREEN_X", screenX); ! getControl().getProperties().put("CONTEXT_MENU_SCENE_X", sceneX); ! contextMenu.show(getControl(), bounds.getMinX(), screenY); } else if (screenX + menuWidth > bounds.getMaxX()) { double leftOver = menuWidth - ( bounds.getMaxX() - screenX); ! getControl().getProperties().put("CONTEXT_MENU_SCREEN_X", screenX); ! getControl().getProperties().put("CONTEXT_MENU_SCENE_X", sceneX); ! contextMenu.show(getControl(), screenX - leftOver, screenY); } else { ! getControl().getProperties().put("CONTEXT_MENU_SCREEN_X", 0); ! getControl().getProperties().put("CONTEXT_MENU_SCENE_X", 0); ! contextMenu.show(getControl(), menuX, screenY); } } e.consume(); } ! // var hadFocus = false; ! // var focused = bind (skin.control as TextInputControl).focused on replace old { ! // if (focused) { ! // hadFocus = true; ! // focusChanged(true); ! // } else { ! // if (hadFocus) { ! // focusChanged(false); ! // } ! // hadFocus = false; ! // } ! // } ! // ! // protected function focusChanged(f:Boolean):Void { ! // def textInputControl = skin.control as TextInputControl; ! // if (f and textInputControl.selectOnFocus and not focusGainedByMouseClick) { ! // textInputControl.selectAll(); ! // } else if (not f) { ! // textInputControl.commit(); ! // focusGainedByMouseClick = false; ! // displaySoftwareKeyboard(false); ! // } ! // } ! // ! protected void mouseSingleClick(HitInfo hit) { skin.positionCaret(hit, false); } ! protected void mouseDoubleClick(HitInfo hit) { ! final TextField textField = getControl(); textField.previousWord(); if (isWindows()) { textField.selectNextWord(); } else { textField.selectEndOfNextWord(); } } ! protected void mouseTripleClick(HitInfo hit) { ! getControl().selectAll(); } // Enumeration of all types of text input that can be simulated on // touch device, such as iPad. Type is passed to native code and // native text component is shown. It's used as workaround for iOS --- 358,419 ---- menuPos = skin.getMenuPosition(); } } if (menuPos != null) { ! Point2D p = getNode().localToScene(menuPos); ! Scene scene = getNode().getScene(); Window window = scene.getWindow(); Point2D location = new Point2D(window.getX() + scene.getX() + p.getX(), window.getY() + scene.getY() + p.getY()); screenX = location.getX(); sceneX = p.getX(); screenY = location.getY(); } } ! populateContextMenu(contextMenu); double menuWidth = contextMenu.prefWidth(-1); ! double menuX = screenX - (Properties.IS_TOUCH_SUPPORTED ? (menuWidth / 2) : 0); Screen currentScreen = com.sun.javafx.util.Utils.getScreenForPoint(screenX, 0); Rectangle2D bounds = currentScreen.getBounds(); if (menuX < bounds.getMinX()) { ! getNode().getProperties().put("CONTEXT_MENU_SCREEN_X", screenX); ! getNode().getProperties().put("CONTEXT_MENU_SCENE_X", sceneX); ! contextMenu.show(getNode(), bounds.getMinX(), screenY); } else if (screenX + menuWidth > bounds.getMaxX()) { double leftOver = menuWidth - ( bounds.getMaxX() - screenX); ! getNode().getProperties().put("CONTEXT_MENU_SCREEN_X", screenX); ! getNode().getProperties().put("CONTEXT_MENU_SCENE_X", sceneX); ! contextMenu.show(getNode(), screenX - leftOver, screenY); } else { ! getNode().getProperties().put("CONTEXT_MENU_SCREEN_X", 0); ! getNode().getProperties().put("CONTEXT_MENU_SCENE_X", 0); ! contextMenu.show(getNode(), menuX, screenY); } } e.consume(); } ! protected void mouseSingleClick(TextPosInfo hit) { skin.positionCaret(hit, false); } ! protected void mouseDoubleClick(TextPosInfo hit) { ! final TextField textField = getNode(); textField.previousWord(); if (isWindows()) { textField.selectNextWord(); } else { textField.selectEndOfNextWord(); } } ! protected void mouseTripleClick(TextPosInfo hit) { ! getNode().selectAll(); } // Enumeration of all types of text input that can be simulated on // touch device, such as iPad. Type is passed to native code and // native text component is shown. It's used as workaround for iOS