1
0
mirror of https://github.com/octoleo/plantuml.git synced 2024-12-22 19:09:03 +00:00

fix: improve local style management for activity diagrams

https://github.com/plantuml/plantuml/issues/1629
This commit is contained in:
Arnaud Roques 2023-12-19 19:08:24 +01:00
parent b65aaff80b
commit 26189b1e64
16 changed files with 249 additions and 29 deletions

View File

@ -1,4 +1,4 @@
# Warning, "version" should be the same in gradle.properties and Version.java # Warning, "version" should be the same in gradle.properties and Version.java
# Any idea anyone how to magically synchronize those :-) ? # Any idea anyone how to magically synchronize those :-) ?
version = 1.2023.14beta1 version = 1.2023.14beta2
org.gradle.workers.max = 3 org.gradle.workers.max = 3

View File

@ -59,6 +59,7 @@ import net.sourceforge.plantuml.sequencediagram.NotePosition;
import net.sourceforge.plantuml.sequencediagram.NoteType; import net.sourceforge.plantuml.sequencediagram.NoteType;
import net.sourceforge.plantuml.stereo.Stereotype; import net.sourceforge.plantuml.stereo.Stereotype;
import net.sourceforge.plantuml.style.ISkinParam; import net.sourceforge.plantuml.style.ISkinParam;
import net.sourceforge.plantuml.style.StyleBuilder;
public class InstructionRepeat extends AbstractInstruction implements Instruction { public class InstructionRepeat extends AbstractInstruction implements Instruction {
@ -87,6 +88,7 @@ public class InstructionRepeat extends AbstractInstruction implements Instructio
private LinkRendering endRepeatLinkRendering = LinkRendering.none(); private LinkRendering endRepeatLinkRendering = LinkRendering.none();
private final Colors colors; private final Colors colors;
private final StyleBuilder currentStyleBuilder;
public boolean containsBreak() { public boolean containsBreak() {
return repeatList.containsBreak(); return repeatList.containsBreak();
@ -94,6 +96,7 @@ public class InstructionRepeat extends AbstractInstruction implements Instructio
public InstructionRepeat(Swimlanes swimlanes, Instruction parent, LinkRendering nextLinkRenderer, HColor color, public InstructionRepeat(Swimlanes swimlanes, Instruction parent, LinkRendering nextLinkRenderer, HColor color,
Display startLabel, BoxStyle boxStyleIn, Colors colors) { Display startLabel, BoxStyle boxStyleIn, Colors colors) {
this.currentStyleBuilder = swimlanes.getCurrentStyleBuilder();
this.swimlanes = swimlanes; this.swimlanes = swimlanes;
this.swimlane = swimlanes.getCurrentSwimlane(); this.swimlane = swimlanes.getCurrentSwimlane();
this.repeatList = new InstructionList(this.swimlane); this.repeatList = new InstructionList(this.swimlane);
@ -158,7 +161,7 @@ public class InstructionRepeat extends AbstractInstruction implements Instructio
if (this.testCalled == false && incoming1.isNone()) if (this.testCalled == false && incoming1.isNone())
incoming1 = swimlanes.nextLinkRenderer(); incoming1 = swimlanes.nextLinkRenderer();
final Ftile result = factory.repeat(boxStyleIn, swimlane, swimlaneOut, startLabel, decorateOut, test, yes, out, final Ftile result = factory.repeat(boxStyleIn, swimlane, swimlaneOut, startLabel, decorateOut, test, yes, out,
colors, back, isLastOfTheParent(), incoming1, incoming2); colors, back, isLastOfTheParent(), incoming1, incoming2, currentStyleBuilder);
if (killed) if (killed)
return new FtileKilled(result); return new FtileKilled(result);

View File

@ -56,6 +56,7 @@ import net.sourceforge.plantuml.klimt.geom.VerticalAlignment;
import net.sourceforge.plantuml.sequencediagram.NotePosition; import net.sourceforge.plantuml.sequencediagram.NotePosition;
import net.sourceforge.plantuml.sequencediagram.NoteType; import net.sourceforge.plantuml.sequencediagram.NoteType;
import net.sourceforge.plantuml.style.ISkinParam; import net.sourceforge.plantuml.style.ISkinParam;
import net.sourceforge.plantuml.style.StyleBuilder;
public class InstructionWhile extends WithNote implements Instruction, InstructionCollection { public class InstructionWhile extends WithNote implements Instruction, InstructionCollection {
@ -82,6 +83,7 @@ public class InstructionWhile extends WithNote implements Instruction, Instructi
private LinkRendering incoming1 = LinkRendering.none(); private LinkRendering incoming1 = LinkRendering.none();
private LinkRendering incoming2 = LinkRendering.none(); private LinkRendering incoming2 = LinkRendering.none();
private boolean backwardCalled; private boolean backwardCalled;
private final StyleBuilder currentStyleBuilder;
public void overwriteYes(Display yes) { public void overwriteYes(Display yes) {
this.yes = yes; this.yes = yes;
@ -94,6 +96,7 @@ public class InstructionWhile extends WithNote implements Instruction, Instructi
this.nextLinkRenderer = Objects.requireNonNull(nextLinkRenderer); this.nextLinkRenderer = Objects.requireNonNull(nextLinkRenderer);
this.yes = Objects.requireNonNull(yes); this.yes = Objects.requireNonNull(yes);
this.swimlane = swimlane; this.swimlane = swimlane;
this.currentStyleBuilder = skinParam.getCurrentStyleBuilder();
this.color = color; this.color = color;
this.skinParam = skinParam; this.skinParam = skinParam;
} }
@ -118,7 +121,7 @@ public class InstructionWhile extends WithNote implements Instruction, Instructi
final Ftile back = Display.isNull(backward) ? null final Ftile back = Display.isNull(backward) ? null
: factory.activity(backward, swimlane, boxStyle, Colors.empty(), null); : factory.activity(backward, swimlane, boxStyle, Colors.empty(), null);
Ftile tmp = repeatList.createFtile(factory); Ftile tmp = repeatList.createFtile(factory);
tmp = factory.createWhile(outColor, swimlane, tmp, test, yes, color, specialOut, back, incoming1, incoming2); tmp = factory.createWhile(outColor, swimlane, tmp, test, yes, color, specialOut, back, incoming1, incoming2, currentStyleBuilder);
if (getPositionedNotes().size() > 0) if (getPositionedNotes().size() > 0)
tmp = FtileWithNoteOpale.create(tmp, getPositionedNotes(), false, VerticalAlignment.CENTER); tmp = FtileWithNoteOpale.create(tmp, getPositionedNotes(), false, VerticalAlignment.CENTER);

View File

@ -84,10 +84,11 @@ public interface FtileFactory {
public Ftile repeat(BoxStyle boxStyleIn, Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, Ftile repeat, public Ftile repeat(BoxStyle boxStyleIn, Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, Ftile repeat,
Display test, Display yes, Display out, Colors colors, Ftile backward, boolean noOut, Display test, Display yes, Display out, Colors colors, Ftile backward, boolean noOut,
LinkRendering incoming1, LinkRendering incoming2); LinkRendering incoming1, LinkRendering incoming2, StyleBuilder currentStyleBuilder);
public Ftile createWhile(LinkRendering outColor, Swimlane swimlane, Ftile whileBlock, Display test, Display yes, public Ftile createWhile(LinkRendering outColor, Swimlane swimlane, Ftile whileBlock, Display test, Display yes,
HColor color, Instruction specialOut, Ftile backward, LinkRendering incoming1, LinkRendering incoming2); HColor color, Instruction specialOut, Ftile backward, LinkRendering incoming1, LinkRendering incoming2,
StyleBuilder currentStyleBuilder);
public Ftile createIf(Swimlane swimlane, List<Branch> thens, Branch elseBranch, LinkRendering outColor, public Ftile createIf(Swimlane swimlane, List<Branch> thens, Branch elseBranch, LinkRendering outColor,
LinkRendering topInlinkRendering, Url url, Collection<PositionedNote> notes, Stereotype stereotype, LinkRendering topInlinkRendering, Url url, Collection<PositionedNote> notes, Stereotype stereotype,

View File

@ -175,16 +175,17 @@ public class FtileFactoryDelegator implements FtileFactory {
@Override @Override
public Ftile repeat(BoxStyle boxStyleIn, Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, Ftile repeat, public Ftile repeat(BoxStyle boxStyleIn, Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, Ftile repeat,
Display test, Display yes, Display out, Colors colors, Ftile backward, boolean noOut, Display test, Display yes, Display out, Colors colors, Ftile backward, boolean noOut,
LinkRendering incoming1, LinkRendering incoming2) { LinkRendering incoming1, LinkRendering incoming2, StyleBuilder currentStyleBuilder) {
return factory.repeat(boxStyleIn, swimlane, swimlaneOut, startLabel, repeat, test, yes, out, colors, backward, return factory.repeat(boxStyleIn, swimlane, swimlaneOut, startLabel, repeat, test, yes, out, colors, backward,
noOut, incoming1, incoming2); noOut, incoming1, incoming2, currentStyleBuilder);
} }
@Override @Override
public Ftile createWhile(LinkRendering outColor, Swimlane swimlane, Ftile whileBlock, Display test, Display yes, public Ftile createWhile(LinkRendering outColor, Swimlane swimlane, Ftile whileBlock, Display test, Display yes,
HColor color, Instruction specialOut, Ftile back, LinkRendering incoming1, LinkRendering incoming2) { HColor color, Instruction specialOut, Ftile back, LinkRendering incoming1, LinkRendering incoming2,
StyleBuilder styleBuilder) {
return factory.createWhile(outColor, swimlane, whileBlock, test, yes, color, specialOut, back, incoming1, return factory.createWhile(outColor, swimlane, whileBlock, test, yes, color, specialOut, back, incoming1,
incoming2); incoming2, styleBuilder);
} }
@Override @Override

View File

@ -82,6 +82,7 @@ import net.sourceforge.plantuml.style.ISkinParam;
import net.sourceforge.plantuml.style.PName; import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.SName; import net.sourceforge.plantuml.style.SName;
import net.sourceforge.plantuml.style.Style; import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleBuilder;
import net.sourceforge.plantuml.style.StyleSignatureBasic; import net.sourceforge.plantuml.style.StyleSignatureBasic;
import net.sourceforge.plantuml.style.Styleable; import net.sourceforge.plantuml.style.Styleable;
import net.sourceforge.plantuml.svek.UGraphicForSnake; import net.sourceforge.plantuml.svek.UGraphicForSnake;
@ -127,9 +128,9 @@ public class Swimlanes extends AbstractTextBlock implements TextBlock, Styleable
} }
protected Style getStyle() { protected Style getStyle() {
if (style == null) { if (style == null)
this.style = getStyleSignature().getMergedStyle(skinParam.getCurrentStyleBuilder()); this.style = getStyleSignature().getMergedStyle(skinParam.getCurrentStyleBuilder());
}
return style; return style;
} }
@ -455,4 +456,8 @@ public class Swimlanes extends AbstractTextBlock implements TextBlock, Styleable
return cachedMinMax; return cachedMinMax;
} }
public StyleBuilder getCurrentStyleBuilder() {
return skinParam.getCurrentStyleBuilder();
}
} }

View File

@ -62,6 +62,7 @@ import net.sourceforge.plantuml.klimt.font.FontConfiguration;
import net.sourceforge.plantuml.klimt.geom.XDimension2D; import net.sourceforge.plantuml.klimt.geom.XDimension2D;
import net.sourceforge.plantuml.style.PName; import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.Style; import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleBuilder;
import net.sourceforge.plantuml.svek.ConditionStyle; import net.sourceforge.plantuml.svek.ConditionStyle;
public class FtileFactoryDelegatorRepeat extends FtileFactoryDelegator { public class FtileFactoryDelegatorRepeat extends FtileFactoryDelegator {
@ -73,13 +74,12 @@ public class FtileFactoryDelegatorRepeat extends FtileFactoryDelegator {
@Override @Override
public Ftile repeat(BoxStyle boxStyleIn, Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, public Ftile repeat(BoxStyle boxStyleIn, Swimlane swimlane, Swimlane swimlaneOut, Display startLabel,
final Ftile repeat, Display test, Display yes, Display out, Colors colors, Ftile backward, boolean noOut, final Ftile repeat, Display test, Display yes, Display out, Colors colors, Ftile backward, boolean noOut,
LinkRendering incoming1, LinkRendering incoming2) { LinkRendering incoming1, LinkRendering incoming2, StyleBuilder currentStyleBuilder) {
final ConditionStyle conditionStyle = skinParam().getConditionStyle(); final ConditionStyle conditionStyle = skinParam().getConditionStyle();
final Style styleArrow = getDefaultStyleDefinitionArrow().getMergedStyle(skinParam().getCurrentStyleBuilder()); final Style styleArrow = getDefaultStyleDefinitionArrow().getMergedStyle(currentStyleBuilder);
final Style styleDiamond = getDefaultStyleDefinitionDiamond() final Style styleDiamond = getDefaultStyleDefinitionDiamond().getMergedStyle(currentStyleBuilder);
.getMergedStyle(skinParam().getCurrentStyleBuilder());
final HColor borderColor = styleDiamond.value(PName.LineColor).asColor(skinParam().getIHtmlColorSet()); final HColor borderColor = styleDiamond.value(PName.LineColor).asColor(skinParam().getIHtmlColorSet());
final HColor diamondColor = styleDiamond.value(PName.BackGroundColor).asColor(skinParam().getIHtmlColorSet()); final HColor diamondColor = styleDiamond.value(PName.BackGroundColor).asColor(skinParam().getIHtmlColorSet());
final Rainbow arrowColor = Rainbow.build(styleArrow, skinParam().getIHtmlColorSet()); final Rainbow arrowColor = Rainbow.build(styleArrow, skinParam().getIHtmlColorSet());

View File

@ -58,6 +58,7 @@ import net.sourceforge.plantuml.klimt.drawing.UGraphic;
import net.sourceforge.plantuml.klimt.font.FontConfiguration; import net.sourceforge.plantuml.klimt.font.FontConfiguration;
import net.sourceforge.plantuml.style.PName; import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.Style; import net.sourceforge.plantuml.style.Style;
import net.sourceforge.plantuml.style.StyleBuilder;
import net.sourceforge.plantuml.svek.ConditionStyle; import net.sourceforge.plantuml.svek.ConditionStyle;
public class FtileFactoryDelegatorWhile extends FtileFactoryDelegator { public class FtileFactoryDelegatorWhile extends FtileFactoryDelegator {
@ -68,13 +69,13 @@ public class FtileFactoryDelegatorWhile extends FtileFactoryDelegator {
@Override @Override
public Ftile createWhile(LinkRendering outColor, Swimlane swimlane, Ftile whileBlock, Display test, Display yes, public Ftile createWhile(LinkRendering outColor, Swimlane swimlane, Ftile whileBlock, Display test, Display yes,
HColor color, Instruction specialOut, Ftile backward, LinkRendering incoming1, LinkRendering incoming2) { HColor color, Instruction specialOut, Ftile backward, LinkRendering incoming1, LinkRendering incoming2,
StyleBuilder currentStyleBuilder) {
final ConditionStyle conditionStyle = skinParam().getConditionStyle(); final ConditionStyle conditionStyle = skinParam().getConditionStyle();
final Style styleArrow = getDefaultStyleDefinitionArrow().getMergedStyle(skinParam().getCurrentStyleBuilder()); final Style styleArrow = getDefaultStyleDefinitionArrow().getMergedStyle(currentStyleBuilder);
final Style styleDiamond = getDefaultStyleDefinitionDiamond() final Style styleDiamond = getDefaultStyleDefinitionDiamond().getMergedStyle(currentStyleBuilder);
.getMergedStyle(skinParam().getCurrentStyleBuilder());
final HColor borderColor = styleDiamond.value(PName.LineColor).asColor(skinParam().getIHtmlColorSet()); final HColor borderColor = styleDiamond.value(PName.LineColor).asColor(skinParam().getIHtmlColorSet());
final HColor backColor = styleDiamond.value(PName.BackGroundColor).asColor(skinParam().getIHtmlColorSet()); final HColor backColor = styleDiamond.value(PName.BackGroundColor).asColor(skinParam().getIHtmlColorSet());
final Rainbow arrowColor = Rainbow.build(styleArrow, skinParam().getIHtmlColorSet()); final Rainbow arrowColor = Rainbow.build(styleArrow, skinParam().getIHtmlColorSet());

View File

@ -156,14 +156,14 @@ public class VCompactFactory implements FtileFactory {
@Override @Override
public Ftile repeat(BoxStyle boxStyleIn, Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, Ftile repeat, public Ftile repeat(BoxStyle boxStyleIn, Swimlane swimlane, Swimlane swimlaneOut, Display startLabel, Ftile repeat,
Display test, Display yes, Display out, Colors colors, Ftile backward, boolean noOut, Display test, Display yes, Display out, Colors colors, Ftile backward, boolean noOut,
LinkRendering incoming1, LinkRendering incoming2) { LinkRendering incoming1, LinkRendering incoming2, StyleBuilder currentStyleBuilder) {
return repeat; return repeat;
} }
@Override @Override
public Ftile createWhile(LinkRendering afterEndwhile, Swimlane swimlane, Ftile whileBlock, Display test, public Ftile createWhile(LinkRendering afterEndwhile, Swimlane swimlane, Ftile whileBlock, Display test,
Display yes, HColor color, Instruction specialOut, Ftile back, LinkRendering incoming1, Display yes, HColor color, Instruction specialOut, Ftile back, LinkRendering incoming1,
LinkRendering incoming2) { LinkRendering incoming2, StyleBuilder styleBuilder) {
return whileBlock; return whileBlock;
} }

View File

@ -0,0 +1,110 @@
/* ========================================================================
* PlantUML : a free UML diagram generator
* ========================================================================
*
* (C) Copyright 2009-2020, Arnaud Roques
*
* Project Info: https://plantuml.com
*
* If you like this project or if you find it useful, you can support us at:
*
* https://plantuml.com/patreon (only 1$ per month!)
* https://plantuml.com/paypal
*
* This file is part of PlantUML.
*
* PlantUML is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* PlantUML 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 for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
*
* Original Author: Arnaud Roques
*
*
*/
package net.sourceforge.plantuml.ebnf;
import net.sourceforge.plantuml.klimt.UStroke;
import net.sourceforge.plantuml.klimt.UTranslate;
import net.sourceforge.plantuml.klimt.color.HColor;
import net.sourceforge.plantuml.klimt.color.HColorSet;
import net.sourceforge.plantuml.klimt.drawing.UGraphic;
import net.sourceforge.plantuml.klimt.font.FontConfiguration;
import net.sourceforge.plantuml.klimt.font.StringBounder;
import net.sourceforge.plantuml.klimt.geom.XDimension2D;
import net.sourceforge.plantuml.klimt.shape.URectangle;
import net.sourceforge.plantuml.klimt.shape.UText;
import net.sourceforge.plantuml.style.PName;
import net.sourceforge.plantuml.style.Style;
public class ETileLookAheadOrBehind extends ETile {
private final ETile orig;
private final HColorSet colorSet;
private final double deltax1 = 4;
private final double deltax2 = 8;
private final double deltay = 6;
private final Style style;
private final UText supText;
private final FontConfiguration fc;
public ETileLookAheadOrBehind(ETile orig, FontConfiguration fc, Style style, HColorSet colorSet, String type) {
this.style = style;
this.orig = orig;
this.fc = fc;
this.colorSet = colorSet;
this.supText = UText.build(type, fc);
}
@Override
public double getH1(StringBounder stringBounder) {
return deltay + orig.getH1(stringBounder);
}
@Override
public double getH2(StringBounder stringBounder) {
return orig.getH2(stringBounder) + deltay;
}
@Override
public double getWidth(StringBounder stringBounder) {
return orig.getWidth(stringBounder) + deltax1 + deltax2 + supText.calculateDimension(stringBounder).getWidth();
}
@Override
public void drawU(UGraphic ug) {
final StringBounder stringBounder = ug.getStringBounder();
final XDimension2D dim = calculateDimension(stringBounder);
final HColor lineColor = style.value(PName.LineColor).asColor(colorSet);
final URectangle rect = URectangle.build(dim).rounded(30);
ug.apply(lineColor).apply(new UStroke(2, 3, 1)).draw(rect);
final double posText = getH1(stringBounder) + supText.getDescent(stringBounder);
ug.apply(new UTranslate(4, 2 + posText)).draw(supText);
orig.drawU(ug.apply(new UTranslate(deltax1 + supText.calculateDimension(stringBounder).getWidth(), deltay)));
}
@Override
public void push(ETile tile) {
throw new UnsupportedOperationException();
}
}

View File

@ -38,6 +38,7 @@ package net.sourceforge.plantuml.klimt.shape;
import net.sourceforge.plantuml.klimt.UShape; import net.sourceforge.plantuml.klimt.UShape;
import net.sourceforge.plantuml.klimt.font.FontConfiguration; import net.sourceforge.plantuml.klimt.font.FontConfiguration;
import net.sourceforge.plantuml.klimt.font.StringBounder; import net.sourceforge.plantuml.klimt.font.StringBounder;
import net.sourceforge.plantuml.klimt.geom.XDimension2D;
public class UText implements UShape { public class UText implements UShape {
@ -83,4 +84,8 @@ public class UText implements UShape {
return orientation; return orientation;
} }
public XDimension2D calculateDimension(StringBounder stringBounder) {
return stringBounder.calculateDimension(font.getFont(), text);
}
} }

View File

@ -52,6 +52,7 @@ import net.sourceforge.plantuml.ebnf.ETile;
import net.sourceforge.plantuml.ebnf.ETileAlternation; import net.sourceforge.plantuml.ebnf.ETileAlternation;
import net.sourceforge.plantuml.ebnf.ETileBox; import net.sourceforge.plantuml.ebnf.ETileBox;
import net.sourceforge.plantuml.ebnf.ETileConcatenation; import net.sourceforge.plantuml.ebnf.ETileConcatenation;
import net.sourceforge.plantuml.ebnf.ETileLookAheadOrBehind;
import net.sourceforge.plantuml.ebnf.ETileNamedGroup; import net.sourceforge.plantuml.ebnf.ETileNamedGroup;
import net.sourceforge.plantuml.ebnf.ETileOneOrMore; import net.sourceforge.plantuml.ebnf.ETileOneOrMore;
import net.sourceforge.plantuml.ebnf.ETileOptional; import net.sourceforge.plantuml.ebnf.ETileOptional;
@ -162,6 +163,10 @@ public class PSystemRegex extends TitledDiagram {
push(token, Symbol.TERMINAL_STRING1); push(token, Symbol.TERMINAL_STRING1);
else if (token.getType() == ReTokenType.GROUP) else if (token.getType() == ReTokenType.GROUP)
push(token, Symbol.SPECIAL_SEQUENCE); push(token, Symbol.SPECIAL_SEQUENCE);
else if (token.getType() == ReTokenType.LOOK_AHEAD)
lookAheadOrBehind(token.getData());
else if (token.getType() == ReTokenType.LOOK_BEHIND)
lookAheadOrBehind(token.getData());
else if (token.getType() == ReTokenType.NAMED_GROUP) else if (token.getType() == ReTokenType.NAMED_GROUP)
namedGroup(token.getData()); namedGroup(token.getData());
else if (token.getType() == ReTokenType.CLASS) else if (token.getType() == ReTokenType.CLASS)
@ -205,6 +210,11 @@ public class PSystemRegex extends TitledDiagram {
stack.addFirst(new ETileBox(element.getData(), type, fontConfiguration, style, colorSet, getSkinParam())); stack.addFirst(new ETileBox(element.getData(), type, fontConfiguration, style, colorSet, getSkinParam()));
} }
private void lookAheadOrBehind(String name) {
final ETile arg1 = stack.removeFirst();
stack.addFirst(new ETileLookAheadOrBehind(arg1, fontConfiguration, style, colorSet, name));
}
private void namedGroup(String name) { private void namedGroup(String name) {
final ETile arg1 = stack.removeFirst(); final ETile arg1 = stack.removeFirst();
stack.addFirst(new ETileNamedGroup(arg1, fontConfiguration, colorSet, getSkinParam(), name)); stack.addFirst(new ETileNamedGroup(arg1, fontConfiguration, colorSet, getSkinParam(), name));

View File

@ -44,13 +44,19 @@ public enum ReTokenType {
ANCHOR, // ANCHOR, //
GROUP, // GROUP, //
NAMED_GROUP, // NAMED_GROUP, //
LOOK_AHEAD, //
LOOK_BEHIND, //
ALTERNATIVE, // ALTERNATIVE, //
PARENTHESIS_OPEN, // PARENTHESIS_OPEN, //
PARENTHESIS_CLOSE, // PARENTHESIS_CLOSE, //
CONCATENATION_IMPLICIT; CONCATENATION_IMPLICIT;
public boolean isNamedGroupOrLookAheadOrLookBehind() {
return this == NAMED_GROUP || this == LOOK_AHEAD || this == LOOK_BEHIND;
}
static public boolean needImplicitConcatenation(ReTokenType token1, ReTokenType token2) { static public boolean needImplicitConcatenation(ReTokenType token1, ReTokenType token2) {
if (token1 == NAMED_GROUP) if (token1.isNamedGroupOrLookAheadOrLookBehind())
return false; return false;
if (token1 == ALTERNATIVE) if (token1 == ALTERNATIVE)
return false; return false;

View File

@ -60,11 +60,22 @@ public class RegexExpression {
} else if (current == '|') { } else if (current == '|') {
result.add(new ReToken(ReTokenType.ALTERNATIVE, "|")); result.add(new ReToken(ReTokenType.ALTERNATIVE, "|"));
it.jump(); it.jump();
} else if (isStartPosixGroup(it)) {
final String s = readGroupPosix(it);
result.add(new ReToken(ReTokenType.CLASS, s));
} else if (current == '[') { } else if (current == '[') {
final String s = readGroup(it); final String s = readGroup(it);
result.add(new ReToken(ReTokenType.GROUP, s)); result.add(new ReToken(ReTokenType.GROUP, s));
} else if (isStartComment(it)) { } else if (isStartComment(it)) {
skipComment(it); skipComment(it);
} else if (isStartLookAhead(it)) {
final ReToken token = readLookAhead(it);
result.add(token);
result.add(new ReToken(ReTokenType.PARENTHESIS_OPEN, "("));
} else if (isStartLookBehind(it)) {
final ReToken token = readLookBehind(it);
result.add(token);
result.add(new ReToken(ReTokenType.PARENTHESIS_OPEN, "("));
} else if (isStartNamedCapturingGroup(it)) { } else if (isStartNamedCapturingGroup(it)) {
final ReToken token = readNamedGroup(it); final ReToken token = readNamedGroup(it);
result.add(token); result.add(token);
@ -102,6 +113,20 @@ public class RegexExpression {
} }
private static boolean isStartLookAhead(CharInspector it) {
final char current0 = it.peek(0);
if (current0 == '(' && it.peek(1) == '?' && (it.peek(2) == '=' || it.peek(2) == '!'))
return true;
return false;
}
private static boolean isStartLookBehind(CharInspector it) {
final char current0 = it.peek(0);
if (current0 == '(' && it.peek(1) == '?' && it.peek(2) == '<' && (it.peek(3) == '=' || it.peek(3) == '!'))
return true;
return false;
}
private static boolean isStartOpenParenthesis(CharInspector it) { private static boolean isStartOpenParenthesis(CharInspector it) {
final char current0 = it.peek(0); final char current0 = it.peek(0);
if (current0 == '(') if (current0 == '(')
@ -109,10 +134,28 @@ public class RegexExpression {
return false; return false;
} }
private static boolean isStartPosixGroup(CharInspector it) {
final char current0 = it.peek(0);
if (current0 == '[' && it.peek(1) == '[' && it.peek(2) == ':')
return true;
return false;
}
private static boolean isStartNamedCapturingGroup(CharInspector it) { private static boolean isStartNamedCapturingGroup(CharInspector it) {
final char current0 = it.peek(0); final char current0 = it.peek(0);
if (current0 == '(' && it.peek(1) == '?' && it.peek(2) == '<') if (current0 == '(' && it.peek(1) == '?' && it.peek(2) == '<') {
return true; int i = 3;
while (it.peek(i) != 0) {
if (it.peek(i) == '>' && i == 3)
return false;
if (it.peek(i) == '>')
return true;
if (Character.isLetter(it.peek(i)) == false)
return false;
i++;
}
}
return false; return false;
} }
@ -140,6 +183,23 @@ public class RegexExpression {
} }
} }
private static ReToken readLookAhead(CharInspector it) throws RegexParsingException {
it.jump();
it.jump();
final char ch = it.peek(0);
it.jump();
return new ReToken(ReTokenType.LOOK_AHEAD, "?" + ch);
}
private static ReToken readLookBehind(CharInspector it) throws RegexParsingException {
it.jump();
it.jump();
it.jump();
final char ch = it.peek(0);
it.jump();
return new ReToken(ReTokenType.LOOK_BEHIND, "?<" + ch);
}
private static ReToken readNamedGroup(CharInspector it) throws RegexParsingException { private static ReToken readNamedGroup(CharInspector it) throws RegexParsingException {
it.jump(); it.jump();
it.jump(); it.jump();
@ -218,6 +278,23 @@ public class RegexExpression {
return false; return false;
} }
private static String readGroupPosix(CharInspector it) {
it.jump();
it.jump();
it.jump();
final StringBuilder result = new StringBuilder(":");
while (it.peek(0) != 0) {
char ch = it.peek(0);
it.jump();
result.append(ch);
if (ch == ':')
break;
}
it.jump();
it.jump();
return result.toString();
}
private static String readGroup(CharInspector it) { private static String readGroup(CharInspector it) {
final char current0 = it.peek(0); final char current0 = it.peek(0);
if (current0 != '[') if (current0 != '[')

View File

@ -59,7 +59,7 @@ public class ShuntingYard {
ouputQueue.add(token); ouputQueue.add(token);
} else if (token.getType() == ReTokenType.GROUP) { } else if (token.getType() == ReTokenType.GROUP) {
ouputQueue.add(token); ouputQueue.add(token);
} else if (token.getType() == ReTokenType.NAMED_GROUP) { } else if (token.getType().isNamedGroupOrLookAheadOrLookBehind()) {
operatorStack.addFirst(token); operatorStack.addFirst(token);
} else if (token.getType() == ReTokenType.CLASS) { } else if (token.getType() == ReTokenType.CLASS) {
ouputQueue.add(token); ouputQueue.add(token);
@ -82,11 +82,9 @@ public class ShuntingYard {
&& operatorStack.peekFirst().getType() != ReTokenType.PARENTHESIS_OPEN) && operatorStack.peekFirst().getType() != ReTokenType.PARENTHESIS_OPEN)
ouputQueue.add(operatorStack.removeFirst()); ouputQueue.add(operatorStack.removeFirst());
final ReToken first = operatorStack.removeFirst(); final ReToken first = operatorStack.removeFirst();
if (operatorStack.peekFirst() != null if (operatorStack.peekFirst() != null && operatorStack.peekFirst().getType().isNamedGroupOrLookAheadOrLookBehind())
&& operatorStack.peekFirst().getType() == ReTokenType.NAMED_GROUP)
ouputQueue.add(operatorStack.removeFirst()); ouputQueue.add(operatorStack.removeFirst());
} else { } else {
throw new UnsupportedOperationException(token.toString()); throw new UnsupportedOperationException(token.toString());
} }

View File

@ -46,7 +46,7 @@ public class Version {
// Warning, "version" should be the same in gradle.properties and Version.java // Warning, "version" should be the same in gradle.properties and Version.java
// Any idea anyone how to magically synchronize those :-) ? // Any idea anyone how to magically synchronize those :-) ?
private static final String version = "1.2023.14beta1"; private static final String version = "1.2023.14beta2";
public static String versionString() { public static String versionString() {
return version; return version;