mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-12 12:29:41 +01:00
JBR-2234 Support CSS setting overflow-wrap:anywhere in JEditorPane
port from JBR 11 to JBR 15 (cherry picked from commitsb6583d0a71,6003abc15f) cherry picked from commit93ad4f06ddalso includes JBR-4006 [JCK] javax.swing.text.html.CSS$Attribute.OVERFLOW_WRAP field breaks public API (cherry picked from commitf20a3d8679) and JBR-4007 [JCK] javax.swing.text.GlyphView.calcBreakSpots method breaks public API (cherry picked from commit1002eff4f3) (cherry picked from commitf603f9e837)
This commit is contained in:
@@ -1601,7 +1601,12 @@ public abstract class AbstractDocument implements Document, Serializable {
|
||||
/**
|
||||
* Document property that indicates if a character has been inserted
|
||||
* into the document that is more than one byte long. GlyphView uses
|
||||
* this to determine if it should use BreakIterator.
|
||||
* this to determine if it should use BreakIterator. This property should
|
||||
* not be publicly exposed, since it is used for implementation convenience
|
||||
* only. As a side effect, copies of this property may be in its subclasses
|
||||
* that live in different packages (e.g. HTMLDocument as of now), so those
|
||||
* copies should also be taken care of when this property needs to be
|
||||
* modified.
|
||||
*/
|
||||
static final Object MultiByteProperty = "multiByte";
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ import java.util.Locale;
|
||||
|
||||
import javax.swing.UIManager;
|
||||
import sun.swing.SwingUtilities2;
|
||||
import sun.swing.text.GlyphViewAccessor;
|
||||
|
||||
import static sun.swing.SwingUtilities2.IMPLIED_CR;
|
||||
|
||||
/**
|
||||
@@ -777,6 +779,41 @@ public class GlyphView extends View implements TabableView, Cloneable {
|
||||
private int getBreakSpot(int p0, int p1) {
|
||||
if (breakSpots == null) {
|
||||
// Re-calculate breakpoints for the whole view
|
||||
BreakIterator breaker = getBreaker();
|
||||
breakSpots = calcBreakSpots(breaker);
|
||||
}
|
||||
|
||||
int breakSpot = BreakIterator.DONE;
|
||||
for (int i = 0; i < breakSpots.length; i++) {
|
||||
int bsp = breakSpots[i];
|
||||
if (bsp <= p1) {
|
||||
if (bsp > p0) {
|
||||
breakSpot = bsp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return breakSpot;
|
||||
}
|
||||
|
||||
static {
|
||||
GlyphViewAccessor.setAccessor(new GlyphViewAccessor() {
|
||||
@Override
|
||||
public int[] calcBreakSpots(GlyphView glyphView, BreakIterator breaker) {
|
||||
return glyphView.calcBreakSpots(breaker);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: convert to protected method (removing accessor) when upstreaming the fix
|
||||
/**
|
||||
* Collects all possible breaking positions in the element,
|
||||
* generated by the provided breaker.
|
||||
*
|
||||
* @param breaker provider of break positions
|
||||
* @return possible break positions in the element
|
||||
*/
|
||||
int[] calcBreakSpots(BreakIterator breaker) {
|
||||
int start = getStartOffset();
|
||||
int end = getEndOffset();
|
||||
int[] bs = new int[end + 1 - start];
|
||||
@@ -790,7 +827,6 @@ public class GlyphView extends View implements TabableView, Cloneable {
|
||||
|
||||
Segment s = getText(pstart, pend);
|
||||
s.first();
|
||||
BreakIterator breaker = getBreaker();
|
||||
breaker.setText(s);
|
||||
|
||||
// Backward search should start from end+1 unless there's NO end+1
|
||||
@@ -807,21 +843,9 @@ public class GlyphView extends View implements TabableView, Cloneable {
|
||||
}
|
||||
|
||||
SegmentCache.releaseSharedSegment(s);
|
||||
breakSpots = new int[ix];
|
||||
System.arraycopy(bs, 0, breakSpots, 0, ix);
|
||||
}
|
||||
|
||||
int breakSpot = BreakIterator.DONE;
|
||||
for (int i = 0; i < breakSpots.length; i++) {
|
||||
int bsp = breakSpots[i];
|
||||
if (bsp <= p1) {
|
||||
if (bsp > p0) {
|
||||
breakSpot = bsp;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return breakSpot;
|
||||
int[] result = new int[ix];
|
||||
System.arraycopy(bs, 0, result, 0, ix);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -97,6 +97,7 @@ import javax.swing.text.View;
|
||||
* <li>list-style-image
|
||||
* <li>list-style-type
|
||||
* <li>list-style-position
|
||||
* <li>overflow-wrap
|
||||
* </ul>
|
||||
* The following are modeled, but currently not rendered.
|
||||
* <ul><li>font-variant
|
||||
@@ -495,6 +496,14 @@ public class CSS implements Serializable {
|
||||
public static final Attribute MARGIN_TOP =
|
||||
new Attribute("margin-top", "0", false);
|
||||
|
||||
/**
|
||||
* CSS attribute "overflow-wrap".
|
||||
*
|
||||
* TODO: make public when upstreaming the fix
|
||||
*/
|
||||
static final Attribute OVERFLOW_WRAP =
|
||||
new Attribute("overflow-wrap", "normal", true);
|
||||
|
||||
/**
|
||||
* CSS attribute "padding".
|
||||
*/
|
||||
@@ -598,7 +607,8 @@ public class CSS implements Serializable {
|
||||
PADDING_TOP, TEXT_ALIGN, TEXT_DECORATION, TEXT_INDENT, TEXT_TRANSFORM,
|
||||
VERTICAL_ALIGN, WORD_SPACING, WHITE_SPACE, WIDTH,
|
||||
BORDER_SPACING, CAPTION_SIDE,
|
||||
MARGIN_LEFT_LTR, MARGIN_LEFT_RTL, MARGIN_RIGHT_LTR, MARGIN_RIGHT_RTL
|
||||
MARGIN_LEFT_LTR, MARGIN_LEFT_RTL, MARGIN_RIGHT_LTR, MARGIN_RIGHT_RTL,
|
||||
OVERFLOW_WRAP
|
||||
};
|
||||
|
||||
private static final Attribute[] ALL_MARGINS =
|
||||
|
||||
@@ -1894,6 +1894,13 @@ public class HTMLDocument extends DefaultStyledDocument {
|
||||
*/
|
||||
private static final String I18NProperty = "i18n";
|
||||
|
||||
/**
|
||||
* Multi-byte property key.
|
||||
*
|
||||
* @see AbstractDocument#MultiByteProperty
|
||||
*/
|
||||
static final String MultiByteProperty = "multiByte";
|
||||
|
||||
static {
|
||||
contentAttributeSet = new SimpleAttributeSet();
|
||||
((MutableAttributeSet)contentAttributeSet).
|
||||
|
||||
@@ -24,8 +24,11 @@
|
||||
*/
|
||||
package javax.swing.text.html;
|
||||
|
||||
import sun.swing.text.GlyphViewAccessor;
|
||||
|
||||
import java.awt.*;
|
||||
import java.text.BreakIterator;
|
||||
import java.util.Locale;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
import javax.swing.text.*;
|
||||
|
||||
@@ -61,6 +64,7 @@ public class InlineView extends LabelView {
|
||||
* @see View#insertUpdate
|
||||
*/
|
||||
public void insertUpdate(DocumentEvent e, Shape a, ViewFactory f) {
|
||||
wrapAnywhereMinimumSpan = -1;
|
||||
super.insertUpdate(e, a, f);
|
||||
}
|
||||
|
||||
@@ -77,6 +81,7 @@ public class InlineView extends LabelView {
|
||||
* @see View#removeUpdate
|
||||
*/
|
||||
public void removeUpdate(DocumentEvent e, Shape a, ViewFactory f) {
|
||||
wrapAnywhereMinimumSpan = -1;
|
||||
super.removeUpdate(e, a, f);
|
||||
}
|
||||
|
||||
@@ -90,6 +95,7 @@ public class InlineView extends LabelView {
|
||||
* @see View#changedUpdate
|
||||
*/
|
||||
public void changedUpdate(DocumentEvent e, Shape a, ViewFactory f) {
|
||||
wrapAnywhereMinimumSpan = -1;
|
||||
super.changedUpdate(e, a, f);
|
||||
StyleSheet sheet = getStyleSheet();
|
||||
attr = sheet.getViewAttributes(this);
|
||||
@@ -206,6 +212,8 @@ public class InlineView extends LabelView {
|
||||
nowrap = false;
|
||||
}
|
||||
|
||||
wrapAnywhere = "anywhere".equals(a.getAttribute(CSS.Attribute.OVERFLOW_WRAP));
|
||||
|
||||
HTMLDocument doc = (HTMLDocument)getDocument();
|
||||
// fetches background color from stylesheet if specified
|
||||
Color bg = doc.getBackground(a);
|
||||
@@ -224,6 +232,41 @@ public class InlineView extends LabelView {
|
||||
return doc.getStyleSheet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getMinimumSpan(int axis) {
|
||||
if (axis == View.X_AXIS && wrapAnywhere) {
|
||||
if (wrapAnywhereMinimumSpan < 0) {
|
||||
wrapAnywhereMinimumSpan = 0;
|
||||
int startOffset = getStartOffset();
|
||||
int endOffset = getEndOffset();
|
||||
Document doc = getDocument();
|
||||
if ((doc != null) && Boolean.TRUE.equals(doc.getProperty(HTMLDocument.MultiByteProperty))) {
|
||||
Container c = getContainer();
|
||||
Locale locale = (c == null ? Locale.getDefault() : c.getLocale());
|
||||
BreakIterator breaker = BreakIterator.getCharacterInstance(locale);
|
||||
int[] breakSpots = GlyphViewAccessor.getAccessor().calcBreakSpots(this, breaker);
|
||||
int lastBreak = endOffset;
|
||||
for (int breakSpot : breakSpots) {
|
||||
wrapAnywhereMinimumSpan = Math.max(wrapAnywhereMinimumSpan,
|
||||
getPartialSpan(breakSpot, lastBreak));
|
||||
lastBreak = breakSpot;
|
||||
}
|
||||
wrapAnywhereMinimumSpan = Math.max(wrapAnywhereMinimumSpan,
|
||||
getPartialSpan(startOffset, lastBreak));
|
||||
} else {
|
||||
for (int i = startOffset ; i < endOffset; i++) {
|
||||
wrapAnywhereMinimumSpan = Math.max(wrapAnywhereMinimumSpan,
|
||||
getPartialSpan(i, i + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return wrapAnywhereMinimumSpan;
|
||||
}
|
||||
return super.getMinimumSpan(axis);
|
||||
}
|
||||
|
||||
private float wrapAnywhereMinimumSpan = -1;
|
||||
private boolean wrapAnywhere;
|
||||
private boolean nowrap;
|
||||
private AttributeSet attr;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2021 JetBrains s.r.o.
|
||||
* 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.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package sun.swing.text;
|
||||
|
||||
import javax.swing.text.GlyphView;
|
||||
import java.text.BreakIterator;
|
||||
|
||||
public abstract class GlyphViewAccessor {
|
||||
private static GlyphViewAccessor accessor;
|
||||
|
||||
public static void setAccessor(GlyphViewAccessor a) {
|
||||
accessor = a;
|
||||
}
|
||||
|
||||
public static GlyphViewAccessor getAccessor() {
|
||||
return accessor;
|
||||
}
|
||||
|
||||
public abstract int[] calcBreakSpots(GlyphView glyphView, BreakIterator breaker);
|
||||
}
|
||||
Reference in New Issue
Block a user