Skip to content

Commit

Permalink
Allow custom merge/replace semantics for TextPresentation ranges ecli…
Browse files Browse the repository at this point in the history
…pse-platform#2543

TextPresentation performs at least two tasks when applying new
StyleRanges:
- identify which style ranges need creating/matching with new styles
- merge or replace an individual style range

Decouple the two tasks by exposing methods for applying style range(s) that
accept a BiConsumer to customise how style ranges should be merged
  • Loading branch information
gregdyke committed Nov 27, 2024
1 parent 6a3eb35 commit 99a0bdb
Showing 1 changed file with 66 additions and 57 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import java.util.ArrayList;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.function.BiConsumer;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
Expand Down Expand Up @@ -233,7 +234,7 @@ public void addStyleRange(StyleRange range) {
* @since 3.0
*/
public void replaceStyleRange(StyleRange range) {
applyStyleRange(range, false);
applyStyleRange(range, this::replaceStyle);
}

/**
Expand All @@ -244,18 +245,20 @@ public void replaceStyleRange(StyleRange range) {
* @since 3.0
*/
public void mergeStyleRange(StyleRange range) {
applyStyleRange(range, true);
applyStyleRange(range, this::mergeStyle);
}

/**
* Applies the given range to this presentation. The range must be a
* subrange of the presentation's default range.
*
* @param range the range to be added
* @param merge <code>true</code> if the style should be merged instead of replaced
* @param styleRangeApplier method accepting a StyleRange template to be applied and a
* StyleRange target, the style being applied to. The target may be modified by the
* method
* @since 3.0
*/
private void applyStyleRange(StyleRange range, boolean merge) {
public void applyStyleRange(StyleRange range, BiConsumer<StyleRange, StyleRange> styleRangeApplier) {
if (range.length == 0)
return;

Expand All @@ -272,7 +275,7 @@ private void applyStyleRange(StyleRange range, boolean merge) {

defaultRange.start= start;
defaultRange.length= length;
applyStyle(range, defaultRange, merge);
styleRangeApplier.accept(range, defaultRange);
fRanges.add(defaultRange);
} else {
IRegion rangeRegion= new Region(start, length);
Expand All @@ -284,7 +287,7 @@ private void applyStyleRange(StyleRange range, boolean merge) {
defaultRange= range;
defaultRange.start= start;
defaultRange.length= length;
applyStyle(range, defaultRange, merge);
styleRangeApplier.accept(range, defaultRange);
fRanges.add(defaultRange);
return;
}
Expand Down Expand Up @@ -313,14 +316,14 @@ private void applyStyleRange(StyleRange range, boolean merge) {

defaultRange.start= start;
defaultRange.length= currentStart - start;
applyStyle(range, defaultRange, merge);
styleRangeApplier.accept(range, defaultRange);
fRanges.add(i, defaultRange);
i++; last++;


// Apply style to first part of current range
current.length= Math.min(end, currentEnd) - currentStart;
applyStyle(range, current, merge);
styleRangeApplier.accept(range, current);
}

if (start >= currentStart) {
Expand All @@ -333,7 +336,7 @@ private void applyStyleRange(StyleRange range, boolean merge) {
i++; last++;
fRanges.add(i, current);
}
applyStyle(range, current, merge);
styleRangeApplier.accept(range, current);
current.start= start;
current.length= Math.min(end, currentEnd) - start;
}
Expand All @@ -359,7 +362,7 @@ private void applyStyleRange(StyleRange range, boolean merge) {
defaultRange= range;
defaultRange.start= start;
defaultRange.length= end - start;
applyStyle(range, defaultRange, merge);
styleRangeApplier.accept(range, defaultRange);
fRanges.add(last, defaultRange);
}
}
Expand All @@ -374,7 +377,7 @@ private void applyStyleRange(StyleRange range, boolean merge) {
* @since 3.0
*/
public void replaceStyleRanges(StyleRange[] ranges) {
applyStyleRanges(ranges, false);
applyStyleRanges(ranges, this::replaceStyle);
}

/**
Expand All @@ -386,7 +389,7 @@ public void replaceStyleRanges(StyleRange[] ranges) {
* @since 3.0
*/
public void mergeStyleRanges(StyleRange[] ranges) {
applyStyleRanges(ranges, true);
applyStyleRanges(ranges, this::mergeStyle);
}

/**
Expand All @@ -395,10 +398,12 @@ public void mergeStyleRanges(StyleRange[] ranges) {
* by increasing offset and must not overlap (but may be adjacent).
*
* @param ranges the ranges to be added
* @param merge <code>true</code> if the style should be merged instead of replaced
* @param styleRangeApplier method accepting a StyleRange template to be applied and a
* StyleRange target, the style being applied to. The target may be modified by the
* method
* @since 3.0
*/
private void applyStyleRanges(StyleRange[] ranges, boolean merge) {
public void applyStyleRanges(StyleRange[] ranges, BiConsumer<StyleRange, StyleRange> styleRangeApplier) {
int j= 0;
ArrayList<StyleRange> oldRanges= fRanges;
ArrayList<StyleRange> newRanges= new ArrayList<>(2*ranges.length + oldRanges.size());
Expand All @@ -407,70 +412,74 @@ private void applyStyleRanges(StyleRange[] ranges, boolean merge) {
for (int m= getFirstIndexAfterWindow(new Region(range.start, range.length)); j < m; j++)
newRanges.add(oldRanges.get(j));
fRanges= newRanges; // for mergeStyleRange(...)
applyStyleRange(range, merge);
applyStyleRange(range, styleRangeApplier);
}
for (int m= oldRanges.size(); j < m; j++)
newRanges.add(oldRanges.get(j));
fRanges= newRanges;
}

/**
* Applies the template's style to the target.
* Merges the template's style to the target.
*
* @param template the style range to be used as template
* @param target the style range to which to apply the template
* @param merge <code>true</code> if the style should be merged instead of replaced
* @since 3.0
*/
private void applyStyle(StyleRange template, StyleRange target, boolean merge) {
if (merge) {
if (template.font != null)
target.font= template.font;
target.fontStyle|= template.fontStyle;

if (template.metrics != null)
target.metrics= template.metrics;
private void mergeStyle(StyleRange template, StyleRange target) {
if (template.font != null)
target.font= template.font;
target.fontStyle|= template.fontStyle;

if (template.foreground != null || template.underlineStyle == SWT.UNDERLINE_LINK)
target.foreground= template.foreground;
if (template.background != null)
target.background= template.background;
if (template.metrics != null)
target.metrics= template.metrics;

target.strikeout|= template.strikeout;
if (template.strikeoutColor != null)
target.strikeoutColor= template.strikeoutColor;
if (template.foreground != null || template.underlineStyle == SWT.UNDERLINE_LINK)
target.foreground= template.foreground;
if (template.background != null)
target.background= template.background;

target.underline|= template.underline;
if (template.underlineStyle != SWT.NONE && target.underlineStyle != SWT.UNDERLINE_LINK)
target.underlineStyle= template.underlineStyle;
target.strikeout|= template.strikeout;
if (template.strikeoutColor != null)
target.strikeoutColor= template.strikeoutColor;

if (template.underlineColor != null)
target.underlineColor= template.underlineColor;
target.underline|= template.underline;
if (template.underlineStyle != SWT.NONE && target.underlineStyle != SWT.UNDERLINE_LINK)
target.underlineStyle= template.underlineStyle;

if (template.borderStyle != SWT.NONE)
target.borderStyle= template.borderStyle;
if (template.borderColor != null)
target.borderColor= template.borderColor;
if (template.underlineColor != null)
target.underlineColor= template.underlineColor;

} else {
target.font= template.font;
target.fontStyle= template.fontStyle;
target.metrics= template.metrics;
target.foreground= template.foreground;
target.background= template.background;
target.strikeout= template.strikeout;
target.strikeoutColor= template.strikeoutColor;
target.underline= template.underline;
target.underlineStyle= template.underlineStyle;
target.underlineColor= template.underlineColor;
target.borderStyle= template.borderStyle;
target.borderColor= template.borderColor;
}
if (template.borderStyle != SWT.NONE)
target.borderStyle= template.borderStyle;
if (template.borderColor != null)
target.borderColor= template.borderColor;
}

/**
* Checks whether the given range is a subrange of the presentation's
* default style range.
* Replaces the target's style with the template.
*
* @param template the style range to be used as template
* @param target the style range to which to apply the template
* @since 3.0
*/
private void replaceStyle(StyleRange template, StyleRange target) {
target.font= template.font;
target.fontStyle= template.fontStyle;
target.metrics= template.metrics;
target.foreground= template.foreground;
target.background= template.background;
target.strikeout= template.strikeout;
target.strikeoutColor= template.strikeoutColor;
target.underline= template.underline;
target.underlineStyle= template.underlineStyle;
target.underlineColor= template.underlineColor;
target.borderStyle= template.borderStyle;
target.borderColor= template.borderColor;
}

/**
* Checks whether the given range is a subrange of the presentation's default style range.
*
* @param range the range to be checked
* @exception IllegalArgumentException if range is not a subrange of the presentation's default range
Expand Down

0 comments on commit 99a0bdb

Please sign in to comment.