Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions ide/editor.lib/src/org/netbeans/editor/GlyphGutter.java
Original file line number Diff line number Diff line change
Expand Up @@ -531,6 +531,8 @@ public void run() {
Shape pViewAlloc = pViewDesc.getAllocation();
Rectangle pViewRect = pViewAlloc.getBounds();
pViewRect.width = repaintWidth;
pViewRect.y += pViewDesc.getShadowHeight();
pViewRect.height -= pViewDesc.getShadowHeight();
if (pViewRect.y >= endRepaintY) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("GlyphGutter: pViewRect.y=" + pViewRect.y + " >= endRepaintY=" + // NOI18N
Expand Down
3 changes: 2 additions & 1 deletion ide/editor.lib2/nbproject/project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
# under the License.

is.autoload=true
javac.source=1.8
javac.source=17
javac.target=17
Comment on lines -19 to +20
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this can't be javac.release, please add a comment why not, otherwise someone might break this in future.

javac.compilerargs=-Xlint:unchecked
spec.version.base=2.50.0

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,13 +160,15 @@ public AttributeSet cutSameFont(Font defaultFont, int maxEndOffset, int wsEndOff
// Extends beyond first highlight
Font firstFont = ViewUtils.getFont(firstAttrs, defaultFont);
Object firstPrependText = firstAttrs != null ? firstAttrs.getAttribute(ViewUtils.KEY_VIRTUAL_TEXT_PREPEND) : null;
Object firstShadowPrependText = firstAttrs != null ? firstAttrs.getAttribute(ViewUtils.KEY_SHADOW_TEXT_PREPEND) : null;
int index = 1;
while (true) {
item = get(index);
AttributeSet attrs = item.getAttributes();
Font font = ViewUtils.getFont(attrs, defaultFont);
Object prependText = attrs != null ? attrs.getAttribute(ViewUtils.KEY_VIRTUAL_TEXT_PREPEND) : null;
if (!font.equals(firstFont) || !Objects.equals(firstPrependText, prependText)) { // Stop at itemEndOffset
Object shadowPrependText = attrs != null ? attrs.getAttribute(ViewUtils.KEY_SHADOW_TEXT_PREPEND) : null;
if (!font.equals(firstFont) || !Objects.equals(firstPrependText, prependText) || !Objects.equals(firstShadowPrependText, shadowPrependText)) { // Stop at itemEndOffset
if (index == 1) { // Just single attribute set
cutStartItems(1);
startOffset = itemEndOffset; // end offset of first item
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ int getNextVisualPositionY(DocumentView docView, int offset, Bias bias, Shape do
pAlloc = getChildAllocation(docView, pIndex, docViewAlloc);
}
docView.op.getTextLayoutCache().activate(pView);
retOffset = pView.children.getNextVisualPositionY(pView, offset, bias, pAlloc, southDirection, biasRet, x);
retOffset = pView.getNextVisualPositionY(pView, offset, bias, pAlloc, southDirection, biasRet, x);
if (retOffset == -1) {
offset = -1; // Continue by entering the paragraph from outside
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,7 @@ public final class DocumentViewOp
private int defaultRowHeightInt;

private int defaultAscentInt;
private float defaultDescent;

private float defaultCharWidth;

Expand Down Expand Up @@ -1087,6 +1088,7 @@ private void updateRowHeight(FontInfo fontInfo, boolean force) {
": defaultAscentInt from " + defaultAscentInt + " to " + fontInfo.ascentInt + "\n"); // NOI18N
}
defaultAscentInt = fontInfo.ascentInt;
defaultDescent = fontInfo.descent;
}
if (force || defaultRowHeightInt < fontInfo.rowHeightInt) {
if (LOG.isLoggable(Level.FINE)) {
Expand Down Expand Up @@ -1276,6 +1278,11 @@ public float getDefaultAscent() {
return defaultAscentInt;
}

public float getDefaultDescent() {
checkSettingsInfo();
return defaultDescent;
}

/**
* Return array of default:
* <ol>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ public EditorView createView(int startOffset, int limitOffset, boolean forcedLim
}

private @NonNull EditorView wrapWithPrependedText(@NonNull EditorView origView, @NullAllowed AttributeSet attrs) {
if (attrs != null && attrs.getAttribute(ViewUtils.KEY_VIRTUAL_TEXT_PREPEND) instanceof String) {
if (attrs != null && (attrs.getAttribute(ViewUtils.KEY_VIRTUAL_TEXT_PREPEND) instanceof String || attrs.getAttribute(ViewUtils.KEY_SHADOW_TEXT_PREPEND) instanceof String)) {
return new PrependedTextView(documentView().op, attrs, origView);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.font.TextLayout;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.swing.JComponent;
import javax.swing.SwingConstants;
Expand Down Expand Up @@ -113,6 +117,8 @@ public final class ParagraphView extends EditorView implements EditorView.Parent

private int statusBits; // 44 + 4 = 48 bytes

private List<TextLayout> shadowText; // 44 + 4 = 52 bytes

public ParagraphView(Position startPos) {
super(null);
setStartPosition(startPos);
Expand Down Expand Up @@ -225,6 +231,39 @@ public void replace(int index, int removeLength, View[] addViews) {
assert (removeLength == 0) : "Attempt to remove from null children length=" + removeLength; // NOI18N
children = new ParagraphViewChildren(addViews.length);
}
if (index == 0 && addViews != null) {
if (shadowText != null && !shadowText.isEmpty()) {
shadowText.clear();
}

AttributeSet attrs = addViews[0].getAttributes();
Object shadowTextDataAttr = attrs != null ? attrs.getAttribute(ViewUtils.KEY_VERTICAL_SHADOW_TEXT_PREPEND) : null;
DocumentView docView = getDocumentView();
DocumentViewOp op = docView.op;
float shadowTextHeight = 0;
float shadowTextWidth = 0;

if (shadowTextDataAttr instanceof String shadowTextData) {
if (shadowText == null) {
shadowText = new ArrayList<>();
}
Font shadowTextFont = ViewUtils.getFont(getAttributes(), op.getDefaultFont());
for (String line : shadowTextData.split("\n")) { //XXX: performance!
//duplicated code:
if (line.isEmpty()) {
line = " ";
}
final TextLayout l = op.createTextLayout(line, shadowTextFont);
shadowText.add(l);
shadowTextHeight += height(l); //???
shadowTextWidth = Math.max(shadowTextWidth, l.getAdvance()); //???
}
}

children.shadowHeight = shadowTextHeight;
children.shadowWidth = shadowTextWidth;
}

children.replace(this, index, removeLength, addViews);
}

Expand Down Expand Up @@ -356,7 +395,18 @@ public int getViewIndexChecked(double x, double y, Shape alloc) {
@Override
public Shape modelToViewChecked(int offset, Shape alloc, Bias bias) {
checkChildrenNotNull();
return children.modelToViewChecked(this, offset, alloc, bias);
Shape ret = children.modelToViewChecked(this, offset, alloc, bias);
if (shadowText != null) {
//XXX: cached shadowText height
Rectangle2D bounds = ret.getBounds2D();
float shadowHeight = 0;
for (TextLayout l : shadowText) {
shadowHeight += height(l);
}
bounds.setRect(bounds.getX(), bounds.getY() + shadowHeight, bounds.getWidth(), bounds.getHeight());
ret = bounds;
}
return ret;
}

@Override
Expand All @@ -369,6 +419,24 @@ public int viewToModelChecked(double x, double y, Shape alloc, Bias[] biasReturn
public void paint(Graphics2D g, Shape alloc, Rectangle clipBounds) {
// The background is already cleared by BasicTextUI.paintBackground() which uses component.getBackground()
checkChildrenNotNull();
if (shadowText != null && !shadowText.isEmpty()) {
Rectangle2D.Double bounds = ViewUtils.shape2Bounds(alloc);
Rectangle2D.Double span = new Rectangle2D.Double(0, 0, 0, 0);
double y = bounds.y;
for (TextLayout l : shadowText) {
g.setColor(Color.gray);
float h = height(l);
span.setRect(bounds.x, y, l.getAdvance(), h);
HighlightsViewUtils.paintTextLayout(g, span, l, getDocumentView());
y += h;
}

bounds.height -= y - bounds.y;
bounds.y = y;

alloc = bounds;
}

children.paint(this, g, alloc, clipBounds);

if (getDocumentView().op.isGuideLinesEnable()) {
Expand Down Expand Up @@ -507,6 +575,12 @@ public int getNextVisualPositionFromChecked(int offset, Bias bias, Shape alloc,
retOffset = children.getNextVisualPositionY(this, offset, bias, alloc,
direction == SwingConstants.SOUTH, biasRet,
HighlightsViewUtils.getMagicX(docView, this, offset, bias, alloc));
if (shadowText != null && direction == SwingConstants.SOUTH) {
//TODO: reuse computed height
for (TextLayout l : shadowText) {
retOffset += height(l);
}
}
} else {
retOffset = offset;
}
Expand All @@ -516,7 +590,19 @@ public int getNextVisualPositionFromChecked(int offset, Bias bias, Shape alloc,
}
return retOffset;
}


//TODO: investigate:
int getNextVisualPositionY(ParagraphView pView,
int offset, Bias bias, Shape pAlloc, boolean southDirection, Bias[] biasRet, double x) {
int retOffset = children.getNextVisualPositionY(pView, offset, bias, pAlloc, southDirection, biasRet, x);
// if (shadowText != null && southDirection) {
// for (TextLayout l : shadowText) {
// retOffset += l.getAscent() + l.getDescent();
// }
// }
return retOffset;
}

void releaseTextLayouts() {
children = null;
markChildrenInvalid();
Expand Down Expand Up @@ -629,4 +715,7 @@ protected String getDumpName() {
return "PV";
}

private float height(TextLayout l) {
return (float) Math.ceil(l.getAscent() + l.getDescent());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,21 @@ public ParagraphViewChildren(int capacity) {
boolean isWrapped() {
return (wrapInfo != null);
}


//TODO: move to ParagraphView:
float shadowHeight;
float shadowWidth;

/**
* Height of
* @return
*/
float height() {
return (wrapInfo == null) ? childrenHeight : wrapInfo.height(this);
return ((wrapInfo == null) ? childrenHeight : wrapInfo.height(this)) + shadowHeight;
}

float width() {
return (wrapInfo == null) ? (float) childrenWidth() : wrapInfo.width();
return Math.max((wrapInfo == null) ? (float) childrenWidth() : wrapInfo.width(), shadowWidth);
}

double childrenWidth() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,9 @@ public float getAscent() {
return docView.op.getDefaultAscent(); // Currently the ascent is global
}

public float getShadowHeight() {
ParagraphViewChildren pViewChildren = docView.getParagraphView(pViewIndex).children;
return pViewChildren != null ? pViewChildren.shadowHeight : 0;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -39,27 +39,50 @@ public final class PrependedTextView extends EditorView {
private final EditorView delegate;
private final TextLayout prependedTextLayout;
private final double prependedTextWidth;
private final TextLayout shadowPrependedTextLayout;
private final double shadowPrependedTextWidth;

public PrependedTextView(DocumentViewOp op, AttributeSet attributes, EditorView delegate) {
super(null);
this.attributes = attributes;
this.delegate = delegate;
Font font = ViewUtils.getFont(attributes, op.getDefaultHintFont());
prependedTextLayout = op.createTextLayout((String) attributes.getAttribute(ViewUtils.KEY_VIRTUAL_TEXT_PREPEND), font);
// Advance represents the width of the full string, including leading
// and trailing spaces
float width = prependedTextLayout.getAdvance();
// The prependTextWidth is rounded to full char widths, so that layout
// is not destroyed too much
double em = op.getDefaultCharWidth();
prependedTextWidth = Math.ceil(width / em) * em;

if (attributes.getAttribute(ViewUtils.KEY_SHADOW_TEXT_PREPEND) instanceof String shadowText) {
Font shadowTextFont = ViewUtils.getFont(attributes, op.getDefaultFont());
shadowPrependedTextLayout = op.createTextLayout(shadowText, shadowTextFont);
// Advance represents the width of the full string, including leading
// and trailing spaces
float width = shadowPrependedTextLayout.getAdvance();
// The prependTextWidth is rounded to full char widths, so that layout
// is not destroyed too much
double em = op.getDefaultCharWidth();
shadowPrependedTextWidth = Math.ceil(width / em) * em;
} else {
shadowPrependedTextLayout = null;
shadowPrependedTextWidth = 0;
}

if (attributes.getAttribute(ViewUtils.KEY_VIRTUAL_TEXT_PREPEND) instanceof String virtualText) {
Font font = ViewUtils.getFont(attributes, op.getDefaultHintFont());
prependedTextLayout = op.createTextLayout(virtualText, font);
// Advance represents the width of the full string, including leading
// and trailing spaces
float width = prependedTextLayout.getAdvance();
// The prependTextWidth is rounded to full char widths, so that layout
// is not destroyed too much
double em = op.getDefaultCharWidth();
prependedTextWidth = Math.ceil(width / em) * em;
} else {
prependedTextLayout = null;
prependedTextWidth = 0;
}
}

@Override
public float getPreferredSpan(int axis) {
float superSpan = delegate.getPreferredSpan(axis);
if (axis == View.X_AXIS) {
superSpan += prependedTextWidth;
superSpan += prependedTextWidth + shadowPrependedTextWidth;
}
return superSpan;
}
Expand All @@ -73,16 +96,16 @@ public AttributeSet getAttributes() {
public Shape modelToViewChecked(int offset, Shape alloc, Bias bias) {
Shape res = delegate.modelToViewChecked(offset, alloc, bias);
Rectangle2D rect = ViewUtils.shapeAsRect(res);
rect.setRect(rect.getX() + prependedTextWidth, rect.getY(), rect.getWidth(), rect.getHeight());
rect.setRect(rect.getX(), rect.getY(), rect.getWidth() + prependedTextWidth + shadowPrependedTextWidth, rect.getHeight());
return rect;
}

@Override
public void paint(Graphics2D g, Shape hViewAlloc, Rectangle clipBounds) {
Rectangle2D span = ViewUtils.shapeAsRect(hViewAlloc);
span.setRect(span.getX() + prependedTextWidth, span.getY(), span.getWidth() - prependedTextWidth, span.getHeight());
span.setRect(span.getX() + prependedTextWidth + shadowPrependedTextWidth, span.getY(), span.getWidth() - prependedTextWidth - shadowPrependedTextWidth, span.getHeight());
delegate.paint(g, span, clipBounds);
span.setRect(span.getX() - prependedTextWidth, span.getY(), prependedTextWidth, span.getHeight());
span.setRect(span.getX() - prependedTextWidth - shadowPrependedTextWidth, span.getY(), prependedTextWidth + shadowPrependedTextWidth, span.getHeight());

HighlightsSequence highlights = getDocumentView().getPaintHighlights(this, 0);

Expand All @@ -92,9 +115,17 @@ public void paint(Graphics2D g, Shape hViewAlloc, Rectangle clipBounds) {
HighlightsViewUtils.paintBackgroundHighlights(g, span, attrs, getDocumentView()); //TODO: clear some attributes (like boxes)???
}

g.setColor(Color.gray);
span.setRect(span.getX(), span.getY(), prependedTextWidth, span.getHeight());
HighlightsViewUtils.paintTextLayout(g, span, prependedTextLayout, getDocumentView());
if (shadowPrependedTextLayout != null) {
g.setColor(Color.gray);
span.setRect(span.getX(), span.getY(), shadowPrependedTextWidth, span.getHeight());
HighlightsViewUtils.paintTextLayout(g, span, shadowPrependedTextLayout, getDocumentView());
}

if (prependedTextLayout != null) {
g.setColor(Color.gray);
span.setRect(span.getX() + shadowPrependedTextWidth, span.getY(), prependedTextWidth, span.getHeight());
HighlightsViewUtils.paintTextLayout(g, span, prependedTextLayout, getDocumentView());
}
}

ParagraphView getParagraphView() {
Expand All @@ -119,8 +150,8 @@ public void setRawEndOffset(int offset) {
@Override
public int viewToModelChecked(double x, double y, Shape alloc, Position.Bias[] biasReturn) {
Rectangle2D bounds = ViewUtils.shapeAsRect(alloc);
bounds.setRect(bounds.getX() + prependedTextWidth, bounds.getY(),
bounds.getWidth() - prependedTextWidth, bounds.getHeight());
bounds.setRect(bounds.getX() + prependedTextWidth + shadowPrependedTextWidth, bounds.getY(),
bounds.getWidth() - prependedTextWidth + shadowPrependedTextWidth, bounds.getHeight());
if (x <= bounds.getX()) {
return getStartOffset();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
public final class ViewUtils {

public static final String KEY_VIRTUAL_TEXT_PREPEND = "virtual-text-prepend"; //NOI18N
public static final String KEY_SHADOW_TEXT_PREPEND = "shadow-text-prepend"; //NOI18N
public static final String KEY_VERTICAL_SHADOW_TEXT_PREPEND = "vertical-shadow-text-prepend"; //NOI18N

private ViewUtils() { // No instances
}
Expand Down
Loading
Loading