2013-12-10 19:36:50 +00:00
|
|
|
/* ========================================================================
|
|
|
|
* PlantUML : a free UML diagram generator
|
|
|
|
* ========================================================================
|
|
|
|
*
|
2019-01-16 18:34:41 +00:00
|
|
|
* (C) Copyright 2009-2020, Arnaud Roques
|
2013-12-10 19:36:50 +00:00
|
|
|
*
|
2016-03-06 16:47:34 +00:00
|
|
|
* Project Info: http://plantuml.com
|
2013-12-10 19:36:50 +00:00
|
|
|
*
|
2017-03-15 19:13:31 +00:00
|
|
|
* If you like this project or if you find it useful, you can support us at:
|
|
|
|
*
|
|
|
|
* http://plantuml.com/patreon (only 1$ per month!)
|
|
|
|
* http://plantuml.com/paypal
|
|
|
|
*
|
2013-12-10 19:36:50 +00:00
|
|
|
* 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.cucadiagram;
|
|
|
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.Arrays;
|
2015-06-20 10:54:49 +00:00
|
|
|
import java.util.Collection;
|
2013-12-10 19:36:50 +00:00
|
|
|
import java.util.Collections;
|
|
|
|
import java.util.Iterator;
|
|
|
|
import java.util.List;
|
|
|
|
|
2017-04-26 17:48:37 +00:00
|
|
|
import net.sourceforge.plantuml.BackSlash;
|
2019-03-01 22:16:29 +00:00
|
|
|
import net.sourceforge.plantuml.EmbeddedDiagram;
|
2019-03-29 22:14:07 +00:00
|
|
|
import net.sourceforge.plantuml.Guillemet;
|
2015-07-11 09:32:49 +00:00
|
|
|
import net.sourceforge.plantuml.ISkinSimple;
|
2017-02-26 16:26:11 +00:00
|
|
|
import net.sourceforge.plantuml.LineBreakStrategy;
|
2015-06-20 10:54:49 +00:00
|
|
|
import net.sourceforge.plantuml.LineLocationImpl;
|
2015-07-11 09:32:49 +00:00
|
|
|
import net.sourceforge.plantuml.SpriteContainer;
|
2019-03-29 22:14:07 +00:00
|
|
|
import net.sourceforge.plantuml.StringLocated;
|
2015-05-31 18:56:03 +00:00
|
|
|
import net.sourceforge.plantuml.StringUtils;
|
2013-12-10 19:36:50 +00:00
|
|
|
import net.sourceforge.plantuml.UrlBuilder;
|
|
|
|
import net.sourceforge.plantuml.UrlBuilder.ModeUrl;
|
2016-05-31 19:41:55 +00:00
|
|
|
import net.sourceforge.plantuml.command.regex.Matcher2;
|
2019-11-03 17:40:03 +00:00
|
|
|
import net.sourceforge.plantuml.command.regex.MyPattern;
|
2016-05-31 19:41:55 +00:00
|
|
|
import net.sourceforge.plantuml.command.regex.Pattern2;
|
2015-07-11 09:32:49 +00:00
|
|
|
import net.sourceforge.plantuml.creole.CreoleMode;
|
|
|
|
import net.sourceforge.plantuml.creole.CreoleParser;
|
|
|
|
import net.sourceforge.plantuml.creole.Sheet;
|
|
|
|
import net.sourceforge.plantuml.creole.SheetBlock1;
|
|
|
|
import net.sourceforge.plantuml.creole.SheetBlock2;
|
|
|
|
import net.sourceforge.plantuml.graphic.CircledCharacter;
|
|
|
|
import net.sourceforge.plantuml.graphic.FontConfiguration;
|
2015-04-07 18:18:37 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.HorizontalAlignment;
|
2015-07-11 09:32:49 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.TextBlock;
|
2016-07-04 19:06:50 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.TextBlockSprited;
|
2015-07-11 09:32:49 +00:00
|
|
|
import net.sourceforge.plantuml.graphic.TextBlockUtils;
|
|
|
|
import net.sourceforge.plantuml.graphic.VerticalAlignment;
|
|
|
|
import net.sourceforge.plantuml.sequencediagram.MessageNumber;
|
2018-10-21 19:44:14 +00:00
|
|
|
import net.sourceforge.plantuml.skin.VisibilityModifier;
|
2020-03-03 22:29:34 +00:00
|
|
|
import net.sourceforge.plantuml.style.PName;
|
2019-08-26 17:07:21 +00:00
|
|
|
import net.sourceforge.plantuml.style.Style;
|
2015-07-11 09:32:49 +00:00
|
|
|
import net.sourceforge.plantuml.ugraphic.UFont;
|
|
|
|
import net.sourceforge.plantuml.ugraphic.UStroke;
|
2020-03-18 10:50:02 +00:00
|
|
|
import net.sourceforge.plantuml.ugraphic.color.HColor;
|
2013-12-10 19:36:50 +00:00
|
|
|
|
|
|
|
public class Display implements Iterable<CharSequence> {
|
|
|
|
|
2019-03-29 22:14:07 +00:00
|
|
|
private final List<CharSequence> displayData;
|
2015-04-07 18:18:37 +00:00
|
|
|
private final HorizontalAlignment naturalHorizontalAlignment;
|
2015-07-11 09:32:49 +00:00
|
|
|
private final boolean isNull;
|
|
|
|
private final CreoleMode defaultCreoleMode;
|
|
|
|
|
|
|
|
public final static Display NULL = new Display(null, null, true, CreoleMode.FULL);
|
2015-04-07 18:18:37 +00:00
|
|
|
|
2020-03-03 22:29:34 +00:00
|
|
|
public Display withoutStereotypeIfNeeded(Style usedStyle) {
|
|
|
|
final boolean showStereotype = usedStyle.value(PName.ShowStereotype).asBoolean();
|
|
|
|
if (showStereotype) {
|
|
|
|
return this;
|
|
|
|
}
|
2019-07-14 20:09:26 +00:00
|
|
|
final List<CharSequence> copy = new ArrayList<CharSequence>(displayData);
|
|
|
|
final Display result = new Display(naturalHorizontalAlignment, isNull, defaultCreoleMode);
|
|
|
|
for (Iterator<CharSequence> it = copy.iterator(); it.hasNext();) {
|
|
|
|
final CharSequence cs = it.next();
|
2019-08-26 17:07:21 +00:00
|
|
|
if (cs instanceof Stereotype && usedStyle.getSignature().match(((Stereotype) cs))) {
|
2019-07-14 20:09:26 +00:00
|
|
|
it.remove();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result.displayData.addAll(copy);
|
|
|
|
return result;
|
2019-03-29 22:14:07 +00:00
|
|
|
}
|
|
|
|
|
2020-03-18 10:50:02 +00:00
|
|
|
public Stereotype getStereotypeIfAny() {
|
|
|
|
for (CharSequence cs : displayData) {
|
|
|
|
if (cs instanceof Stereotype) {
|
|
|
|
return (Stereotype) cs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2018-08-26 12:09:50 +00:00
|
|
|
public Display replaceBackslashT() {
|
|
|
|
final Display result = new Display(this, defaultCreoleMode);
|
2019-03-29 22:14:07 +00:00
|
|
|
for (int i = 0; i < result.displayData.size(); i++) {
|
|
|
|
final CharSequence s = displayData.get(i);
|
2018-08-26 12:09:50 +00:00
|
|
|
if (s.toString().contains("\\t")) {
|
2019-03-29 22:14:07 +00:00
|
|
|
result.displayData.set(i, s.toString().replace("\\t", "\t"));
|
2018-08-26 12:09:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2018-03-09 21:37:34 +00:00
|
|
|
public Display replace(String src, String dest) {
|
|
|
|
final List<CharSequence> newDisplay = new ArrayList<CharSequence>();
|
2019-03-29 22:14:07 +00:00
|
|
|
for (CharSequence cs : displayData) {
|
2018-03-09 21:37:34 +00:00
|
|
|
if (cs.toString().contains(src)) {
|
|
|
|
cs = cs.toString().replace(src, dest);
|
|
|
|
}
|
|
|
|
newDisplay.add(cs);
|
|
|
|
}
|
|
|
|
return new Display(newDisplay, naturalHorizontalAlignment, isNull, defaultCreoleMode);
|
|
|
|
}
|
|
|
|
|
2015-04-07 18:18:37 +00:00
|
|
|
public boolean isWhite() {
|
2019-03-29 22:14:07 +00:00
|
|
|
return displayData == null || displayData.size() == 0
|
|
|
|
|| (displayData.size() == 1 && displayData.get(0).toString().matches("\\s*"));
|
2015-04-07 18:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static Display empty() {
|
2015-07-11 09:32:49 +00:00
|
|
|
return new Display((HorizontalAlignment) null, false, CreoleMode.FULL);
|
2015-04-07 18:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static Display create(CharSequence... s) {
|
|
|
|
return create(Arrays.asList(s));
|
|
|
|
}
|
|
|
|
|
2019-03-29 22:14:07 +00:00
|
|
|
public static Display createFoo(List<StringLocated> data) {
|
|
|
|
final List<CharSequence> tmp = new ArrayList<CharSequence>();
|
|
|
|
for (StringLocated s : data) {
|
|
|
|
tmp.add(s.getString());
|
|
|
|
}
|
|
|
|
return create(tmp);
|
|
|
|
}
|
|
|
|
|
2015-06-20 10:54:49 +00:00
|
|
|
public static Display create(Collection<? extends CharSequence> other) {
|
2015-07-11 09:32:49 +00:00
|
|
|
return new Display(other, null, false, CreoleMode.FULL);
|
2015-04-07 18:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static Display getWithNewlines(Code s) {
|
2019-12-10 21:45:49 +00:00
|
|
|
return getWithNewlines(s.getName());
|
2015-04-07 18:18:37 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public static Display getWithNewlines(String s) {
|
|
|
|
if (s == null) {
|
2015-07-11 09:32:49 +00:00
|
|
|
// Thread.dumpStack();
|
|
|
|
return NULL;
|
2015-04-07 18:18:37 +00:00
|
|
|
}
|
|
|
|
final List<String> result = new ArrayList<String>();
|
|
|
|
final StringBuilder current = new StringBuilder();
|
|
|
|
HorizontalAlignment naturalHorizontalAlignment = null;
|
2017-06-05 11:27:21 +00:00
|
|
|
boolean rawMode = false;
|
2015-04-07 18:18:37 +00:00
|
|
|
for (int i = 0; i < s.length(); i++) {
|
|
|
|
final char c = s.charAt(i);
|
2017-04-05 17:37:42 +00:00
|
|
|
final String sub = s.substring(i);
|
2017-06-05 11:27:21 +00:00
|
|
|
if (sub.startsWith("<math>") || sub.startsWith("<latex>") || sub.startsWith("[[")) {
|
|
|
|
rawMode = true;
|
|
|
|
} else if (sub.startsWith("</math>") || sub.startsWith("</latex>") || sub.startsWith("]]")) {
|
|
|
|
rawMode = false;
|
2017-04-05 17:37:42 +00:00
|
|
|
}
|
2017-06-05 11:27:21 +00:00
|
|
|
if (rawMode == false && c == '\\' && i < s.length() - 1) {
|
2015-04-07 18:18:37 +00:00
|
|
|
final char c2 = s.charAt(i + 1);
|
|
|
|
i++;
|
|
|
|
if (c2 == 'n' || c2 == 'r' || c2 == 'l') {
|
|
|
|
if (c2 == 'r') {
|
|
|
|
naturalHorizontalAlignment = HorizontalAlignment.RIGHT;
|
|
|
|
} else if (c2 == 'l') {
|
|
|
|
naturalHorizontalAlignment = HorizontalAlignment.LEFT;
|
|
|
|
}
|
|
|
|
result.add(current.toString());
|
|
|
|
current.setLength(0);
|
|
|
|
} else if (c2 == 't') {
|
|
|
|
current.append('\t');
|
|
|
|
} else if (c2 == '\\') {
|
|
|
|
current.append(c2);
|
|
|
|
} else {
|
|
|
|
current.append(c);
|
|
|
|
current.append(c2);
|
|
|
|
}
|
2017-04-26 17:48:37 +00:00
|
|
|
} else if (c == BackSlash.hiddenNewLine()) {
|
2015-05-31 18:56:03 +00:00
|
|
|
result.add(current.toString());
|
|
|
|
current.setLength(0);
|
2015-04-07 18:18:37 +00:00
|
|
|
} else {
|
|
|
|
current.append(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
result.add(current.toString());
|
2015-07-11 09:32:49 +00:00
|
|
|
return new Display(result, naturalHorizontalAlignment, false, CreoleMode.FULL);
|
2015-04-07 18:18:37 +00:00
|
|
|
}
|
2013-12-10 19:36:50 +00:00
|
|
|
|
2015-07-11 09:32:49 +00:00
|
|
|
private Display(Display other, CreoleMode mode) {
|
|
|
|
this(other.naturalHorizontalAlignment, other.isNull, mode);
|
2019-03-29 22:14:07 +00:00
|
|
|
this.displayData.addAll(other.displayData);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2015-07-11 09:32:49 +00:00
|
|
|
private Display(HorizontalAlignment naturalHorizontalAlignment, boolean isNull, CreoleMode defaultCreoleMode) {
|
|
|
|
this.defaultCreoleMode = defaultCreoleMode;
|
|
|
|
this.isNull = isNull;
|
2019-03-29 22:14:07 +00:00
|
|
|
this.displayData = isNull ? null : new ArrayList<CharSequence>();
|
2015-07-11 09:32:49 +00:00
|
|
|
this.naturalHorizontalAlignment = isNull ? null : naturalHorizontalAlignment;
|
2015-04-07 18:18:37 +00:00
|
|
|
}
|
|
|
|
|
2015-07-11 09:32:49 +00:00
|
|
|
private Display(Collection<? extends CharSequence> other, HorizontalAlignment naturalHorizontalAlignment,
|
|
|
|
boolean isNull, CreoleMode defaultCreoleMode) {
|
|
|
|
this(naturalHorizontalAlignment, isNull, defaultCreoleMode);
|
|
|
|
if (isNull == false) {
|
2019-03-29 22:14:07 +00:00
|
|
|
this.displayData.addAll(manageEmbeddedDiagrams(other));
|
2015-07-11 09:32:49 +00:00
|
|
|
}
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2019-03-01 22:16:29 +00:00
|
|
|
private static List<CharSequence> manageEmbeddedDiagrams(final Collection<? extends CharSequence> strings) {
|
2015-04-07 18:18:37 +00:00
|
|
|
final List<CharSequence> result = new ArrayList<CharSequence>();
|
|
|
|
final Iterator<? extends CharSequence> it = strings.iterator();
|
|
|
|
while (it.hasNext()) {
|
|
|
|
CharSequence s = it.next();
|
2015-05-31 18:56:03 +00:00
|
|
|
if (s != null && StringUtils.trin(s.toString()).equals("{{")) {
|
2015-04-07 18:18:37 +00:00
|
|
|
final List<CharSequence> other = new ArrayList<CharSequence>();
|
|
|
|
other.add("@startuml");
|
|
|
|
while (it.hasNext()) {
|
2019-03-29 22:14:07 +00:00
|
|
|
CharSequence s2 = it.next();
|
2015-05-31 18:56:03 +00:00
|
|
|
if (s2 != null && StringUtils.trin(s2.toString()).equals("}}")) {
|
2015-04-07 18:18:37 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
other.add(s2);
|
|
|
|
}
|
|
|
|
other.add("@enduml");
|
2019-03-01 22:16:29 +00:00
|
|
|
s = new EmbeddedDiagram(Display.create(other));
|
2015-04-07 18:18:37 +00:00
|
|
|
}
|
|
|
|
result.add(s);
|
|
|
|
}
|
|
|
|
return result;
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2016-11-04 21:39:29 +00:00
|
|
|
public Display manageGuillemet() {
|
|
|
|
final List<CharSequence> result = new ArrayList<CharSequence>();
|
2018-10-21 19:44:14 +00:00
|
|
|
boolean first = true;
|
2019-03-29 22:14:07 +00:00
|
|
|
for (CharSequence line : displayData) {
|
2019-04-21 20:40:01 +00:00
|
|
|
if (line instanceof EmbeddedDiagram) {
|
|
|
|
result.add(line);
|
|
|
|
} else {
|
|
|
|
String lineString = line.toString();
|
|
|
|
if (first && VisibilityModifier.isVisibilityCharacter(line)) {
|
|
|
|
lineString = lineString.substring(1).trim();
|
|
|
|
}
|
|
|
|
final String withGuillement = Guillemet.GUILLEMET.manageGuillemet(lineString);
|
|
|
|
result.add(withGuillement);
|
2016-11-04 21:39:29 +00:00
|
|
|
}
|
2018-10-21 19:44:14 +00:00
|
|
|
first = false;
|
2016-11-04 21:39:29 +00:00
|
|
|
}
|
|
|
|
return new Display(result, this.naturalHorizontalAlignment, this.isNull, this.defaultCreoleMode);
|
|
|
|
}
|
|
|
|
|
2017-11-20 16:10:36 +00:00
|
|
|
public Display withPage(int page, int lastpage) {
|
2019-03-29 22:14:07 +00:00
|
|
|
if (displayData == null) {
|
2017-11-20 16:10:36 +00:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
final List<CharSequence> result = new ArrayList<CharSequence>();
|
2019-03-29 22:14:07 +00:00
|
|
|
for (CharSequence line : displayData) {
|
2017-11-20 16:10:36 +00:00
|
|
|
line = line.toString().replace("%page%", "" + page);
|
|
|
|
line = line.toString().replace("%lastpage%", "" + lastpage);
|
|
|
|
result.add(line);
|
|
|
|
}
|
|
|
|
return new Display(result, this.naturalHorizontalAlignment, this.isNull, this.defaultCreoleMode);
|
|
|
|
}
|
|
|
|
|
2019-11-03 17:40:03 +00:00
|
|
|
public Display removeEndingStereotype() {
|
|
|
|
final Matcher2 m = patternStereotype.matcher(displayData.get(displayData.size() - 1));
|
|
|
|
if (m.matches()) {
|
|
|
|
final List<CharSequence> result = new ArrayList<CharSequence>(this.displayData);
|
|
|
|
result.set(result.size() - 1, m.group(1));
|
|
|
|
return new Display(result, this.naturalHorizontalAlignment, this.isNull, this.defaultCreoleMode);
|
|
|
|
}
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
public final static Pattern2 patternStereotype = MyPattern.cmpile("^(.*?)(?:\\<\\<\\s*(.*)\\s*\\>\\>)\\s*$");
|
|
|
|
|
|
|
|
public String getEndingStereotype() {
|
|
|
|
final Matcher2 m = patternStereotype.matcher(displayData.get(displayData.size() - 1));
|
|
|
|
if (m.matches()) {
|
|
|
|
return m.group(2);
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
public Display underlined() {
|
|
|
|
final List<CharSequence> result = new ArrayList<CharSequence>();
|
2019-03-29 22:14:07 +00:00
|
|
|
for (CharSequence line : displayData) {
|
2013-12-10 19:36:50 +00:00
|
|
|
result.add("<u>" + line);
|
|
|
|
}
|
2015-07-11 09:32:49 +00:00
|
|
|
return new Display(result, this.naturalHorizontalAlignment, this.isNull, this.defaultCreoleMode);
|
|
|
|
}
|
|
|
|
|
|
|
|
public Display withCreoleMode(CreoleMode mode) {
|
|
|
|
if (isNull) {
|
|
|
|
throw new IllegalArgumentException();
|
|
|
|
}
|
|
|
|
return new Display(this, mode);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String toString() {
|
2015-07-11 09:32:49 +00:00
|
|
|
if (isNull) {
|
|
|
|
return "NULL";
|
|
|
|
}
|
2019-03-29 22:14:07 +00:00
|
|
|
return displayData.toString();
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public int hashCode() {
|
2019-03-29 22:14:07 +00:00
|
|
|
return displayData.hashCode();
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean equals(Object other) {
|
2019-03-29 22:14:07 +00:00
|
|
|
return this.displayData.equals(((Display) other).displayData);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public Display addAll(Display other) {
|
2015-07-11 09:32:49 +00:00
|
|
|
final Display result = new Display(this, this.defaultCreoleMode);
|
2019-03-29 22:14:07 +00:00
|
|
|
result.displayData.addAll(other.displayData);
|
2013-12-10 19:36:50 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Display addFirst(CharSequence s) {
|
2015-07-11 09:32:49 +00:00
|
|
|
final Display result = new Display(this, this.defaultCreoleMode);
|
2019-03-29 22:14:07 +00:00
|
|
|
result.displayData.add(0, s);
|
2013-12-10 19:36:50 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
public Display add(CharSequence s) {
|
2015-07-11 09:32:49 +00:00
|
|
|
final Display result = new Display(this, this.defaultCreoleMode);
|
2019-03-29 22:14:07 +00:00
|
|
|
result.displayData.add(s);
|
2013-12-10 19:36:50 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2017-09-03 16:59:24 +00:00
|
|
|
public Display addGeneric(CharSequence s) {
|
|
|
|
final Display result = new Display(this, this.defaultCreoleMode);
|
2019-03-29 22:14:07 +00:00
|
|
|
final int size = displayData.size();
|
2017-09-03 16:59:24 +00:00
|
|
|
if (size == 0) {
|
2019-03-29 22:14:07 +00:00
|
|
|
result.displayData.add("<" + s + ">");
|
2017-09-03 16:59:24 +00:00
|
|
|
} else {
|
2019-03-29 22:14:07 +00:00
|
|
|
result.displayData.set(size - 1, displayData.get(size - 1) + "<" + s + ">");
|
2017-09-03 16:59:24 +00:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
public int size() {
|
2015-07-11 09:32:49 +00:00
|
|
|
if (isNull) {
|
|
|
|
return 0;
|
|
|
|
}
|
2019-03-29 22:14:07 +00:00
|
|
|
return displayData.size();
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public CharSequence get(int i) {
|
2019-03-29 22:14:07 +00:00
|
|
|
return displayData.get(i);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public Iterator<CharSequence> iterator() {
|
2019-03-29 22:14:07 +00:00
|
|
|
return Collections.unmodifiableList(displayData).iterator();
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public Display subList(int i, int size) {
|
2019-03-29 22:14:07 +00:00
|
|
|
return new Display(displayData.subList(i, size), this.naturalHorizontalAlignment, this.isNull,
|
2015-07-11 09:32:49 +00:00
|
|
|
this.defaultCreoleMode);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public List<? extends CharSequence> as() {
|
2019-03-29 22:14:07 +00:00
|
|
|
return Collections.unmodifiableList(displayData);
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|
|
|
|
|
2019-03-29 22:14:07 +00:00
|
|
|
public List<StringLocated> as2() {
|
|
|
|
final List<StringLocated> result = new ArrayList<StringLocated>();
|
2015-06-20 10:54:49 +00:00
|
|
|
LineLocationImpl location = new LineLocationImpl("inner", null);
|
2019-03-29 22:14:07 +00:00
|
|
|
for (CharSequence cs : displayData) {
|
2015-06-20 10:54:49 +00:00
|
|
|
location = location.oneLineRead();
|
2019-03-29 22:14:07 +00:00
|
|
|
result.add(new StringLocated(cs.toString(), location));
|
2015-06-20 10:54:49 +00:00
|
|
|
}
|
|
|
|
return Collections.unmodifiableList(result);
|
|
|
|
}
|
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
public boolean hasUrl() {
|
|
|
|
final UrlBuilder urlBuilder = new UrlBuilder(null, ModeUrl.ANYWHERE);
|
|
|
|
for (CharSequence s : this) {
|
|
|
|
if (urlBuilder.getUrl(s.toString()) != null) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2015-04-07 18:18:37 +00:00
|
|
|
public HorizontalAlignment getNaturalHorizontalAlignment() {
|
|
|
|
return naturalHorizontalAlignment;
|
|
|
|
}
|
|
|
|
|
2016-05-31 19:41:55 +00:00
|
|
|
public List<Display> splitMultiline(Pattern2 separator) {
|
2015-05-31 18:56:03 +00:00
|
|
|
final List<Display> result = new ArrayList<Display>();
|
2015-07-11 09:32:49 +00:00
|
|
|
Display pending = new Display(this.naturalHorizontalAlignment, this.isNull, this.defaultCreoleMode);
|
2015-05-31 18:56:03 +00:00
|
|
|
result.add(pending);
|
2019-03-29 22:14:07 +00:00
|
|
|
for (CharSequence line : displayData) {
|
2016-05-31 19:41:55 +00:00
|
|
|
final Matcher2 m = separator.matcher(line);
|
2015-05-31 18:56:03 +00:00
|
|
|
if (m.find()) {
|
|
|
|
final CharSequence s1 = line.subSequence(0, m.start());
|
2019-03-29 22:14:07 +00:00
|
|
|
pending.displayData.add(s1);
|
2015-05-31 18:56:03 +00:00
|
|
|
final CharSequence s2 = line.subSequence(m.end(), line.length());
|
2015-07-11 09:32:49 +00:00
|
|
|
pending = new Display(this.naturalHorizontalAlignment, this.isNull, this.defaultCreoleMode);
|
2015-05-31 18:56:03 +00:00
|
|
|
result.add(pending);
|
2019-03-29 22:14:07 +00:00
|
|
|
pending.displayData.add(s2);
|
2015-05-31 18:56:03 +00:00
|
|
|
} else {
|
2019-03-29 22:14:07 +00:00
|
|
|
pending.displayData.add(line);
|
2015-05-31 18:56:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return Collections.unmodifiableList(result);
|
|
|
|
}
|
|
|
|
|
2015-07-11 09:32:49 +00:00
|
|
|
// ------
|
|
|
|
|
|
|
|
public static boolean isNull(Display display) {
|
2016-01-09 12:15:40 +00:00
|
|
|
// if (display == null) {
|
|
|
|
// throw new IllegalArgumentException();
|
|
|
|
// }
|
2015-07-11 09:32:49 +00:00
|
|
|
return display == null || display.isNull;
|
|
|
|
}
|
|
|
|
|
|
|
|
public TextBlock create(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,
|
|
|
|
ISkinSimple spriteContainer) {
|
2020-04-05 15:13:04 +00:00
|
|
|
return create7(fontConfiguration, horizontalAlignment, spriteContainer, CreoleMode.FULL);
|
2015-07-11 09:32:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public TextBlock createWithNiceCreoleMode(FontConfiguration fontConfiguration,
|
|
|
|
HorizontalAlignment horizontalAlignment, ISkinSimple spriteContainer) {
|
2020-04-05 15:13:04 +00:00
|
|
|
return create7(fontConfiguration, horizontalAlignment, spriteContainer, defaultCreoleMode);
|
2015-07-11 09:32:49 +00:00
|
|
|
}
|
|
|
|
|
2020-04-05 15:13:04 +00:00
|
|
|
public TextBlock create7(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,
|
2019-05-24 19:59:31 +00:00
|
|
|
ISkinSimple spriteContainer, CreoleMode creoleMode) {
|
2020-04-05 15:13:04 +00:00
|
|
|
return create0(fontConfiguration, horizontalAlignment, spriteContainer, LineBreakStrategy.NONE, creoleMode,
|
|
|
|
null, null);
|
2015-07-11 09:32:49 +00:00
|
|
|
}
|
|
|
|
|
2020-04-05 15:13:04 +00:00
|
|
|
public TextBlock create8(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,
|
2018-03-09 21:37:34 +00:00
|
|
|
ISkinSimple spriteContainer, CreoleMode modeSimpleLine, LineBreakStrategy maxMessageSize) {
|
2020-04-05 15:13:04 +00:00
|
|
|
return create0(fontConfiguration, horizontalAlignment, spriteContainer, maxMessageSize, modeSimpleLine, null,
|
2018-07-27 21:56:46 +00:00
|
|
|
null);
|
2018-03-09 21:37:34 +00:00
|
|
|
}
|
|
|
|
|
2020-04-05 15:13:04 +00:00
|
|
|
public TextBlock create9(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,
|
2017-02-26 16:26:11 +00:00
|
|
|
ISkinSimple spriteContainer, LineBreakStrategy maxMessageSize) {
|
2020-04-05 15:13:04 +00:00
|
|
|
return create0(fontConfiguration, horizontalAlignment, spriteContainer, maxMessageSize, defaultCreoleMode, null,
|
2017-02-26 16:26:11 +00:00
|
|
|
null);
|
|
|
|
}
|
|
|
|
|
2020-04-05 15:13:04 +00:00
|
|
|
public TextBlock create0(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,
|
2019-05-24 19:59:31 +00:00
|
|
|
ISkinSimple spriteContainer, LineBreakStrategy maxMessageSize, CreoleMode creoleMode,
|
2020-03-18 10:50:02 +00:00
|
|
|
UFont fontForStereotype, HColor htmlColorForStereotype) {
|
2017-02-26 16:26:11 +00:00
|
|
|
if (maxMessageSize == null) {
|
|
|
|
throw new IllegalArgumentException();
|
|
|
|
}
|
2015-07-11 09:32:49 +00:00
|
|
|
if (getNaturalHorizontalAlignment() != null) {
|
|
|
|
horizontalAlignment = getNaturalHorizontalAlignment();
|
|
|
|
}
|
2020-01-12 22:13:17 +00:00
|
|
|
final FontConfiguration stereotypeConfiguration = fontConfiguration.forceFont(fontForStereotype,
|
|
|
|
htmlColorForStereotype);
|
2015-07-11 09:32:49 +00:00
|
|
|
if (size() > 0) {
|
|
|
|
if (get(0) instanceof Stereotype) {
|
|
|
|
return createStereotype(fontConfiguration, horizontalAlignment, spriteContainer, 0, fontForStereotype,
|
2020-01-12 22:13:17 +00:00
|
|
|
htmlColorForStereotype, maxMessageSize, creoleMode);
|
2015-07-11 09:32:49 +00:00
|
|
|
}
|
|
|
|
if (get(size() - 1) instanceof Stereotype) {
|
|
|
|
return createStereotype(fontConfiguration, horizontalAlignment, spriteContainer, size() - 1,
|
2020-01-12 22:13:17 +00:00
|
|
|
fontForStereotype, htmlColorForStereotype, maxMessageSize, creoleMode);
|
2015-07-11 09:32:49 +00:00
|
|
|
}
|
|
|
|
if (get(0) instanceof MessageNumber) {
|
2020-01-12 22:13:17 +00:00
|
|
|
return createMessageNumber(fontConfiguration, horizontalAlignment, spriteContainer, maxMessageSize,
|
|
|
|
stereotypeConfiguration);
|
2015-07-11 09:32:49 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-12 22:13:17 +00:00
|
|
|
return getCreole(fontConfiguration, horizontalAlignment, spriteContainer, maxMessageSize, creoleMode,
|
|
|
|
stereotypeConfiguration);
|
|
|
|
}
|
|
|
|
|
|
|
|
private TextBlock createStereotype(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,
|
2020-03-18 10:50:02 +00:00
|
|
|
SpriteContainer spriteContainer, int position, UFont fontForStereotype, HColor htmlColorForStereotype,
|
2020-01-12 22:13:17 +00:00
|
|
|
LineBreakStrategy maxMessageSize, CreoleMode creoleMode) {
|
|
|
|
final Stereotype stereotype = (Stereotype) get(position);
|
|
|
|
TextBlock circledCharacter = null;
|
|
|
|
if (stereotype.isSpotted()) {
|
|
|
|
circledCharacter = new CircledCharacter(stereotype.getCharacter(), stereotype.getRadius(),
|
|
|
|
stereotype.getCircledFont(), stereotype.getHtmlColor(), null, fontConfiguration.getColor());
|
|
|
|
} else {
|
|
|
|
circledCharacter = stereotype.getSprite(spriteContainer);
|
|
|
|
}
|
|
|
|
final FontConfiguration stereotypeConfiguration = fontConfiguration.forceFont(fontForStereotype,
|
|
|
|
htmlColorForStereotype);
|
|
|
|
final TextBlock result = getCreole(fontConfiguration, horizontalAlignment, (ISkinSimple) spriteContainer,
|
|
|
|
maxMessageSize, creoleMode, stereotypeConfiguration);
|
|
|
|
if (circledCharacter != null) {
|
|
|
|
return new TextBlockSprited(circledCharacter, result);
|
|
|
|
}
|
|
|
|
return result;
|
2015-07-11 09:32:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private TextBlock getCreole(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,
|
2020-01-12 22:13:17 +00:00
|
|
|
ISkinSimple spriteContainer, LineBreakStrategy maxMessageSize, CreoleMode creoleMode,
|
|
|
|
FontConfiguration stereotypeConfiguration) {
|
|
|
|
final Sheet sheet = new CreoleParser(fontConfiguration, horizontalAlignment, spriteContainer, creoleMode,
|
|
|
|
stereotypeConfiguration).createSheet(this);
|
2020-04-05 15:13:04 +00:00
|
|
|
final double padding = spriteContainer == null ? 0 : spriteContainer.getPadding();
|
|
|
|
final SheetBlock1 sheetBlock1 = new SheetBlock1(sheet, maxMessageSize, padding);
|
2015-07-11 09:32:49 +00:00
|
|
|
return new SheetBlock2(sheetBlock1, sheetBlock1, new UStroke(1.5));
|
|
|
|
}
|
|
|
|
|
|
|
|
private TextBlock createMessageNumber(FontConfiguration fontConfiguration, HorizontalAlignment horizontalAlignment,
|
2020-01-12 22:13:17 +00:00
|
|
|
ISkinSimple spriteContainer, LineBreakStrategy maxMessageSize, FontConfiguration stereotypeConfiguration) {
|
2020-03-03 22:29:34 +00:00
|
|
|
TextBlock tb1 = subList(0, 1).getCreole(fontConfiguration, horizontalAlignment, spriteContainer, maxMessageSize,
|
|
|
|
CreoleMode.FULL, stereotypeConfiguration);
|
2015-07-11 09:32:49 +00:00
|
|
|
tb1 = TextBlockUtils.withMargin(tb1, 0, 4, 0, 0);
|
|
|
|
final TextBlock tb2 = subList(1, size()).getCreole(fontConfiguration, horizontalAlignment, spriteContainer,
|
2020-01-12 22:13:17 +00:00
|
|
|
maxMessageSize, CreoleMode.FULL, stereotypeConfiguration);
|
2015-07-11 09:32:49 +00:00
|
|
|
return TextBlockUtils.mergeLR(tb1, tb2, VerticalAlignment.CENTER);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2013-12-10 19:36:50 +00:00
|
|
|
}
|