< 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 >