-
Notifications
You must be signed in to change notification settings - Fork 96
/
TextPainterHelper.java
238 lines (204 loc) · 7.47 KB
/
TextPainterHelper.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
package org.eclipse.nebula.widgets.ganttchart.utils;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.nebula.widgets.ganttchart.ColorCache;
import org.eclipse.nebula.widgets.ganttchart.Utils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
/**
* Helper class to draw texts with markups within the GanttChart.
* Currently used for rendering tooltips and section details.
* Following markups are supported:
* <ul>
* <li>\\ce - render the following text in black</li>
* <li>\\c[0-9]{9} - render the following text in the specified rbg color (Note that there need to be nine digits)</li>
* <li>\\s[0-9]{1,3} - render the following text with the specified font size</li>
* <li>\\i - render the following text italic</li>
* <li>\\b - render the following text bold</li>
* <li>\\x - normalize, which means to reset the previous assigned markups and render with the default font and color</li>
* </ul>
*/
@SuppressWarnings("nls")
public class TextPainterHelper {
/**
* Will draw the given text to the given GC. Before drawing the containing
* markups will be interpreted to apply color and font settings.
* @param gc The GC to draw the text to
* @param text The text to draw
* @param x The x coordinate where the text should be drawed to the GC
* @param y The y coordinate where the text should be drawed to the GC
* @return The end point of the drawed text.
*/
public static Point drawText(final GC gc, final String text, final int x, final int y) {
Pattern pattern = Pattern.compile("(\\\\(ce|c[0-9]{9}|s[0-9]{1,3}|[xbi]))*[^\\\\]*");
try {
final Font old = gc.getFont();
final int oldSize = (int) old.getFontData()[0].height;
int curX = x;
boolean bold = false;
boolean italic = false;
int size = oldSize;
Color fg = ColorCache.getBlack();
int maxWidth = 0;
int maxHeight = 0;
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
String token = matcher.group();
if (isNormalize(token)) {
bold = false;
italic = false;
size = oldSize;
fg = ColorCache.getBlack();
}
else {
final int newSize = getSize(token);
if (newSize != size && newSize != -1) {
size = newSize;
}
final boolean newBold = isBold(token);
if (bold && !newBold) {
bold = true;
}
else {
bold = newBold;
}
final boolean newItalic = isItalic(token);
if (italic && !newItalic) {
italic = true;
}
else {
italic = newItalic;
}
final Color newColor = getColor(token);
if (newColor != null && !newColor.equals(fg)) {
fg = newColor;
}
}
if (fg != null) {
gc.setForeground(fg);
}
token = cleanUp(token);
int style = SWT.NORMAL;
if (bold) {
style |= SWT.BOLD;
}
if (italic) {
style |= SWT.ITALIC;
}
Font used = Utils.applyFontData(old, style, size);
gc.setFont(used);
if (token.length() != 0) {
gc.drawText(token, curX, y, true);
final int extX = gc.textExtent(token).x;
final int extY = gc.textExtent(token).y;
curX += extX;
maxWidth = Math.max(maxWidth, curX);
maxHeight = Math.max(maxHeight, extY);
}
used.dispose();
}
gc.setFont(old);
return new Point(maxWidth - x, maxHeight);
}
catch (Exception err) {
SWT.error(SWT.ERROR_UNSPECIFIED, err);
}
return null;
}
/**
* Removes all markups out of the given string. Needed to render
* after all markups have been resolved.
* @param string The string whose markups should be removed.
* @return The given string without any further markups.
*/
public static String cleanUp(final String string) {
String str = string;
str = str.replaceAll("\\\\ce", "");
str = str.replaceAll("\\\\c[0-9]{9}", "");
str = str.replaceAll("\\\\s[0-9]{1,3}", "");
str = str.replaceAll("\\\\x", "");
str = str.replaceAll("\\\\b", "");
str = str.replaceAll("\\\\i", "");
return str;
}
/**
* Checks for the existence of the normalize markup.
* The normalize markup can be used to reset all former assigned
* markups for the following text to render.
* The normalize markup is \\x
* @param str The string to check for the normalize markup
* @return <code>true</code> if the given string contains the
* normalize markup
*/
public static boolean isNormalize(final String str) {
return str.indexOf("\\x") > -1;
}
/**
* Checks for the existence of the bold markup.
* The bold markup is \\b
* @param str The string to check for the bold markup
* @return <code>true</code> if the given string contains the
* bold markup
*/
public static boolean isBold(final String str) {
return str.indexOf("\\b") > -1;
}
/**
* Checks for the existence of the italic markup.
* The italic markup is \\i
* @param str The string to check for the italic markup
* @return <code>true</code> if the given string contains the
* italic markup
*/
public static boolean isItalic(final String str) {
return str.indexOf("\\i") > -1;
}
/**
* Gets the font size out of a size markup in the given string.
* A size markup is specified \\s[0-9]{1,3}
* @param str The string containing the size markup
* @return The font size to use for rendering
*/
public static int getSize(final String str) {
Pattern pattern = Pattern.compile("\\\\s[0-9]{1,3}");
Matcher matcher = pattern.matcher(str);
if (matcher.find()) {
String sizeString = matcher.group();
sizeString = sizeString.substring(2);
try {
return Integer.parseInt(sizeString);
} catch (Exception badParse) {
SWT.error(SWT.ERROR_UNSPECIFIED, badParse);
}
}
return -1;
}
/**
* Gets the color for a color markup in the given string.
* A color markup is either \\ce for black or \\c[0-9]{9}
* to specify a custom color by rgb code
* @param str The string containing a color markup
* @return The Color that is specified by the color markup
*/
public static Color getColor(final String str) {
final int start = str.indexOf("\\c");
if (start == -1) {
return null;
}
if (str.indexOf("\\ce") != -1) {
return ColorCache.getBlack();
}
try {
final int red = Integer.parseInt(str.substring(start + 2, start + 5));
final int green = Integer.parseInt(str.substring(start + 5, start + 8));
final int blue = Integer.parseInt(str.substring(start + 8, start + 11));
return ColorCache.getColor(red, green, blue);
} catch (Exception err) {
SWT.error(SWT.ERROR_UNSPECIFIED, err);
}
return ColorCache.getBlack();
}
}