Merge lp:~tapaal-contributor/tapaal/cpn-gui-TikZ-support into lp:~tapaal-contributor/tapaal/cpn-gui-dev
- cpn-gui-TikZ-support
- Merge into cpn-gui-dev
Status: | Superseded |
---|---|
Proposed branch: | lp:~tapaal-contributor/tapaal/cpn-gui-TikZ-support |
Merge into: | lp:~tapaal-contributor/tapaal/cpn-gui-dev |
Diff against target: |
461 lines (+199/-136) 1 file modified
src/net/tapaal/export/TikZExporter.java (+199/-136) |
To merge this branch: | bzr merge lp:~tapaal-contributor/tapaal/cpn-gui-TikZ-support |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Jiri Srba | Needs Fixing | ||
Kenneth Yrke Jørgensen | code | Pending | |
Review via email: mp+415854@code.launchpad.net |
This proposal supersedes a proposal from 2022-02-17.
This proposal has been superseded by a proposal from 2022-03-06.
Commit message
Added TikZ support for colored nets.
Added a framed box to the Tikz output for global variables/
Removed subscripiting from transition- and place names
Changed \mathrm to \mathit
Added more adjustment options for transitions, places and arcs
Merged with cpn-gui-dev
Description of the change
The TikZ export now shows all of the new features associated with colored nets.
Also added a framed box that contains all the global variables, constants and/or color types for a given net.
Subscripting from transition- and place names have been removed, so it looks more like the GUI.
\mathrm has also been replaces with \mathit.
Kenneth Yrke Jørgensen (yrke) : Posted in a previous version of this proposal | # |
Jiri Srba (srba) wrote : Posted in a previous version of this proposal | # |
Jiri Srba (srba) wrote : | # |
Please, set the default position for arc lables to pos=0.5
- 1576. By Kristian Morsing Pedersen <email address hidden>
-
Changed default pos of arc labels to 0.5
- 1577. By Kristian Morsing Pedersen <email address hidden>
-
Resolved merge conflicts
- 1578. By Kristian Morsing Pedersen <email address hidden>
-
Removed redundant \\ and changed 0,0 -> 0.0 for age of tokens in initial markings
- 1579. By Kristian Morsing Pedersen <email address hidden>
-
Changed x -> \times in inhibitor arcs
Unmerged revisions
Preview Diff
1 | === modified file 'src/net/tapaal/export/TikZExporter.java' |
2 | --- src/net/tapaal/export/TikZExporter.java 2022-02-21 19:46:59 +0000 |
3 | +++ src/net/tapaal/export/TikZExporter.java 2022-03-06 10:50:31 +0000 |
4 | @@ -3,16 +3,17 @@ |
5 | import java.io.FileWriter; |
6 | import java.io.IOException; |
7 | import java.io.PrintWriter; |
8 | -import java.util.List; |
9 | +import java.util.*; |
10 | |
11 | +import dk.aau.cs.model.CPN.ColorType; |
12 | +import dk.aau.cs.model.CPN.Variable; |
13 | +import dk.aau.cs.model.tapn.Constant; |
14 | import dk.aau.cs.model.tapn.TimedToken; |
15 | |
16 | +import net.tapaal.gui.petrinet.Context; |
17 | import pipe.gui.petrinet.dataLayer.DataLayer; |
18 | import pipe.gui.TAPAALGUI; |
19 | -import pipe.gui.petrinet.graphicElements.Arc; |
20 | -import pipe.gui.petrinet.graphicElements.ArcPathPoint; |
21 | -import pipe.gui.petrinet.graphicElements.Place; |
22 | -import pipe.gui.petrinet.graphicElements.Transition; |
23 | +import pipe.gui.petrinet.graphicElements.*; |
24 | import pipe.gui.petrinet.graphicElements.tapn.TimedInhibitorArcComponent; |
25 | import pipe.gui.petrinet.graphicElements.tapn.TimedInputArcComponent; |
26 | import pipe.gui.petrinet.graphicElements.tapn.TimedPlaceComponent; |
27 | @@ -45,7 +46,7 @@ |
28 | if (option == TikZOutputOption.FULL_LATEX) { |
29 | out.println("\\documentclass[a4paper]{article}"); |
30 | out.println("\\usepackage{tikz}"); |
31 | - out.println("\\usetikzlibrary{petri,arrows}"); |
32 | + out.println("\\usetikzlibrary{petri,arrows,positioning}"); |
33 | out.println("\\usepackage{amstext}"); |
34 | out.println(); |
35 | out.println("\\begin{document}"); |
36 | @@ -62,6 +63,8 @@ |
37 | out.print(exportTransitions(net.getTransitions())); |
38 | out.print(exportArcs(net.getArcs())); |
39 | |
40 | + out.println(exportGlobalVariables()); |
41 | + |
42 | out.println("\\end{tikzpicture}"); |
43 | if (option == TikZOutputOption.FULL_LATEX) { |
44 | out.println("\\end{document}"); |
45 | @@ -94,7 +97,7 @@ |
46 | ArcPathPoint currentPoint = arc.getArcPath().getArcPathPoint(i); |
47 | |
48 | if(currentPoint.getPointType() == ArcPathPoint.STRAIGHT) { |
49 | - arcPoints += "to[bend right=0] (" + (currentPoint.getX()) + "," + (currentPoint.getY() * (-1)) + ") "; |
50 | + arcPoints += "to [bend right=0] (" + (currentPoint.getX()) + "," + (currentPoint.getY() * (-1)) + ") "; |
51 | } else if (currentPoint.getPointType() == ArcPathPoint.CURVED) { |
52 | double xCtrl1 = Math.round(currentPoint.getControl1().getX()); |
53 | double yCtrl1 = Math.round(currentPoint.getControl1().getY() * (-1)); |
54 | @@ -109,21 +112,19 @@ |
55 | } |
56 | |
57 | String arrowType = getArcArrowType(arc); |
58 | - String arcLabel = getArcLabels(arc); |
59 | |
60 | + out.append("% Arc between " + arc.getSource().getName() + " and " + arc.getTarget().getName() + "\n"); |
61 | out.append("\\draw["); |
62 | out.append(arrowType); |
63 | - out.append("] ("); |
64 | + out.append(",pos=0.5] ("); |
65 | out.append(arc.getSource().getId()); |
66 | out.append(") "); |
67 | out.append(arcPoints); |
68 | - out.append("to[bend right=0]"); |
69 | - out.append(" ("); |
70 | - out.append(arc.getTarget().getId()); |
71 | - out.append(") {};\n"); |
72 | - if(!arcLabel.equals("")) |
73 | - out.append("%% Label for arc between " + arc.getSource().getName() + " and " + arc.getTarget().getName() + "\n"); |
74 | - out.append(arcLabel); |
75 | + out.append("to node[bend right=0,auto,align=left]"); |
76 | + out.append(" {"); |
77 | + out.append(handleNameLabel(arc.getNameLabel().getText())); |
78 | + out.append("} "); |
79 | + out.append("(" + arc.getTarget().getId() + ");\n"); |
80 | } |
81 | return out; |
82 | } |
83 | @@ -142,50 +143,6 @@ |
84 | return arrowType; |
85 | } |
86 | |
87 | - protected String getArcLabels(Arc arc) { |
88 | - String arcLabel = ""; |
89 | - String arcLabelPositionString = "\\draw (" + (arc.getNameLabel().getX()) + "," + (arc.getNameLabel().getY())*(-1) + ") node {"; |
90 | - |
91 | - if (arc instanceof TimedInputArcComponent) { |
92 | - if (!(arc.getSource() instanceof TimedTransitionComponent)) { |
93 | - arcLabel = arcLabelPositionString; |
94 | - if (arc.getWeight().value() > 1) { |
95 | - arcLabel += "$" + arc.getWeight().value() + "\\times$\\ "; |
96 | - } |
97 | - |
98 | - if(TAPAALGUI.getCurrentTab().getLens().isTimed()) { |
99 | - arcLabel += "$\\mathrm{" + replaceWithMathLatex(getGuardAsStringIfNotHidden((TimedInputArcComponent) arc)) + "}$"; |
100 | - if (arc instanceof TimedTransportArcComponent) |
101 | - arcLabel += ":" + ((TimedTransportArcComponent) arc).getGroupNr(); |
102 | - arcLabel += "};\n"; |
103 | - } else { |
104 | - arcLabel += "};\n"; |
105 | - } |
106 | - |
107 | - } else { |
108 | - arcLabel = arcLabelPositionString; |
109 | - if (arc.getWeight().value() > 1) { |
110 | - arcLabel += "$" + arc.getWeight().value() + "\\times$\\ "; |
111 | - } |
112 | - arcLabel += ":" + ((TimedTransportArcComponent) arc).getGroupNr() + "};\n"; |
113 | - } |
114 | - |
115 | - } else { |
116 | - if (arc.getWeight().value() > 1) { |
117 | - arcLabel += arcLabelPositionString + "$" + arc.getWeight().value() + "\\times$\\ };\n"; |
118 | - } |
119 | - } |
120 | - return arcLabel; |
121 | - } |
122 | - |
123 | - private String getGuardAsStringIfNotHidden(TimedInputArcComponent arc) { |
124 | - if (!TAPAALGUI.getAppGui().showZeroToInfinityIntervals() && arc.getGuardAsString().equals("[0,inf)")){ |
125 | - return ""; |
126 | - } else { |
127 | - return arc.getGuardAsString(); |
128 | - } |
129 | - } |
130 | - |
131 | private StringBuffer exportTransitions(Transition[] transitions) { |
132 | StringBuffer out = new StringBuffer(); |
133 | for (Transition trans : transitions) { |
134 | @@ -195,7 +152,8 @@ |
135 | |
136 | |
137 | out.append("\\node[transition"); |
138 | - out.append(angle); |
139 | + out.append(angle); |
140 | + out.append(handlePlaceAndTransitionLabel(trans.getNameLabel().getText(), trans.getName(), trans.getAttributesVisible())); |
141 | out.append("] at ("); |
142 | out.append((trans.getPositionX())); |
143 | out.append(','); |
144 | @@ -226,31 +184,30 @@ |
145 | out.append(trans.getId()); |
146 | out.append(".center) { };\n"); |
147 | } |
148 | - if (trans.getAttributesVisible()){ |
149 | - boolean isLabelAboveTransition = trans.getY() > trans.getNameLabel().getY(); |
150 | - boolean isLabelBehindTrans = trans.getX() < trans.getNameLabel().getX(); |
151 | - double xOffset = trans.getName().length() > 5 && !isLabelAboveTransition && !isLabelBehindTrans ? trans.getLayerOffset() : 0; |
152 | - |
153 | - out.append("%% label for transition " + trans.getName() + "\n"); |
154 | - out.append("\\draw ("); |
155 | - out.append(trans.getNameLabel().getX() + xOffset + "," + (trans.getNameLabel().getY() * -1) + ")"); |
156 | - out.append(" node "); |
157 | - out.append(" {"); |
158 | - out.append(exportMathName(trans.getName())); |
159 | - out.append("};\n"); |
160 | - } |
161 | } |
162 | return out; |
163 | } |
164 | |
165 | + private String handlePlaceAndTransitionLabel(String nameLabelText, String name, boolean isVisible) { |
166 | + if(!isVisible) |
167 | + return ""; |
168 | + |
169 | + String result = ", label={[align=left,label distance=0cm]90:"; |
170 | + result += "$\\mathrm{" + (name.replace("_","\\_")) + "}$"; |
171 | + result += handleNameLabel(nameLabelText); |
172 | + result += "}"; |
173 | + return result; |
174 | + } |
175 | + |
176 | private StringBuffer exportPlacesWithTokens(Place[] places) { |
177 | StringBuffer out = new StringBuffer(); |
178 | |
179 | for (Place place : places) { |
180 | - String invariant = getPlaceInvariantString(place); |
181 | + String invariant = "$" + getPlaceInvariantString(place) + "$"; |
182 | String tokensInPlace = getTokenListStringFor(place); |
183 | |
184 | out.append("\\node[place"); |
185 | + out.append(handlePlaceAndTransitionLabel(place.getNameLabel().getText(), place.getName(), place.getAttributesVisible())); |
186 | out.append("] at ("); |
187 | out.append(place.getPositionX()); |
188 | out.append(','); |
189 | @@ -262,37 +219,38 @@ |
190 | exportPlaceTokens(place, out, ((TimedPlaceComponent) place).underlyingPlace().tokens().size()); |
191 | |
192 | if(((TimedPlaceComponent)place).underlyingPlace().isShared()){ |
193 | - out.append("\\node[sharedplace] at ("); |
194 | + out.append("\\node[sharedplace "); |
195 | + out.append("] at ("); |
196 | out.append(place.getId()); |
197 | out.append(".center) { };\n"); |
198 | } |
199 | - if (place.getAttributesVisible() || !invariant.equals("")){ |
200 | - boolean isLabelAbovePlace = place.getY() > place.getNameLabel().getY(); |
201 | - boolean isLabelBehindPlace = place.getX() < place.getNameLabel().getX(); |
202 | - double xOffset = place.getName().length() > 6 && !isLabelAbovePlace && !isLabelBehindPlace ? place.getLayerOffset() : 0; |
203 | - double yOffset = isLabelAbovePlace ? (place.getNameLabel().getHeight() / 2) : 0; |
204 | - |
205 | - out.append("%% label for place " + place.getName() + "\n"); |
206 | - out.append("\\draw ("); |
207 | - out.append((place.getNameLabel().getX() + xOffset) + "," + ((place.getNameLabel().getY() * -1) + yOffset) +")"); |
208 | - out.append(" node[align=left] "); |
209 | - out.append("{"); |
210 | - if(place.getAttributesVisible()) |
211 | - out.append(exportMathName(place.getName())); |
212 | - if(!invariant.equals("")) { |
213 | - if((place.getAttributesVisible())) |
214 | - out.append("\\\\"); |
215 | - out.append(invariant); |
216 | - }else { |
217 | - out.append("};\n"); |
218 | - } |
219 | - |
220 | - } |
221 | } |
222 | - |
223 | return out; |
224 | } |
225 | |
226 | + private String handleNameLabel(String nameLabel) { |
227 | + String nameLabelsString = ""; |
228 | + String[] labelsInName = nameLabel.split("\n"); |
229 | + for(int i = 0; i < labelsInName.length; i++) { |
230 | + |
231 | + if(labelsInName[i].contains("[")) { |
232 | + nameLabelsString += escapeSpacesInAndOrNot(replaceWithMathLatex(labelsInName[i])); |
233 | + nameLabelsString += "\\\\"; |
234 | + } |
235 | + else if(!labelsInName[i].isEmpty()){ |
236 | + nameLabelsString += escapeSpacesInAndOrNot(replaceWithMathLatex(labelsInName[i])); |
237 | + nameLabelsString += "\\\\"; |
238 | + } else { |
239 | + nameLabelsString += "\\\\"; |
240 | + } |
241 | + } |
242 | + return nameLabelsString; |
243 | + } |
244 | + |
245 | + private String escapeSpacesInAndOrNot(String str) { |
246 | + return str.replace(" and ", "\\ and\\ ").replace(" or", "\\ or\\ ").replace(" not", "\\ not\\ "); |
247 | + } |
248 | + |
249 | private void exportPlaceTokens(Place place, StringBuffer out, int numOfTokens) { |
250 | // Dot radius |
251 | final double tRadius = 1; |
252 | @@ -437,6 +395,124 @@ |
253 | } |
254 | } |
255 | |
256 | + private StringBuffer exportGlobalVariables() { |
257 | + StringBuffer out = new StringBuffer(); |
258 | + |
259 | + Context context = new Context(TAPAALGUI.getCurrentTab()); |
260 | + List<ColorType> listColorTypes = context.network().colorTypes(); |
261 | + List<Constant> constantsList = new ArrayList<>(context.network().constants()); |
262 | + List<Variable> variableList = context.network().variables(); |
263 | + |
264 | + if(!context.network().isColored()) { |
265 | + if(constantsList.isEmpty()) { |
266 | + return out; |
267 | + } |
268 | + out.append("%%Global box which contains global color types, variables and/or constants.\n"); |
269 | + out.append("\\node [globalBox] (globalBox) at (current bounding box.north west) [anchor=south west] {"); |
270 | + exportConstants(constantsList, out); |
271 | + out.append("};"); |
272 | + return out; |
273 | + } |
274 | + |
275 | + if((listColorTypes.isEmpty() && constantsList.isEmpty() && variableList.isEmpty())) |
276 | + return out; |
277 | + |
278 | + out.append("%%Global box which contains global color types, variables and/or constants.\n"); |
279 | + out.append("\\node [globalBox] (globalBox) at (current bounding box.north west) [anchor=south west] {"); |
280 | + |
281 | + exportColorTypes(listColorTypes, out); |
282 | + |
283 | + if(listColorTypes.size() > 0 && (variableList.size() > 0 || constantsList.size() > 0)) { |
284 | + out.append("\\\\"); |
285 | + } |
286 | + |
287 | + exportVariables(variableList, out); |
288 | + |
289 | + if(variableList.size() > 0 && !constantsList.isEmpty()) { |
290 | + out.append("\\\\"); |
291 | + } |
292 | + |
293 | + exportConstants(constantsList, out); |
294 | + |
295 | + out.append("};"); |
296 | + |
297 | + return out; |
298 | + } |
299 | + |
300 | + private void exportColorTypes(List<ColorType> listColorTypes, StringBuffer out) { |
301 | + String stringColorList = ""; |
302 | + for(int i = 0; i < listColorTypes.size(); i++) { |
303 | + if(i == 0) { |
304 | + out.append("Color Types:\\\\"); |
305 | + } |
306 | + out.append("$\\mathit{" + listColorTypes.get(i).getName() + "}$ \\textbf{is} "); |
307 | + |
308 | + if(listColorTypes.get(i).isProductColorType()) { |
309 | + out.append("$\\mathit{<"); |
310 | + for(int x = 0; x < listColorTypes.get(i).getProductColorTypes().size(); x++) { |
311 | + stringColorList += listColorTypes.get(i).getProductColorTypes().get(x).getName().replace("_", "\\_"); |
312 | + |
313 | + if(x != listColorTypes.get(i).getProductColorTypes().size() - 1){ |
314 | + stringColorList += ", "; |
315 | + } |
316 | + } |
317 | + out.append(stringColorList + ">}$\\\\"); |
318 | + stringColorList = ""; |
319 | + |
320 | + } else if(listColorTypes.get(i).isIntegerRange()) { |
321 | + out.append("$\\mathit{"); |
322 | + if(listColorTypes.get(i).size() > 1) { |
323 | + int listSize = listColorTypes.get(i).size(); |
324 | + out.append("[" + listColorTypes.get(i).getColors().get(0).getColorName().replace("_","\\_") + ".." + listColorTypes.get(i).getColors().get(listSize - 1).getColorName().replace("_","\\_") + "]"); |
325 | + } else { |
326 | + out.append("[" + listColorTypes.get(i).getFirstColor().getColorName().replace("_","\\_") + "]"); |
327 | + } |
328 | + out.append("}$\\\\"); |
329 | + |
330 | + } else { |
331 | + out.append("$\\mathit{["); |
332 | + for(int x = 0; x < listColorTypes.get(i).getColors().size(); x++) { |
333 | + stringColorList += listColorTypes.get(i).getColors().get(x).getName().replace("_","\\_"); |
334 | + |
335 | + if(x != listColorTypes.get(i).getColors().size() - 1){ |
336 | + stringColorList += ", "; |
337 | + } |
338 | + } |
339 | + out.append(stringColorList + "]}$\\\\"); |
340 | + stringColorList = ""; |
341 | + } |
342 | + } |
343 | + } |
344 | + |
345 | + private void exportVariables(List<Variable> variableList, StringBuffer out) { |
346 | + String result = ""; |
347 | + for(int i = 0; i < variableList.size(); i++) { |
348 | + if (i == 0) { |
349 | + result += "Variables:\\\\ "; |
350 | + } |
351 | + result += "$\\mathit{" + variableList.get(i).getName().replace("_","\\_") + " \\textbf{ in } " + variableList.get(i).getColorType().getName().replace("_","\\_") + "}$"; |
352 | + if(i != variableList.size() - 1) { |
353 | + result += "\\\\"; |
354 | + } |
355 | + } |
356 | + out.append(result); |
357 | + } |
358 | + |
359 | + private void exportConstants(List<Constant> constantsList, StringBuffer out) { |
360 | + String result = ""; |
361 | + |
362 | + for(int i = 0; i < constantsList.size(); i++) { |
363 | + if(i == 0) { |
364 | + result += "Constants:\\\\"; |
365 | + } |
366 | + result += "$\\mathit{" + constantsList.get(i).toString().replace("_","\\_") + "}$"; |
367 | + if(i != constantsList.size() - 1) { |
368 | + result += "\\\\"; |
369 | + } |
370 | + } |
371 | + out.append(result); |
372 | + } |
373 | + |
374 | protected String getTokenListStringFor(Place place) { |
375 | List<TimedToken> tokens = ((TimedPlaceComponent) place).underlyingPlace().tokens(); |
376 | |
377 | @@ -455,7 +531,7 @@ |
378 | String invariant = ""; |
379 | |
380 | if (!((TimedPlaceComponent) place).getInvariantAsString().contains("inf")) |
381 | - invariant = "$\\mathrm{" + replaceWithMathLatex(((TimedPlaceComponent) place).getInvariantAsString()) + "}$};\n"; |
382 | + invariant = replaceWithMathLatex(((TimedPlaceComponent) place).getInvariantAsString()) + "};\n"; |
383 | return invariant; |
384 | } |
385 | |
386 | @@ -480,12 +556,14 @@ |
387 | StringBuffer out = new StringBuffer(); |
388 | |
389 | out.append("\\begin{tikzpicture}[font=\\scriptsize, xscale=0.45, yscale=0.45, x=1.33pt, y=1.33pt]\n"); |
390 | - out.append("%% the figure can be scaled by changing xscale and yscale\n"); |
391 | + out.append("%% the figure can be scaled by changing xscale and yscale or the size of the x- and y-coordinates\n"); |
392 | out.append("%% positions of place/transition labels that are currently fixed to label=135 degrees\n"); |
393 | - out.append("%% can be adjusted so that they do not cover arcs\n"); |
394 | - out.append("%% similarly the curving of arcs can be done by adjusting bend left/right=XX\n"); |
395 | - out.append("%% labels may be slightly skewed compared to the tapaal drawing due to rounding.\n"); |
396 | - out.append("%% This can be adjusted by tuning the coordinates of the label\n"); |
397 | + out.append("%% these can be adjusted by adjusting either the coordinates, the label distance or the label degree\n"); |
398 | + out.append("%% that is placed right after the 'label-distance'. 90: is above (default), 180 is left, 270 is below etc.\n"); |
399 | + out.append("%% The curving of arcs can be done by adjusting bend left/right=XX\n"); |
400 | + out.append("%% labels may be slightly skewed compared to the Tapaal drawing due to rounding.\n"); |
401 | + out.append("%% This can be adjusted by tuning the coordinates of the label, or the degree (see above)\n"); |
402 | + out.append("%% The box containing global variables can also be moved by adjusting the anchor points / bounding box in the [globalBox] node at the end of the Tikz document\n"); |
403 | out.append("\\tikzstyle{arc}=[->,>=stealth,thick]\n"); |
404 | |
405 | out.append("\\tikzstyle{transportArc}=[->,>=diamond,thick]\n"); |
406 | @@ -496,39 +574,24 @@ |
407 | out.append("\\tikzstyle{every token}=[fill=white,text=black]\n"); |
408 | out.append("\\tikzstyle{sharedplace}=[place,minimum size=7.5mm,dashed,thin]\n"); |
409 | out.append("\\tikzstyle{sharedtransition}=[transition, fill opacity=0, minimum width=3.5mm, minimum height=6.5mm,dashed]\n"); |
410 | - out.append("\\tikzstyle{urgenttransition}=[place,fill=white,minimum size=2.0mm,thin]"); |
411 | - out.append("\\tikzstyle{uncontrollabletransition}=[transition,fill=white,draw=black,very thick]"); |
412 | + out.append("\\tikzstyle{urgenttransition}=[place,fill=white,minimum size=2.0mm,thin]\n"); |
413 | + out.append("\\tikzstyle{uncontrollabletransition}=[transition,fill=white,draw=black,very thick]\n"); |
414 | + out.append("\\tikzstyle{globalBox} = [draw,thick,align=left]"); |
415 | return out; |
416 | } |
417 | |
418 | protected String replaceWithMathLatex(String text) { |
419 | - return text.replace("inf", "\\infty").replace("<=", "\\leq ").replace("*", "\\cdot "); |
420 | - } |
421 | - |
422 | - private String exportMathName(String name) { |
423 | - StringBuilder out = new StringBuilder("$\\mathrm{"); |
424 | - int subscripts = 0; |
425 | - for (int i = 0; i < name.length() - 1; i++) { |
426 | - char c = name.charAt(i); |
427 | - if (c == '_') { |
428 | - out.append("_{"); |
429 | - subscripts++; |
430 | - } else { |
431 | - out.append(c); |
432 | - } |
433 | - } |
434 | - |
435 | - char last = name.charAt(name.length() - 1); |
436 | - if (last == '_') { |
437 | - out.append("\\_"); |
438 | - } else |
439 | - out.append(last); |
440 | - |
441 | - for (int i = 0; i < subscripts; i++) { |
442 | - out.append('}'); |
443 | - } |
444 | - out.append("}$"); |
445 | - return out.toString(); |
446 | - } |
447 | - |
448 | + String[] stringList = text.split(" "); |
449 | + String result = ""; |
450 | + |
451 | + for(int i = 0; i < stringList.length; i++) { |
452 | + result += "$\\mathit{" + replaceSpecialSymbols(stringList[i]) + "}$ "; |
453 | + } |
454 | + return result; |
455 | + } |
456 | + |
457 | + protected String replaceSpecialSymbols(String text) { |
458 | + return text.replace("inf", "\\infty").replace("<=", "\\leq").replace("*", "\\cdot") |
459 | + .replace("\u2192", "\\rightarrow").replace("\u221E", "\\infty"); |
460 | + } |
461 | } |
It would be nice if instead of (in referendum colored timed):
1′v[1, 2]Voters1 → [1, 4]
one would print:
1′v
[1, 2]
Voters1 → [1, 4]
(on three sepratate lines).