< prev index next >
modules/graphics/src/main/java/javafx/scene/text/Text.java
Print this page
*** 1,7 ****
/*
! * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
--- 1,7 ----
/*
! * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
*** 32,42 ****
import com.sun.javafx.geom.Path2D;
import com.sun.javafx.geom.RectBounds;
import com.sun.javafx.geom.TransformedShape;
import com.sun.javafx.geom.transform.BaseTransform;
import com.sun.javafx.scene.DirtyBits;
! import com.sun.javafx.scene.text.*;
import com.sun.javafx.sg.prism.NGNode;
import com.sun.javafx.sg.prism.NGShape;
import com.sun.javafx.sg.prism.NGText;
import com.sun.javafx.tk.Toolkit;
import javafx.beans.DefaultProperty;
--- 32,46 ----
import com.sun.javafx.geom.Path2D;
import com.sun.javafx.geom.RectBounds;
import com.sun.javafx.geom.TransformedShape;
import com.sun.javafx.geom.transform.BaseTransform;
import com.sun.javafx.scene.DirtyBits;
! import com.sun.javafx.scene.text.GlyphList;
! import com.sun.javafx.scene.text.TextLayout;
! import com.sun.javafx.scene.text.TextLayoutFactory;
! import com.sun.javafx.scene.text.TextLine;
! import com.sun.javafx.scene.text.TextSpan;
import com.sun.javafx.sg.prism.NGNode;
import com.sun.javafx.sg.prism.NGShape;
import com.sun.javafx.sg.prism.NGText;
import com.sun.javafx.tk.Toolkit;
import javafx.beans.DefaultProperty;
*** 385,398 ****
text = new StringPropertyBase("") {
@Override public Object getBean() { return Text.this; }
@Override public String getName() { return "text"; }
@Override public void invalidated() {
needsFullTextLayout();
! setImpl_selectionStart(-1);
! setImpl_selectionEnd(-1);
! setImpl_caretPosition(-1);
! setImpl_caretBias(true);
// MH: Functionality copied from store() method,
// which was removed.
// Wonder what should happen if text is bound
// and becomes null?
--- 389,402 ----
text = new StringPropertyBase("") {
@Override public Object getBean() { return Text.this; }
@Override public String getName() { return "text"; }
@Override public void invalidated() {
needsFullTextLayout();
! setSelectionStart(-1);
! setSelectionEnd(-1);
! setCaretPosition(-1);
! setCaretBias(true);
// MH: Functionality copied from store() method,
// which was removed.
// Wonder what should happen if text is bound
// and becomes null?
*** 774,1009 ****
}
impl_markDirty(DirtyBits.NODE_GEOMETRY);
}
/**
- * @treatAsPrivate implementation detail
- * @deprecated This is an internal API that is not intended
- * for use and will be removed in the next version
- */
- @Deprecated
- public final PathElement[] getImpl_selectionShape() {
- return impl_selectionShapeProperty().get();
- }
-
- /**
* Shape of selection in local coordinates.
*
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
*/
! @Deprecated
! public final ReadOnlyObjectProperty<PathElement[]> impl_selectionShapeProperty() {
return getTextAttribute().impl_selectionShapeProperty();
}
/**
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
*/
! @Deprecated
! public final void setImpl_selectionStart(int value) {
if (value == -1 &&
(attributes == null || attributes.impl_selectionStart == null)) {
return;
}
! impl_selectionStartProperty().set(value);
}
! /**
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
! */
! @Deprecated
! public final int getImpl_selectionStart() {
if (attributes == null || attributes.impl_selectionStart == null) {
return DEFAULT_SELECTION_START;
}
return attributes.getImpl_selectionStart();
}
! /**
! * Selection start index in the content.
! * set to {@code -1} to unset selection.
! *
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
! */
! @Deprecated
! public final IntegerProperty impl_selectionStartProperty() {
return getTextAttribute().impl_selectionStartProperty();
}
/**
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
*/
! @Deprecated
! public final void setImpl_selectionEnd(int value) {
if (value == -1 &&
(attributes == null || attributes.impl_selectionEnd == null)) {
return;
}
! impl_selectionEndProperty().set(value);
}
! /**
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
! */
! @Deprecated
! public final int getImpl_selectionEnd() {
if (attributes == null || attributes.impl_selectionEnd == null) {
return DEFAULT_SELECTION_END;
}
return attributes.getImpl_selectionEnd();
}
! /**
! * Selection end index in the content.
! * set to {@code -1} to unset selection.
! *
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
! */
! @Deprecated
! public final IntegerProperty impl_selectionEndProperty() {
return getTextAttribute().impl_selectionEndProperty();
}
/**
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
*/
! @Deprecated
! public final ObjectProperty<Paint> impl_selectionFillProperty() {
return getTextAttribute().impl_selectionFillProperty();
}
! /**
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
! */
! @Deprecated
! public final PathElement[] getImpl_caretShape() {
! return impl_caretShapeProperty().get();
}
/**
* Shape of caret in local coordinates.
*
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
*/
! @Deprecated
! public final ReadOnlyObjectProperty<PathElement[]> impl_caretShapeProperty() {
return getTextAttribute().impl_caretShapeProperty();
}
/**
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
*/
! @Deprecated
! public final void setImpl_caretPosition(int value) {
if (value == -1 &&
(attributes == null || attributes.impl_caretPosition == null)) {
return;
}
! impl_caretPositionProperty().set(value);
}
! /**
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
! */
! @Deprecated
! public final int getImpl_caretPosition() {
if (attributes == null || attributes.impl_caretPosition == null) {
return DEFAULT_CARET_POSITION;
}
return attributes.getImpl_caretPosition();
}
! /**
! * caret index in the content.
! * set to {@code -1} to unset caret.
! *
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
! */
! @Deprecated
! public final IntegerProperty impl_caretPositionProperty() {
return getTextAttribute().impl_caretPositionProperty();
}
/**
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
*/
! @Deprecated
! public final void setImpl_caretBias(boolean value) {
if (value && (attributes == null || attributes.impl_caretBias == null)) {
return;
}
! impl_caretBiasProperty().set(value);
}
! /**
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
! */
! @Deprecated
! public final boolean isImpl_caretBias() {
if (attributes == null || attributes.impl_caretBias == null) {
return DEFAULT_CARET_BIAS;
}
return getTextAttribute().isImpl_caretBias();
}
! /**
! * caret bias in the content. true means a bias towards forward character
! * (true=leading/false=trailing)
! *
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
! */
! @Deprecated
! public final BooleanProperty impl_caretBiasProperty() {
return getTextAttribute().impl_caretBiasProperty();
}
/**
* Maps local point to index in the content.
*
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
*/
! @Deprecated
! public final HitInfo impl_hitTestChar(Point2D point) {
if (point == null) return null;
TextLayout layout = getTextLayout();
double x = point.getX() - getX();
double y = point.getY() - getY() + getYRendering();
! return layout.getHitInfo((float)x, (float)y);
}
private PathElement[] getRange(int start, int end, int type) {
int length = getTextInternal().length();
if (0 <= start && start < end && end <= length) {
--- 778,940 ----
}
impl_markDirty(DirtyBits.NODE_GEOMETRY);
}
/**
* Shape of selection in local coordinates.
*
! * @since 9
*/
! public final PathElement[] getSelectionShape() {
! return selectionShapeProperty().get();
! }
!
! public final ReadOnlyObjectProperty<PathElement[]> selectionShapeProperty() {
return getTextAttribute().impl_selectionShapeProperty();
}
/**
! * Selection start index in the content.
! * set to {@code -1} to unset selection.
! *
! * @since 9
*/
! public final void setSelectionStart(int value) {
if (value == -1 &&
(attributes == null || attributes.impl_selectionStart == null)) {
return;
}
! selectionStartProperty().set(value);
}
! public final int getSelectionStart() {
if (attributes == null || attributes.impl_selectionStart == null) {
return DEFAULT_SELECTION_START;
}
return attributes.getImpl_selectionStart();
}
! public final IntegerProperty selectionStartProperty() {
return getTextAttribute().impl_selectionStartProperty();
}
/**
! * Selection end index in the content.
! * set to {@code -1} to unset selection.
! *
! * @since 9
*/
! public final void setSelectionEnd(int value) {
if (value == -1 &&
(attributes == null || attributes.impl_selectionEnd == null)) {
return;
}
! selectionEndProperty().set(value);
}
! public final int getSelectionEnd() {
if (attributes == null || attributes.impl_selectionEnd == null) {
return DEFAULT_SELECTION_END;
}
return attributes.getImpl_selectionEnd();
}
! public final IntegerProperty selectionEndProperty() {
return getTextAttribute().impl_selectionEndProperty();
}
/**
! * The fill color of selected text.
! *
! * @since 9
*/
! public final ObjectProperty<Paint> selectionFillProperty() {
return getTextAttribute().impl_selectionFillProperty();
}
! public final void setSelectionFill(Paint paint) {
! selectionFillProperty().set(paint);
! }
! public final Paint getSelectionFill() {
! return selectionFillProperty().get();
}
/**
* Shape of caret in local coordinates.
*
! * @since 9
*/
! public final PathElement[] getCaretShape() {
! return caretShapeProperty().get();
! }
!
! public final ReadOnlyObjectProperty<PathElement[]> caretShapeProperty() {
return getTextAttribute().impl_caretShapeProperty();
}
/**
! * caret index in the content.
! * set to {@code -1} to unset caret.
! *
! * @since 9
*/
! public final void setCaretPosition(int value) {
if (value == -1 &&
(attributes == null || attributes.impl_caretPosition == null)) {
return;
}
! caretPositionProperty().set(value);
}
! public final int getCaretPosition() {
if (attributes == null || attributes.impl_caretPosition == null) {
return DEFAULT_CARET_POSITION;
}
return attributes.getImpl_caretPosition();
}
! public final IntegerProperty caretPositionProperty() {
return getTextAttribute().impl_caretPositionProperty();
}
/**
! * caret bias in the content. {@code true} means a bias towards the leading character edge.
! * (true=leading/false=trailing)
! *
! * @since 9
*/
! public final void setCaretBias(boolean value) {
if (value && (attributes == null || attributes.impl_caretBias == null)) {
return;
}
! caretBiasProperty().set(value);
}
! public final boolean isCaretBias() {
if (attributes == null || attributes.impl_caretBias == null) {
return DEFAULT_CARET_BIAS;
}
return getTextAttribute().isImpl_caretBias();
}
! public final BooleanProperty caretBiasProperty() {
return getTextAttribute().impl_caretBiasProperty();
}
/**
* Maps local point to index in the content.
*
! * @since 9
*/
! public final HitInfo hitTest(Point2D point) {
if (point == null) return null;
TextLayout layout = getTextLayout();
double x = point.getX() - getX();
double y = point.getY() - getY() + getYRendering();
! TextLayout.Hit layoutHit = layout.getHitInfo((float)x, (float)y);
! return new HitInfo(layoutHit.getCharIndex(), layoutHit.getInsertionIndex(),
! layoutHit.isLeading(), getText());
}
private PathElement[] getRange(int start, int end, int type) {
int length = getTextInternal().length();
if (0 <= start && start < end && end <= length) {
*** 1014,1043 ****
}
return EMPTY_PATH_ELEMENT_ARRAY;
}
/**
* Returns shape for the range of the text in local coordinates.
*
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
*/
! @Deprecated
! public final PathElement[] impl_getRangeShape(int start, int end) {
return getRange(start, end, TextLayout.TYPE_TEXT);
}
/**
* Returns shape for the underline in local coordinates.
*
! * @treatAsPrivate implementation detail
! * @deprecated This is an internal API that is not intended
! * for use and will be removed in the next version
*/
! @Deprecated
! public final PathElement[] impl_getUnderlineShape(int start, int end) {
return getRange(start, end, TextLayout.TYPE_UNDERLINE);
}
/**
* Shows/Hides on-screen keyboard if available (mobile platform)
--- 945,983 ----
}
return EMPTY_PATH_ELEMENT_ARRAY;
}
/**
+ * Returns shape for the caret at given index and bias.
+ *
+ * @since 9
+ */
+ public final PathElement[] caretShape(int charIndex, boolean caretBias) {
+ if (0 <= charIndex && charIndex <= getTextInternal().length()) {
+ float x = (float)getX();
+ float y = (float)getY() - getYRendering();
+ return getTextLayout().getCaretShape(charIndex, caretBias, x, y);
+ } else {
+ return null;
+ }
+ }
+
+ /**
* Returns shape for the range of the text in local coordinates.
*
! * @since 9
*/
! public final PathElement[] rangeShape(int start, int end) {
return getRange(start, end, TextLayout.TYPE_TEXT);
}
/**
* Returns shape for the underline in local coordinates.
*
! * @since 9
*/
! public final PathElement[] underlineShape(int start, int end) {
return getRange(start, end, TextLayout.TYPE_UNDERLINE);
}
/**
* Shows/Hides on-screen keyboard if available (mobile platform)
*** 1475,1489 ****
peer.setLayoutLocation(-x, yadj - y);
}
}
if (impl_isDirty(DirtyBits.TEXT_SELECTION)) {
Object fillObj = null;
! int start = getImpl_selectionStart();
! int end = getImpl_selectionEnd();
int length = getTextInternal().length();
if (0 <= start && start < end && end <= length) {
! Paint fill = impl_selectionFillProperty().get();
fillObj = fill != null ? Toolkit.getPaintAccessor().getPlatformPaint(fill) : null;
}
peer.setSelection(start, end, fillObj);
}
}
--- 1415,1429 ----
peer.setLayoutLocation(-x, yadj - y);
}
}
if (impl_isDirty(DirtyBits.TEXT_SELECTION)) {
Object fillObj = null;
! int start = getSelectionStart();
! int end = getSelectionEnd();
int length = getTextInternal().length();
if (0 <= start && start < end && end <= length) {
! Paint fill = selectionFillProperty().get();
fillObj = fill != null ? Toolkit.getPaintAccessor().getPlatformPaint(fill) : null;
}
peer.setSelection(start, end, fillObj);
}
}
*** 1689,1700 ****
public final ReadOnlyObjectProperty<PathElement[]> impl_selectionShapeProperty() {
if (impl_selectionShape == null) {
impl_selectionBinding = new ObjectBinding<PathElement[]>() {
{bind(impl_selectionStartProperty(), impl_selectionEndProperty());}
@Override protected PathElement[] computeValue() {
! int start = getImpl_selectionStart();
! int end = getImpl_selectionEnd();
return getRange(start, end, TextLayout.TYPE_TEXT);
}
};
impl_selectionShape = new SimpleObjectProperty<PathElement[]>(Text.this, "impl_selectionShape");
impl_selectionShape.bind(impl_selectionBinding);
--- 1629,1640 ----
public final ReadOnlyObjectProperty<PathElement[]> impl_selectionShapeProperty() {
if (impl_selectionShape == null) {
impl_selectionBinding = new ObjectBinding<PathElement[]>() {
{bind(impl_selectionStartProperty(), impl_selectionEndProperty());}
@Override protected PathElement[] computeValue() {
! int start = getSelectionStart();
! int end = getSelectionEnd();
return getRange(start, end, TextLayout.TYPE_TEXT);
}
};
impl_selectionShape = new SimpleObjectProperty<PathElement[]>(Text.this, "impl_selectionShape");
impl_selectionShape.bind(impl_selectionBinding);
*** 1765,1775 ****
};
}
return impl_selectionEnd;
}
- @Deprecated
private ObjectProperty<PathElement[]> impl_caretShape;
private ObjectBinding<PathElement[]> impl_caretBinding;
@Deprecated
public final ReadOnlyObjectProperty<PathElement[]> impl_caretShapeProperty() {
--- 1705,1714 ----
*** 1895,1919 ****
if (accText != null && !accText.isEmpty()) return accText;
return getText();
}
case FONT: return getFont();
case CARET_OFFSET: {
! int sel = getImpl_caretPosition();
if (sel >= 0) return sel;
return getText().length();
}
case SELECTION_START: {
! int sel = getImpl_selectionStart();
if (sel >= 0) return sel;
! sel = getImpl_caretPosition();
if (sel >= 0) return sel;
return getText().length();
}
case SELECTION_END: {
! int sel = getImpl_selectionEnd();
if (sel >= 0) return sel;
! sel = getImpl_caretPosition();
if (sel >= 0) return sel;
return getText().length();
}
case LINE_FOR_OFFSET: {
int offset = (Integer)parameters[0];
--- 1834,1858 ----
if (accText != null && !accText.isEmpty()) return accText;
return getText();
}
case FONT: return getFont();
case CARET_OFFSET: {
! int sel = getCaretPosition();
if (sel >= 0) return sel;
return getText().length();
}
case SELECTION_START: {
! int sel = getSelectionStart();
if (sel >= 0) return sel;
! sel = getCaretPosition();
if (sel >= 0) return sel;
return getText().length();
}
case SELECTION_END: {
! int sel = getSelectionEnd();
if (sel >= 0) return sel;
! sel = getCaretPosition();
if (sel >= 0) return sel;
return getText().length();
}
case LINE_FOR_OFFSET: {
int offset = (Integer)parameters[0];
*** 1946,1961 ****
return null;
}
case OFFSET_AT_POINT: {
Point2D point = (Point2D)parameters[0];
point = screenToLocal(point);
! return impl_hitTestChar(point).getCharIndex();
}
case BOUNDS_FOR_RANGE: {
int start = (Integer)parameters[0];
int end = (Integer)parameters[1];
! PathElement[] elements = impl_getRangeShape(start, end + 1);
/* Each bounds is defined by a MoveTo (top-left) followed by
* 4 LineTo (to top-right, bottom-right, bottom-left, back to top-left).
*/
Bounds[] bounds = new Bounds[elements.length / 5];
int index = 0;
--- 1885,1900 ----
return null;
}
case OFFSET_AT_POINT: {
Point2D point = (Point2D)parameters[0];
point = screenToLocal(point);
! return hitTest(point).getCharIndex();
}
case BOUNDS_FOR_RANGE: {
int start = (Integer)parameters[0];
int end = (Integer)parameters[1];
! PathElement[] elements = rangeShape(start, end + 1);
/* Each bounds is defined by a MoveTo (top-left) followed by
* 4 LineTo (to top-right, bottom-right, bottom-left, back to top-left).
*/
Bounds[] bounds = new Bounds[elements.length / 5];
int index = 0;
< prev index next >