1 /*
2 * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
27
28 import com.sun.javafx.PlatformUtil;
29 import com.sun.javafx.geom.transform.Affine3D;
30 import com.sun.javafx.scene.control.Properties;
31 import javafx.scene.control.skin.TextAreaSkin;
32 import javafx.beans.value.ChangeListener;
33 import javafx.beans.value.ObservableValue;
34 import javafx.geometry.Bounds;
35 import javafx.geometry.Point2D;
36 import javafx.geometry.Rectangle2D;
37 import javafx.scene.Scene;
38 import javafx.scene.control.ContextMenu;
39 import javafx.scene.control.TextArea;
40 import com.sun.javafx.scene.control.skin.Utils;
41 import javafx.scene.input.ContextMenuEvent;
42 import com.sun.javafx.scene.control.inputmap.InputMap;
43 import com.sun.javafx.scene.control.inputmap.KeyBinding;
44 import javafx.scene.input.KeyEvent;
45 import javafx.scene.input.MouseButton;
46 import javafx.scene.input.MouseEvent;
47 import javafx.stage.Screen;
48 import javafx.stage.Window;
49
50 import java.util.function.Predicate;
51
52 import static javafx.scene.control.skin.TextAreaSkin.TextPosInfo;
53
54 import static com.sun.javafx.PlatformUtil.isMac;
55 import static com.sun.javafx.PlatformUtil.isWindows;
56 import static javafx.scene.control.skin.TextInputControlSkin.TextUnit;
57 import static javafx.scene.control.skin.TextInputControlSkin.Direction;
58 import static javafx.scene.input.KeyCode.*;
59
60
61 /**
62 * Text area behavior.
63 */
64 public class TextAreaBehavior extends TextInputControlBehavior<TextArea> {
65 // /**************************************************************************
66 // * Setup KeyBindings *
67 // *************************************************************************/
68 // protected static final List<KeyBinding> TEXT_AREA_BINDINGS = new ArrayList<KeyBinding>();
69 // static {
70 // TEXT_AREA_BINDINGS.add(new KeyBinding(HOME, KEY_PRESSED, "LineStart")); // changed
71 // TEXT_AREA_BINDINGS.add(new KeyBinding(END, KEY_PRESSED, "LineEnd")); // changed
72 // TEXT_AREA_BINDINGS.add(new KeyBinding(UP, KEY_PRESSED, "PreviousLine")); // changed
73 // TEXT_AREA_BINDINGS.add(new KeyBinding(KP_UP, KEY_PRESSED, "PreviousLine")); // changed
326 @Override public void mousePressed(MouseEvent e) {
327 TextArea textArea = getNode();
328 // We never respond to events if disabled
329 if (!textArea.isDisabled()) {
330 // If the text field doesn't have focus, then we'll attempt to set
331 // the focus and we'll indicate that we gained focus by a mouse
332 // click, TODO which will then NOT honor the selectOnFocus variable
333 // of the textInputControl
334 if (!textArea.isFocused()) {
335 focusGainedByMouseClick = true;
336 textArea.requestFocus();
337 }
338
339 // stop the caret animation
340 setCaretAnimating(false);
341 // only if there is no selection should we see the caret
342 // setCaretOpacity(if (textInputControl.dot == textInputControl.mark) then 1.0 else 0.0);
343
344 // if the primary button was pressed
345 if (e.getButton() == MouseButton.PRIMARY && !(e.isMiddleButtonDown() || e.isSecondaryButtonDown())) {
346 TextPosInfo hit = skin.getIndex(e.getX(), e.getY());
347 int i = Utils.getHitInsertionIndex(hit, textArea.textProperty().getValueSafe());
348 // int i = skin.getInsertionPoint(e.getX(), e.getY());
349 final int anchor = textArea.getAnchor();
350 final int caretPosition = textArea.getCaretPosition();
351 if (e.getClickCount() < 2 &&
352 (e.isSynthesized() ||
353 (anchor != caretPosition &&
354 ((i > anchor && i < caretPosition) || (i < anchor && i > caretPosition))))) {
355 // if there is a selection, then we will NOT handle the
356 // press now, but will defer until the release. If you
357 // select some text and then press down, we change the
358 // caret and wait to allow you to drag the text (TODO).
359 // When the drag concludes, then we handle the click
360
361 deferClick = true;
362 // TODO start a timer such that after some millis we
363 // switch into text dragging mode, change the cursor
364 // to indicate the text can be dragged, etc.
365 } else if (!(e.isControlDown() || e.isAltDown() || e.isShiftDown() || e.isMetaDown() || e.isShortcutDown())) {
366 switch (e.getClickCount()) {
367 case 1: skin.positionCaret(hit, false); break;
368 case 2: mouseDoubleClick(hit); break;
471 contextMenu.show(getNode(), bounds.getMinX(), screenY);
472 } else if (screenX + menuWidth > bounds.getMaxX()) {
473 double leftOver = menuWidth - ( bounds.getMaxX() - screenX);
474 getNode().getProperties().put("CONTEXT_MENU_SCREEN_X", screenX);
475 getNode().getProperties().put("CONTEXT_MENU_SCENE_X", sceneX);
476 contextMenu.show(getNode(), screenX - leftOver, screenY);
477 } else {
478 getNode().getProperties().put("CONTEXT_MENU_SCREEN_X", 0);
479 getNode().getProperties().put("CONTEXT_MENU_SCENE_X", 0);
480 contextMenu.show(getNode(), menuX, screenY);
481 }
482 }
483
484 e.consume();
485 }
486
487 @Override protected void setCaretAnimating(boolean play) {
488 skin.setCaretAnimating(play);
489 }
490
491 protected void mouseDoubleClick(TextPosInfo hit) {
492 final TextArea textArea = getNode();
493 textArea.previousWord();
494 if (isWindows()) {
495 textArea.selectNextWord();
496 } else {
497 textArea.selectEndOfNextWord();
498 }
499 }
500
501 protected void mouseTripleClick(TextPosInfo hit) {
502 // select the line
503 skin.moveCaret(TextUnit.PARAGRAPH, Direction.BEGINNING, false);
504 skin.moveCaret(TextUnit.PARAGRAPH, Direction.END, true);
505 }
506 }
|
1 /*
2 * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
27
28 import com.sun.javafx.PlatformUtil;
29 import com.sun.javafx.geom.transform.Affine3D;
30 import com.sun.javafx.scene.control.Properties;
31 import javafx.scene.control.skin.TextAreaSkin;
32 import javafx.beans.value.ChangeListener;
33 import javafx.beans.value.ObservableValue;
34 import javafx.geometry.Bounds;
35 import javafx.geometry.Point2D;
36 import javafx.geometry.Rectangle2D;
37 import javafx.scene.Scene;
38 import javafx.scene.control.ContextMenu;
39 import javafx.scene.control.TextArea;
40 import com.sun.javafx.scene.control.skin.Utils;
41 import javafx.scene.input.ContextMenuEvent;
42 import com.sun.javafx.scene.control.inputmap.InputMap;
43 import com.sun.javafx.scene.control.inputmap.KeyBinding;
44 import javafx.scene.input.KeyEvent;
45 import javafx.scene.input.MouseButton;
46 import javafx.scene.input.MouseEvent;
47 import javafx.scene.text.HitInfo;
48 import javafx.stage.Screen;
49 import javafx.stage.Window;
50
51 import java.util.function.Predicate;
52
53 import static com.sun.javafx.PlatformUtil.isMac;
54 import static com.sun.javafx.PlatformUtil.isWindows;
55 import static javafx.scene.control.skin.TextInputControlSkin.TextUnit;
56 import static javafx.scene.control.skin.TextInputControlSkin.Direction;
57 import static javafx.scene.input.KeyCode.*;
58
59
60 /**
61 * Text area behavior.
62 */
63 public class TextAreaBehavior extends TextInputControlBehavior<TextArea> {
64 // /**************************************************************************
65 // * Setup KeyBindings *
66 // *************************************************************************/
67 // protected static final List<KeyBinding> TEXT_AREA_BINDINGS = new ArrayList<KeyBinding>();
68 // static {
69 // TEXT_AREA_BINDINGS.add(new KeyBinding(HOME, KEY_PRESSED, "LineStart")); // changed
70 // TEXT_AREA_BINDINGS.add(new KeyBinding(END, KEY_PRESSED, "LineEnd")); // changed
71 // TEXT_AREA_BINDINGS.add(new KeyBinding(UP, KEY_PRESSED, "PreviousLine")); // changed
72 // TEXT_AREA_BINDINGS.add(new KeyBinding(KP_UP, KEY_PRESSED, "PreviousLine")); // changed
325 @Override public void mousePressed(MouseEvent e) {
326 TextArea textArea = getNode();
327 // We never respond to events if disabled
328 if (!textArea.isDisabled()) {
329 // If the text field doesn't have focus, then we'll attempt to set
330 // the focus and we'll indicate that we gained focus by a mouse
331 // click, TODO which will then NOT honor the selectOnFocus variable
332 // of the textInputControl
333 if (!textArea.isFocused()) {
334 focusGainedByMouseClick = true;
335 textArea.requestFocus();
336 }
337
338 // stop the caret animation
339 setCaretAnimating(false);
340 // only if there is no selection should we see the caret
341 // setCaretOpacity(if (textInputControl.dot == textInputControl.mark) then 1.0 else 0.0);
342
343 // if the primary button was pressed
344 if (e.getButton() == MouseButton.PRIMARY && !(e.isMiddleButtonDown() || e.isSecondaryButtonDown())) {
345 HitInfo hit = skin.getIndex(e.getX(), e.getY());
346 int i = hit.getInsertionIndex();
347 final int anchor = textArea.getAnchor();
348 final int caretPosition = textArea.getCaretPosition();
349 if (e.getClickCount() < 2 &&
350 (e.isSynthesized() ||
351 (anchor != caretPosition &&
352 ((i > anchor && i < caretPosition) || (i < anchor && i > caretPosition))))) {
353 // if there is a selection, then we will NOT handle the
354 // press now, but will defer until the release. If you
355 // select some text and then press down, we change the
356 // caret and wait to allow you to drag the text (TODO).
357 // When the drag concludes, then we handle the click
358
359 deferClick = true;
360 // TODO start a timer such that after some millis we
361 // switch into text dragging mode, change the cursor
362 // to indicate the text can be dragged, etc.
363 } else if (!(e.isControlDown() || e.isAltDown() || e.isShiftDown() || e.isMetaDown() || e.isShortcutDown())) {
364 switch (e.getClickCount()) {
365 case 1: skin.positionCaret(hit, false); break;
366 case 2: mouseDoubleClick(hit); break;
469 contextMenu.show(getNode(), bounds.getMinX(), screenY);
470 } else if (screenX + menuWidth > bounds.getMaxX()) {
471 double leftOver = menuWidth - ( bounds.getMaxX() - screenX);
472 getNode().getProperties().put("CONTEXT_MENU_SCREEN_X", screenX);
473 getNode().getProperties().put("CONTEXT_MENU_SCENE_X", sceneX);
474 contextMenu.show(getNode(), screenX - leftOver, screenY);
475 } else {
476 getNode().getProperties().put("CONTEXT_MENU_SCREEN_X", 0);
477 getNode().getProperties().put("CONTEXT_MENU_SCENE_X", 0);
478 contextMenu.show(getNode(), menuX, screenY);
479 }
480 }
481
482 e.consume();
483 }
484
485 @Override protected void setCaretAnimating(boolean play) {
486 skin.setCaretAnimating(play);
487 }
488
489 protected void mouseDoubleClick(HitInfo hit) {
490 final TextArea textArea = getNode();
491 textArea.previousWord();
492 if (isWindows()) {
493 textArea.selectNextWord();
494 } else {
495 textArea.selectEndOfNextWord();
496 }
497 }
498
499 protected void mouseTripleClick(HitInfo hit) {
500 // select the line
501 skin.moveCaret(TextUnit.PARAGRAPH, Direction.BEGINNING, false);
502 skin.moveCaret(TextUnit.PARAGRAPH, Direction.END, true);
503 }
504 }
|