25
26 package com.sun.javafx.scene.control.behavior;
27
28 import com.sun.javafx.scene.control.Properties;
29 import javafx.beans.value.ChangeListener;
30 import javafx.beans.value.WeakChangeListener;
31 import javafx.event.ActionEvent;
32 import javafx.event.EventHandler;
33 import javafx.geometry.Bounds;
34 import javafx.geometry.Point2D;
35 import javafx.geometry.Rectangle2D;
36 import javafx.scene.Node;
37 import javafx.scene.Scene;
38 import javafx.scene.control.ContextMenu;
39 import javafx.scene.control.TextField;
40 import javafx.scene.control.skin.TextFieldSkin;
41 import com.sun.javafx.scene.control.skin.Utils;
42 import javafx.scene.input.ContextMenuEvent;
43 import javafx.scene.input.KeyEvent;
44 import javafx.scene.input.MouseEvent;
45 import javafx.stage.Screen;
46 import javafx.stage.Window;
47 import com.sun.javafx.PlatformUtil;
48 import com.sun.javafx.geom.transform.Affine3D;
49
50 import static javafx.scene.control.skin.TextFieldSkin.TextPosInfo;
51 import static com.sun.javafx.PlatformUtil.isMac;
52 import static com.sun.javafx.PlatformUtil.isWindows;
53
54 /**
55 * Text field behavior.
56 */
57 public class TextFieldBehavior extends TextInputControlBehavior<TextField> {
58 private TextFieldSkin skin;
59 private TwoLevelFocusBehavior tlFocus;
60 private ChangeListener<Scene> sceneListener;
61 private ChangeListener<Node> focusOwnerListener;
62
63 public TextFieldBehavior(final TextField textField) {
64 super(textField);
65
66 if (Properties.IS_TOUCH_SUPPORTED) {
67 contextMenu.getStyleClass().add("text-input-context-menu");
68 }
69
70 handleFocusChange();
240 @Override public void mousePressed(MouseEvent e) {
241 TextField textField = getNode();
242 // We never respond to events if disabled
243 if (!textField.isDisabled()) {
244 // If the text field doesn't have focus, then we'll attempt to set
245 // the focus and we'll indicate that we gained focus by a mouse
246 // click, which will then NOT honor the selectOnFocus variable
247 // of the textInputControl
248 if (!textField.isFocused()) {
249 focusGainedByMouseClick = true;
250 textField.requestFocus();
251 }
252
253 // stop the caret animation
254 setCaretAnimating(false);
255 // only if there is no selection should we see the caret
256 // setCaretOpacity(if (textInputControl.dot == textInputControl.mark) then 1.0 else 0.0);
257
258 // if the primary button was pressed
259 if (e.isPrimaryButtonDown() && !(e.isMiddleButtonDown() || e.isSecondaryButtonDown())) {
260 TextPosInfo hit = skin.getIndex(e.getX(), e.getY());
261 String text = textField.textProperty().getValueSafe();
262 int i = Utils.getHitInsertionIndex(hit, text);
263 final int anchor = textField.getAnchor();
264 final int caretPosition = textField.getCaretPosition();
265 if (e.getClickCount() < 2 &&
266 (Properties.IS_TOUCH_SUPPORTED ||
267 (anchor != caretPosition &&
268 ((i > anchor && i < caretPosition) || (i < anchor && i > caretPosition))))) {
269 // if there is a selection, then we will NOT handle the
270 // press now, but will defer until the release. If you
271 // select some text and then press down, we change the
272 // caret and wait to allow you to drag the text (TODO).
273 // When the drag concludes, then we handle the click
274
275 deferClick = true;
276 // TODO start a timer such that after some millis we
277 // switch into text dragging mode, change the cursor
278 // to indicate the text can be dragged, etc.
279 } else if (!(e.isControlDown() || e.isAltDown() || e.isShiftDown() || e.isMetaDown())) {
280 switch (e.getClickCount()) {
281 case 1: mouseSingleClick(hit); break;
282 case 2: mouseDoubleClick(hit); break;
380
381 if (menuX < bounds.getMinX()) {
382 getNode().getProperties().put("CONTEXT_MENU_SCREEN_X", screenX);
383 getNode().getProperties().put("CONTEXT_MENU_SCENE_X", sceneX);
384 contextMenu.show(getNode(), bounds.getMinX(), screenY);
385 } else if (screenX + menuWidth > bounds.getMaxX()) {
386 double leftOver = menuWidth - ( bounds.getMaxX() - screenX);
387 getNode().getProperties().put("CONTEXT_MENU_SCREEN_X", screenX);
388 getNode().getProperties().put("CONTEXT_MENU_SCENE_X", sceneX);
389 contextMenu.show(getNode(), screenX - leftOver, screenY);
390 } else {
391 getNode().getProperties().put("CONTEXT_MENU_SCREEN_X", 0);
392 getNode().getProperties().put("CONTEXT_MENU_SCENE_X", 0);
393 contextMenu.show(getNode(), menuX, screenY);
394 }
395 }
396
397 e.consume();
398 }
399
400 protected void mouseSingleClick(TextPosInfo hit) {
401 skin.positionCaret(hit, false);
402 }
403
404 protected void mouseDoubleClick(TextPosInfo hit) {
405 final TextField textField = getNode();
406 textField.previousWord();
407 if (isWindows()) {
408 textField.selectNextWord();
409 } else {
410 textField.selectEndOfNextWord();
411 }
412 }
413
414 protected void mouseTripleClick(TextPosInfo hit) {
415 getNode().selectAll();
416 }
417
418 // Enumeration of all types of text input that can be simulated on
419 // touch device, such as iPad. Type is passed to native code and
420 // native text component is shown. It's used as workaround for iOS
421 // devices since keyboard control is not possible without native
422 // text component being displayed
423 enum TextInputTypes {
424 TEXT_FIELD,
425 PASSWORD_FIELD,
426 EDITABLE_COMBO,
427 TEXT_AREA;
428 }
429
430 }
|
25
26 package com.sun.javafx.scene.control.behavior;
27
28 import com.sun.javafx.scene.control.Properties;
29 import javafx.beans.value.ChangeListener;
30 import javafx.beans.value.WeakChangeListener;
31 import javafx.event.ActionEvent;
32 import javafx.event.EventHandler;
33 import javafx.geometry.Bounds;
34 import javafx.geometry.Point2D;
35 import javafx.geometry.Rectangle2D;
36 import javafx.scene.Node;
37 import javafx.scene.Scene;
38 import javafx.scene.control.ContextMenu;
39 import javafx.scene.control.TextField;
40 import javafx.scene.control.skin.TextFieldSkin;
41 import com.sun.javafx.scene.control.skin.Utils;
42 import javafx.scene.input.ContextMenuEvent;
43 import javafx.scene.input.KeyEvent;
44 import javafx.scene.input.MouseEvent;
45 import javafx.scene.text.HitInfo;
46 import javafx.stage.Screen;
47 import javafx.stage.Window;
48 import com.sun.javafx.PlatformUtil;
49 import com.sun.javafx.geom.transform.Affine3D;
50
51 import static com.sun.javafx.PlatformUtil.isMac;
52 import static com.sun.javafx.PlatformUtil.isWindows;
53
54 /**
55 * Text field behavior.
56 */
57 public class TextFieldBehavior extends TextInputControlBehavior<TextField> {
58 private TextFieldSkin skin;
59 private TwoLevelFocusBehavior tlFocus;
60 private ChangeListener<Scene> sceneListener;
61 private ChangeListener<Node> focusOwnerListener;
62
63 public TextFieldBehavior(final TextField textField) {
64 super(textField);
65
66 if (Properties.IS_TOUCH_SUPPORTED) {
67 contextMenu.getStyleClass().add("text-input-context-menu");
68 }
69
70 handleFocusChange();
240 @Override public void mousePressed(MouseEvent e) {
241 TextField textField = getNode();
242 // We never respond to events if disabled
243 if (!textField.isDisabled()) {
244 // If the text field doesn't have focus, then we'll attempt to set
245 // the focus and we'll indicate that we gained focus by a mouse
246 // click, which will then NOT honor the selectOnFocus variable
247 // of the textInputControl
248 if (!textField.isFocused()) {
249 focusGainedByMouseClick = true;
250 textField.requestFocus();
251 }
252
253 // stop the caret animation
254 setCaretAnimating(false);
255 // only if there is no selection should we see the caret
256 // setCaretOpacity(if (textInputControl.dot == textInputControl.mark) then 1.0 else 0.0);
257
258 // if the primary button was pressed
259 if (e.isPrimaryButtonDown() && !(e.isMiddleButtonDown() || e.isSecondaryButtonDown())) {
260 HitInfo hit = skin.getIndex(e.getX(), e.getY());
261 int i = hit.getInsertionIndex();
262 final int anchor = textField.getAnchor();
263 final int caretPosition = textField.getCaretPosition();
264 if (e.getClickCount() < 2 &&
265 (Properties.IS_TOUCH_SUPPORTED ||
266 (anchor != caretPosition &&
267 ((i > anchor && i < caretPosition) || (i < anchor && i > caretPosition))))) {
268 // if there is a selection, then we will NOT handle the
269 // press now, but will defer until the release. If you
270 // select some text and then press down, we change the
271 // caret and wait to allow you to drag the text (TODO).
272 // When the drag concludes, then we handle the click
273
274 deferClick = true;
275 // TODO start a timer such that after some millis we
276 // switch into text dragging mode, change the cursor
277 // to indicate the text can be dragged, etc.
278 } else if (!(e.isControlDown() || e.isAltDown() || e.isShiftDown() || e.isMetaDown())) {
279 switch (e.getClickCount()) {
280 case 1: mouseSingleClick(hit); break;
281 case 2: mouseDoubleClick(hit); break;
379
380 if (menuX < bounds.getMinX()) {
381 getNode().getProperties().put("CONTEXT_MENU_SCREEN_X", screenX);
382 getNode().getProperties().put("CONTEXT_MENU_SCENE_X", sceneX);
383 contextMenu.show(getNode(), bounds.getMinX(), screenY);
384 } else if (screenX + menuWidth > bounds.getMaxX()) {
385 double leftOver = menuWidth - ( bounds.getMaxX() - screenX);
386 getNode().getProperties().put("CONTEXT_MENU_SCREEN_X", screenX);
387 getNode().getProperties().put("CONTEXT_MENU_SCENE_X", sceneX);
388 contextMenu.show(getNode(), screenX - leftOver, screenY);
389 } else {
390 getNode().getProperties().put("CONTEXT_MENU_SCREEN_X", 0);
391 getNode().getProperties().put("CONTEXT_MENU_SCENE_X", 0);
392 contextMenu.show(getNode(), menuX, screenY);
393 }
394 }
395
396 e.consume();
397 }
398
399 protected void mouseSingleClick(HitInfo hit) {
400 skin.positionCaret(hit, false);
401 }
402
403 protected void mouseDoubleClick(HitInfo hit) {
404 final TextField textField = getNode();
405 textField.previousWord();
406 if (isWindows()) {
407 textField.selectNextWord();
408 } else {
409 textField.selectEndOfNextWord();
410 }
411 }
412
413 protected void mouseTripleClick(HitInfo hit) {
414 getNode().selectAll();
415 }
416
417 // Enumeration of all types of text input that can be simulated on
418 // touch device, such as iPad. Type is passed to native code and
419 // native text component is shown. It's used as workaround for iOS
420 // devices since keyboard control is not possible without native
421 // text component being displayed
422 enum TextInputTypes {
423 TEXT_FIELD,
424 PASSWORD_FIELD,
425 EDITABLE_COMBO,
426 TEXT_AREA;
427 }
428
429 }
|