fiore@0
|
1 /*
|
fiore@0
|
2 CCmI Editor - A Collaborative Cross-Modal Diagram Editing Tool
|
fiore@0
|
3
|
fiore@0
|
4 Copyright (C) 2002 Cay S. Horstmann (http://horstmann.com)
|
fiore@0
|
5 Copyright (C) 2011 Queen Mary University of London (http://ccmi.eecs.qmul.ac.uk/)
|
fiore@0
|
6
|
fiore@0
|
7 This program is free software: you can redistribute it and/or modify
|
fiore@0
|
8 it under the terms of the GNU General Public License as published by
|
fiore@0
|
9 the Free Software Foundation, either version 3 of the License, or
|
fiore@0
|
10 (at your option) any later version.
|
fiore@0
|
11
|
fiore@0
|
12 This program is distributed in the hope that it will be useful,
|
fiore@0
|
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
fiore@0
|
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
fiore@0
|
15 GNU General Public License for more details.
|
fiore@0
|
16
|
fiore@0
|
17 You should have received a copy of the GNU General Public License
|
fiore@0
|
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
fiore@0
|
19 */
|
fiore@0
|
20
|
fiore@0
|
21 package uk.ac.qmul.eecs.ccmi.simpletemplate;
|
fiore@0
|
22
|
fiore@0
|
23 import java.awt.Dimension;
|
fiore@0
|
24 import java.awt.Graphics2D;
|
fiore@0
|
25 import java.awt.geom.Rectangle2D;
|
fiore@0
|
26 import java.util.Arrays;
|
fiore@0
|
27 import java.util.List;
|
fiore@0
|
28 import java.util.Set;
|
fiore@0
|
29
|
fiore@0
|
30 import javax.swing.JLabel;
|
fiore@0
|
31
|
fiore@0
|
32 import uk.ac.qmul.eecs.ccmi.diagrammodel.NodeProperties.Modifiers;
|
fiore@0
|
33
|
fiore@0
|
34 /**
|
fiore@0
|
35 A string that can extend over multiple lines.
|
fiore@0
|
36 */
|
fiore@0
|
37 public class MultiLineString {
|
fiore@0
|
38 /**
|
fiore@0
|
39 Constructs an empty, centered, normal size multiline
|
fiore@0
|
40 string.
|
fiore@0
|
41 */
|
fiore@0
|
42 public MultiLineString(){
|
fiore@0
|
43 text = "";
|
fiore@0
|
44 arrayText = null;
|
fiore@0
|
45 justification = CENTER;
|
fiore@0
|
46 size = NORMAL;
|
fiore@0
|
47 isSingleLine = true;
|
fiore@0
|
48 }
|
fiore@0
|
49 /**
|
fiore@0
|
50 Sets the value of the text property.
|
fiore@0
|
51 @param newValue the text of the multiline string
|
fiore@0
|
52 */
|
fiore@0
|
53 public void setText(String newValue){
|
fiore@0
|
54 setText(newValue,null);
|
fiore@0
|
55 }
|
fiore@0
|
56
|
fiore@0
|
57 public void setText(String newValue, ModifierView[] modifierViews) {
|
fiore@0
|
58 isSingleLine = true;
|
fiore@0
|
59 text = newValue;
|
fiore@0
|
60 this.modifierViews = modifierViews;
|
fiore@0
|
61 format();
|
fiore@0
|
62 }
|
fiore@0
|
63
|
fiore@0
|
64 public void setText(String[] newValue, Modifiers modifiers){
|
fiore@0
|
65 isSingleLine = false;
|
fiore@0
|
66 this.modifiers = modifiers;
|
fiore@0
|
67 arrayText = newValue;
|
fiore@0
|
68 format();
|
fiore@0
|
69 }
|
fiore@0
|
70
|
fiore@0
|
71 public void setBold(boolean bold){
|
fiore@0
|
72 isBold = bold;
|
fiore@0
|
73 format();
|
fiore@0
|
74 }
|
fiore@0
|
75 /**
|
fiore@0
|
76 Gets the value of the text property.
|
fiore@0
|
77 @return the text of the multiline string
|
fiore@0
|
78 */
|
fiore@0
|
79 public String getText() {
|
fiore@0
|
80 if(isSingleLine)
|
fiore@0
|
81 return text;
|
fiore@0
|
82 else{
|
fiore@0
|
83 StringBuilder builder = new StringBuilder("");
|
fiore@0
|
84 for(int i=0; i<arrayText.length; i++){
|
fiore@0
|
85 builder.append(arrayText[i]);
|
fiore@0
|
86 builder.append('\n');
|
fiore@0
|
87 }
|
fiore@0
|
88 return builder.toString();
|
fiore@0
|
89 }
|
fiore@0
|
90 }
|
fiore@0
|
91 /**
|
fiore@0
|
92 Sets the value of the justification property.
|
fiore@0
|
93 @param newValue the justification, one of LEFT, CENTER,
|
fiore@0
|
94 RIGHT
|
fiore@0
|
95 */
|
fiore@0
|
96 public void setJustification(int newValue) { justification = newValue; format(); }
|
fiore@0
|
97 /**
|
fiore@0
|
98 Gets the value of the justification property.
|
fiore@0
|
99 @return the justification, one of LEFT, CENTER,
|
fiore@0
|
100 RIGHT
|
fiore@0
|
101 */
|
fiore@0
|
102 public int getJustification() { return justification; }
|
fiore@0
|
103 /**
|
fiore@0
|
104 Sets the value of the size property.
|
fiore@0
|
105 @param newValue the size, one of SMALL, NORMAL, LARGE
|
fiore@0
|
106 */
|
fiore@0
|
107 public void setSize(int newValue) { size = newValue; format(); }
|
fiore@0
|
108 /**
|
fiore@0
|
109 Gets the value of the size property.
|
fiore@0
|
110 @return the size, one of SMALL, NORMAL, LARGE
|
fiore@0
|
111 */
|
fiore@0
|
112 public int getSize() { return size; }
|
fiore@0
|
113
|
fiore@0
|
114 @Override
|
fiore@0
|
115 public String toString(){
|
fiore@0
|
116 if(isSingleLine)
|
fiore@0
|
117 return text.replace('\n', '|');
|
fiore@0
|
118 else
|
fiore@0
|
119 return getText().replace('\n', '|');
|
fiore@0
|
120 }
|
fiore@0
|
121
|
fiore@0
|
122 private void format(){
|
fiore@0
|
123 StringBuffer prefix = new StringBuffer();
|
fiore@0
|
124 StringBuffer suffix = new StringBuffer();
|
fiore@0
|
125 StringBuffer htmlText = new StringBuffer();
|
fiore@0
|
126 prefix.append(" ");
|
fiore@0
|
127 suffix.insert(0, " ");
|
fiore@0
|
128 if (size == LARGE){
|
fiore@0
|
129 prefix.append("<font size=\"+1\">");
|
fiore@0
|
130 suffix.insert(0, "</font>");
|
fiore@0
|
131 }
|
fiore@0
|
132 if (size == SMALL){
|
fiore@0
|
133 prefix.append("<font size=\"-1\">");
|
fiore@0
|
134 suffix.insert(0, "</font>");
|
fiore@0
|
135 }
|
fiore@0
|
136
|
fiore@0
|
137 htmlText.append("<html>");
|
fiore@0
|
138 if(isSingleLine){
|
fiore@0
|
139 if(isBold)
|
fiore@0
|
140 prefix.append("<b>");
|
fiore@0
|
141 htmlText.append(prefix);
|
fiore@0
|
142
|
fiore@0
|
143 String formattedText = text;
|
fiore@0
|
144 if(modifierViews != null){
|
fiore@0
|
145 for(ModifierView view : modifierViews){
|
fiore@0
|
146 formattedText = formatFromView(formattedText,view);
|
fiore@0
|
147 }
|
fiore@0
|
148 }
|
fiore@0
|
149 htmlText.append(formattedText);
|
fiore@0
|
150
|
fiore@0
|
151 if(isBold)
|
fiore@0
|
152 suffix.insert(0, "</b>");
|
fiore@0
|
153 htmlText.append(suffix);
|
fiore@0
|
154 }else{ // multi line
|
fiore@0
|
155 boolean first = true;
|
fiore@0
|
156 for(int i=0; i<arrayText.length; i++){
|
fiore@0
|
157 if (first)
|
fiore@0
|
158 first = false;
|
fiore@0
|
159 else
|
fiore@0
|
160 htmlText.append("<br>");
|
fiore@0
|
161 htmlText.append(prefix);
|
fiore@0
|
162 String textLine = arrayText[i];
|
fiore@0
|
163 Set<Integer> indexes = modifiers.getIndexes(i);
|
fiore@0
|
164 for(Integer I : indexes){
|
fiore@0
|
165 ModifierView view = (ModifierView)modifiers.getView(modifiers.getTypes().get(I));
|
fiore@0
|
166 textLine = formatFromView(textLine, view);
|
fiore@0
|
167 }
|
fiore@0
|
168 htmlText.append(textLine);
|
fiore@0
|
169 htmlText.append(suffix);
|
fiore@0
|
170 }
|
fiore@0
|
171 }
|
fiore@0
|
172 htmlText.append("</html>");
|
fiore@0
|
173
|
fiore@0
|
174 // replace any < that are not followed by {u, i, b, tt, font, br} with <
|
fiore@0
|
175 List<String> dontReplace = Arrays.asList(new String[] { "u", "i", "b", "tt", "font", "br" });
|
fiore@0
|
176
|
fiore@0
|
177 int ltpos = 0;
|
fiore@0
|
178 while (ltpos != -1){
|
fiore@0
|
179 ltpos = htmlText.indexOf("<", ltpos + 1);
|
fiore@0
|
180 if (ltpos != -1 && !(ltpos + 1 < htmlText.length() && htmlText.charAt(ltpos + 1) == '/')){
|
fiore@0
|
181 int end = ltpos + 1;
|
fiore@0
|
182 while (end < htmlText.length() && Character.isLetter(htmlText.charAt(end))) end++;
|
fiore@0
|
183 if (!dontReplace.contains(htmlText.substring(ltpos + 1, end)))
|
fiore@0
|
184 htmlText.replace(ltpos, ltpos+1, "<");
|
fiore@0
|
185 }
|
fiore@0
|
186 }
|
fiore@0
|
187
|
fiore@0
|
188 label.setText(htmlText.toString());
|
fiore@0
|
189 if (justification == LEFT) label.setHorizontalAlignment(JLabel.LEFT);
|
fiore@0
|
190 else if (justification == CENTER) label.setHorizontalAlignment(JLabel.CENTER);
|
fiore@0
|
191 else if (justification == RIGHT) label.setHorizontalAlignment(JLabel.RIGHT);
|
fiore@0
|
192 }
|
fiore@0
|
193
|
fiore@0
|
194 private String formatFromView(String text, ModifierView view){
|
fiore@0
|
195 if(view == null)
|
fiore@0
|
196 return text;
|
fiore@0
|
197
|
fiore@0
|
198 StringBuilder prefix = new StringBuilder("");
|
fiore@0
|
199 StringBuilder suffix = new StringBuilder("");
|
fiore@0
|
200
|
fiore@0
|
201 prefix.append(view.getPrefix());
|
fiore@0
|
202 suffix.append(view.getSuffix());
|
fiore@0
|
203
|
fiore@0
|
204 if(view.isBold()){
|
fiore@0
|
205 prefix.insert(0,"<b>");
|
fiore@0
|
206 suffix.append("</b>");
|
fiore@0
|
207 }
|
fiore@0
|
208
|
fiore@0
|
209 if(view.isItalic()){
|
fiore@0
|
210 prefix.insert(0,"<i>");
|
fiore@0
|
211 suffix.append("</i>");
|
fiore@0
|
212 }
|
fiore@0
|
213
|
fiore@0
|
214 if(view.isUnderline()){
|
fiore@0
|
215 prefix.insert(0,"<u>");
|
fiore@0
|
216 suffix.append("</u>");
|
fiore@0
|
217 }
|
fiore@0
|
218 return prefix.append(text).append(suffix).toString();
|
fiore@0
|
219 }
|
fiore@0
|
220
|
fiore@0
|
221 /**
|
fiore@0
|
222 Gets the bounding rectangle for this multiline string.
|
fiore@0
|
223 @return the bounding rectangle (with top left corner (0,0))
|
fiore@0
|
224 */
|
fiore@0
|
225 public Rectangle2D getBounds(){
|
fiore@0
|
226 if(isSingleLine){
|
fiore@0
|
227 if (text.length() == 0)
|
fiore@0
|
228 return new Rectangle2D.Double();
|
fiore@0
|
229 }else {
|
fiore@0
|
230 if(arrayText.length == 0)
|
fiore@0
|
231 return new Rectangle2D.Double();
|
fiore@0
|
232 }
|
fiore@0
|
233 Dimension dim = label.getPreferredSize();
|
fiore@0
|
234 return new Rectangle2D.Double(0, 0, dim.getWidth(), dim.getHeight());
|
fiore@0
|
235 }
|
fiore@0
|
236
|
fiore@0
|
237 /**
|
fiore@0
|
238 Draws this multiline string inside a given rectangle
|
fiore@0
|
239 @param g2 the graphics context
|
fiore@0
|
240 @param r the rectangle into which to place this multiline string
|
fiore@0
|
241 */
|
fiore@0
|
242 public void draw(Graphics2D g2, Rectangle2D r){
|
fiore@0
|
243 label.setFont(g2.getFont());
|
fiore@0
|
244 label.setBounds(0, 0, (int) r.getWidth(), (int) r.getHeight());
|
fiore@0
|
245 g2.translate(r.getX(), r.getY());
|
fiore@0
|
246 label.paint(g2);
|
fiore@0
|
247 g2.translate(-r.getX(), -r.getY());
|
fiore@0
|
248 }
|
fiore@0
|
249
|
fiore@0
|
250 public static final int LEFT = 0;
|
fiore@0
|
251 public static final int CENTER = 1;
|
fiore@0
|
252 public static final int RIGHT = 2;
|
fiore@0
|
253 public static final int LARGE = 3;
|
fiore@0
|
254 public static final int NORMAL = 4;
|
fiore@0
|
255 public static final int SMALL = 5;
|
fiore@0
|
256
|
fiore@0
|
257 private String text;
|
fiore@0
|
258 private String[] arrayText;
|
fiore@0
|
259 private Modifiers modifiers;
|
fiore@0
|
260 private ModifierView[] modifierViews;
|
fiore@0
|
261 private int justification;
|
fiore@0
|
262 private int size;
|
fiore@0
|
263 private boolean isBold;
|
fiore@0
|
264 private transient JLabel label = new JLabel();
|
fiore@0
|
265 private boolean isSingleLine;
|
fiore@0
|
266 }
|