Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
DiagramSettings |
|
| 2.7837837837837838;2.784 | ||||
DiagramSettings$1 |
|
| 2.7837837837837838;2.784 | ||||
DiagramSettings$2 |
|
| 2.7837837837837838;2.784 | ||||
DiagramSettings$3 |
|
| 2.7837837837837838;2.784 | ||||
DiagramSettings$4 |
|
| 2.7837837837837838;2.784 | ||||
DiagramSettings$StereotypeStyle |
|
| 2.7837837837837838;2.784 |
1 | /* $Id: DiagramSettings.java 17850 2010-01-12 19:53:35Z linus $ | |
2 | ***************************************************************************** | |
3 | * Copyright (c) 2009 Contributors - see below | |
4 | * All rights reserved. This program and the accompanying materials | |
5 | * are made available under the terms of the Eclipse Public License v1.0 | |
6 | * which accompanies this distribution, and is available at | |
7 | * http://www.eclipse.org/legal/epl-v10.html | |
8 | * | |
9 | * Contributors: | |
10 | * mvw | |
11 | ***************************************************************************** | |
12 | * | |
13 | * Some portions of this file was previously release using the BSD License: | |
14 | */ | |
15 | ||
16 | // Copyright (c) 2008, 2009 The Regents of the University of California. All | |
17 | // Rights Reserved. Permission to use, copy, modify, and distribute this | |
18 | // software and its documentation without fee, and without a written | |
19 | // agreement is hereby granted, provided that the above copyright notice | |
20 | // and this paragraph appear in all copies. This software program and | |
21 | // documentation are copyrighted by The Regents of the University of | |
22 | // California. The software program and documentation are supplied "AS | |
23 | // IS", without any accompanying services from The Regents. The Regents | |
24 | // does not warrant that the operation of the program will be | |
25 | // uninterrupted or error-free. The end-user understands that the program | |
26 | // was developed for research purposes and is advised not to rely | |
27 | // exclusively on the program for any reason. IN NO EVENT SHALL THE | |
28 | // UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, | |
29 | // SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, | |
30 | // ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF | |
31 | // THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF | |
32 | // SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY | |
33 | // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
34 | // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE | |
35 | // PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF | |
36 | // CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, | |
37 | // UPDATES, ENHANCEMENTS, OR MODIFICATIONS. | |
38 | ||
39 | package org.argouml.uml.diagram; | |
40 | ||
41 | import java.awt.Font; | |
42 | import java.beans.PropertyChangeEvent; | |
43 | ||
44 | import org.argouml.application.events.ArgoDiagramAppearanceEvent; | |
45 | import org.argouml.application.events.ArgoEventPump; | |
46 | import org.argouml.application.events.ArgoEventTypes; | |
47 | import org.argouml.configuration.Configuration; | |
48 | import org.argouml.configuration.ConfigurationKey; | |
49 | import org.argouml.kernel.ProfileConfiguration; | |
50 | import org.argouml.notation.NotationSettings; | |
51 | import org.tigris.gef.undo.Memento; | |
52 | ||
53 | /** | |
54 | * Diagram appearance settings. This includes basic things like colors and | |
55 | * fonts, as well as the {@link NotationSettings} which contain all the settings | |
56 | * that control text formatting. | |
57 | * <p> | |
58 | * The settings are designed to work in a hierarchical fashion with any settings | |
59 | * that are defaulted at the current level inheriting from the next level in | |
60 | * the hierarchy. A typical hierarchy would be Fig->StyleSheet->Project where | |
61 | * a style sheet is a named set of attributes that can be applied as a set to | |
62 | * a fig (perhaps in conjunction with a stereotype). The hierarchy which is | |
63 | * currently used in ArgoUML is Fig->Diagram->Project, although there's no | |
64 | * support for changing anything but the Project (and a few of the attributes | |
65 | * managed directly by GEF). | |
66 | * <p> | |
67 | * Notation settings have a semantic meaning in the UML, which | |
68 | * defines the difference between notation settings and | |
69 | * diagram appearance settings. | |
70 | * | |
71 | * @author Tom Morris <tfmorris@gmail.com> | |
72 | */ | |
73 | 3872 | public class DiagramSettings { |
74 | ||
75 | /* | |
76 | * The special value <code>null</code> is used internally to indicate that | |
77 | * the default value should be inherited from the next level of settings. | |
78 | */ | |
79 | ||
80 | /** | |
81 | * Enumeration representing different stereotype presentation styles | |
82 | */ | |
83 | 2768 | public enum StereotypeStyle { |
84 | ||
85 | // *IMPORTANT* - These MUST remain in order! | |
86 | ||
87 | /** | |
88 | * Textual rendering for stereotype | |
89 | */ | |
90 | 900 | TEXTUAL(DiagramAppearance.STEREOTYPE_VIEW_TEXTUAL), |
91 | /** | |
92 | * Stereotype rendered with large icon | |
93 | */ | |
94 | 900 | BIG_ICON(DiagramAppearance.STEREOTYPE_VIEW_BIG_ICON), |
95 | /** | |
96 | * Stereotype rendered with small icon | |
97 | */ | |
98 | 900 | SMALL_ICON(DiagramAppearance.STEREOTYPE_VIEW_SMALL_ICON); |
99 | ||
100 | 2700 | StereotypeStyle(int value) { |
101 | 2700 | assert value == this.ordinal(); |
102 | 2700 | } |
103 | ||
104 | ||
105 | /** | |
106 | * Convert old style int representation to an enum. The enum returned | |
107 | * is the one at the given ordinal (ie this is the inverse of the | |
108 | * mapping done by ordinal()). | |
109 | * | |
110 | * @param value one of the defined int values in DiagramAppearance | |
111 | * @return the corresponding StereotypeView enum | |
112 | */ | |
113 | public static StereotypeStyle getEnum(int value) { | |
114 | 968 | int counter = 0; |
115 | 968 | for (StereotypeStyle sv : StereotypeStyle.values()) { |
116 | 968 | if (counter == value) { |
117 | 968 | return sv; |
118 | } | |
119 | 0 | counter++; |
120 | } | |
121 | 0 | return null; |
122 | } | |
123 | } | |
124 | ||
125 | // private static final StereotypeView[] stereotypeViewMap; | |
126 | // | |
127 | // static { | |
128 | // stereotypeViewMap = new StereotypeView[3]; | |
129 | // StereotypeView. | |
130 | // stereotypeViewMap[DiagramAppearance.STEREOTYPE_VIEW_TEXTUAL] = | |
131 | // StereotypeView.TEXTUAL; | |
132 | // stereotypeViewMap[DiagramAppearance.STEREOTYPE_VIEW_BIG_ICON] = | |
133 | // StereotypeView.BIG_ICON; | |
134 | // stereotypeViewMap[DiagramAppearance.STEREOTYPE_VIEW_SMALL_ICON] = | |
135 | // StereotypeView.SMALL_ICON; | |
136 | // } | |
137 | ||
138 | /** | |
139 | * Next level in the settings hierarchy to inherit from if the value | |
140 | * isn't set (ie is <default>) at the current level. | |
141 | */ | |
142 | private DiagramSettings parent; | |
143 | ||
144 | private NotationSettings notationSettings; | |
145 | ||
146 | /* Diagram appearance settings with project scope: */ | |
147 | private String fontName; | |
148 | private Integer fontSize; | |
149 | ||
150 | // We can not remove this and have the application manage things directly | |
151 | // based on the font, since only the names should be bold. | |
152 | private Boolean showBoldNames; | |
153 | ||
154 | private Boolean showBidirectionalArrows; | |
155 | ||
156 | private Integer defaultShadowWidth; | |
157 | ||
158 | private StereotypeStyle defaultStereotypeView; | |
159 | ||
160 | /* Some cached fonts based on the above settings */ | |
161 | private Font fontPlain; | |
162 | private Font fontItalic; | |
163 | private Font fontBold; | |
164 | private Font fontBoldItalic; | |
165 | ||
166 | /** | |
167 | * Construct an empty diagram settings with no parent and all values | |
168 | * defaulted. <p> | |
169 | */ | |
170 | public DiagramSettings() { | |
171 | 2039 | this(null); |
172 | 2039 | } |
173 | ||
174 | /** | |
175 | * Construct a DiagramSettings object which inherits from the given | |
176 | * parent settings (e.g. project default diagram settings). | |
177 | * | |
178 | * @param parentSettings settings to inherit from if default values aren't | |
179 | * overridden. | |
180 | */ | |
181 | public DiagramSettings(DiagramSettings parentSettings) { | |
182 | 2039 | super(); |
183 | 2039 | parent = parentSettings; |
184 | 2039 | if (parentSettings == null) { |
185 | 2039 | notationSettings = new NotationSettings(); |
186 | } else { | |
187 | 0 | notationSettings = |
188 | new NotationSettings(parent.getNotationSettings()); | |
189 | } | |
190 | 2039 | recomputeFonts(); |
191 | 2039 | } |
192 | ||
193 | /** | |
194 | * Send all events when the settings are changed to refresh | |
195 | * anything rendered with these settings. | |
196 | */ | |
197 | public void notifyOfChangedSettings() { | |
198 | /* | |
199 | * Since body ever looks | |
200 | * at the type of the diagram appearance event, we can simplify from | |
201 | * sending every existing event to one event only. But since there is no | |
202 | * catch-all event defined, we just use one. Rationale: reduce the | |
203 | * number of total refreshes of the drawing. | |
204 | */ | |
205 | 12 | ConfigurationKey key = |
206 | Configuration.makeKey("diagramappearance", "all"); | |
207 | 12 | ArgoEventPump.fireEvent(new ArgoDiagramAppearanceEvent( |
208 | ArgoEventTypes.DIAGRAM_FONT_CHANGED, new PropertyChangeEvent( | |
209 | this, key.getKey(), "0", "0"))); | |
210 | 12 | } |
211 | ||
212 | /** | |
213 | * Initialize the diagram settings with application default values | |
214 | * from the Configuration retrieved from disk. | |
215 | */ | |
216 | public void initFromConfiguration() { | |
217 | 968 | setShowBoldNames(Configuration.getBoolean( |
218 | DiagramAppearance.KEY_SHOW_BOLD_NAMES)); | |
219 | ||
220 | 968 | setShowBidirectionalArrows(!Configuration.getBoolean( |
221 | DiagramAppearance.KEY_HIDE_BIDIRECTIONAL_ARROWS, true)); | |
222 | ||
223 | 968 | setDefaultShadowWidth(Configuration.getInteger( |
224 | DiagramAppearance.KEY_DEFAULT_SHADOW_WIDTH, 1)); | |
225 | ||
226 | 968 | setDefaultStereotypeView(Configuration.getInteger( |
227 | ProfileConfiguration.KEY_DEFAULT_STEREOTYPE_VIEW, | |
228 | DiagramAppearance.STEREOTYPE_VIEW_TEXTUAL)); | |
229 | ||
230 | 968 | setFontName( |
231 | DiagramAppearance.getInstance().getConfiguredFontName()); | |
232 | 968 | setFontSize( |
233 | Configuration.getInteger(DiagramAppearance.KEY_FONT_SIZE)); | |
234 | 968 | } |
235 | ||
236 | /** | |
237 | * @return Returns the notationSettings. | |
238 | */ | |
239 | public NotationSettings getNotationSettings() { | |
240 | 2039 | return notationSettings; |
241 | } | |
242 | ||
243 | ||
244 | /** | |
245 | * @param notationSettings The notationSettings to set. | |
246 | */ | |
247 | public void setNotationSettings(NotationSettings notationSettings) { | |
248 | 0 | this.notationSettings = notationSettings; |
249 | 0 | } |
250 | ||
251 | ||
252 | /** | |
253 | * @return Returns <code>true</code> if we show bold names. | |
254 | */ | |
255 | public boolean isShowBoldNames() { | |
256 | 124 | if (showBoldNames == null) { |
257 | 0 | if (parent != null) { |
258 | 0 | return parent.isShowBoldNames(); |
259 | } else { | |
260 | 0 | return false; |
261 | } | |
262 | } | |
263 | 124 | return showBoldNames; |
264 | } | |
265 | ||
266 | /** | |
267 | * @param showem <code>true</code> if names are to be shown in bold font. | |
268 | */ | |
269 | public void setShowBoldNames(final boolean showem) { | |
270 | 980 | if (showBoldNames != null && showBoldNames == showem) { |
271 | 12 | return; |
272 | } | |
273 | ||
274 | 968 | Memento memento = new Memento() { |
275 | public void redo() { | |
276 | 968 | showBoldNames = showem; |
277 | 968 | } |
278 | ||
279 | public void undo() { | |
280 | 0 | showBoldNames = !showem; |
281 | 0 | } |
282 | }; | |
283 | 968 | doUndoable(memento); |
284 | 968 | } |
285 | ||
286 | ||
287 | /** | |
288 | * @return Returns <code>true</code> if we show the arrows when | |
289 | * both association ends of an association are navigable. | |
290 | */ | |
291 | public boolean isShowBidirectionalArrows() { | |
292 | 124 | if (showBidirectionalArrows == null) { |
293 | 0 | if (parent != null) { |
294 | 0 | return parent.isShowBidirectionalArrows(); |
295 | } else { | |
296 | 0 | return false; |
297 | } | |
298 | } | |
299 | 124 | return showBidirectionalArrows; |
300 | } | |
301 | ||
302 | /** | |
303 | * @param showem <code>true</code> if both arrows are to be shown when | |
304 | * both association ends of an association are navigable. | |
305 | */ | |
306 | public void setShowBidirectionalArrows(final boolean showem) { | |
307 | 980 | if (showBidirectionalArrows != null |
308 | && showBidirectionalArrows == showem) { | |
309 | 12 | return; |
310 | } | |
311 | ||
312 | 968 | Memento memento = new Memento() { |
313 | public void redo() { | |
314 | 968 | showBidirectionalArrows = showem; |
315 | 968 | } |
316 | ||
317 | public void undo() { | |
318 | 0 | showBidirectionalArrows = !showem; |
319 | 0 | } |
320 | }; | |
321 | 968 | doUndoable(memento); |
322 | ||
323 | 968 | } |
324 | ||
325 | ||
326 | /** | |
327 | * @return Returns the shadow width. | |
328 | */ | |
329 | public int getDefaultShadowWidth() { | |
330 | 1195 | if (defaultShadowWidth == null) { |
331 | 1071 | if (parent != null) { |
332 | 0 | return parent.getDefaultShadowWidth(); |
333 | } else { | |
334 | 1071 | return 0; |
335 | } | |
336 | } | |
337 | 124 | return defaultShadowWidth; |
338 | } | |
339 | ||
340 | /** | |
341 | * @param newWidth The Shadow Width. | |
342 | */ | |
343 | public void setDefaultShadowWidth(final int newWidth) { | |
344 | 980 | if (defaultShadowWidth != null && defaultShadowWidth == newWidth) { |
345 | 12 | return; |
346 | } | |
347 | ||
348 | 968 | final Integer oldValue = defaultShadowWidth; |
349 | ||
350 | 968 | Memento memento = new Memento() { |
351 | public void redo() { | |
352 | 968 | defaultShadowWidth = newWidth; |
353 | 968 | } |
354 | ||
355 | public void undo() { | |
356 | 0 | defaultShadowWidth = oldValue; |
357 | 0 | } |
358 | }; | |
359 | 968 | doUndoable(memento); |
360 | ||
361 | 968 | } |
362 | ||
363 | ||
364 | /** | |
365 | * @return Returns the default stereotype view | |
366 | * TODO: Enumeration here? | |
367 | */ | |
368 | public StereotypeStyle getDefaultStereotypeView() { | |
369 | 1171 | if (defaultStereotypeView == null) { |
370 | 1071 | if (parent != null) { |
371 | 0 | return parent.getDefaultStereotypeView(); |
372 | } else { | |
373 | 1071 | return StereotypeStyle.TEXTUAL; |
374 | } | |
375 | } | |
376 | 100 | return defaultStereotypeView; |
377 | } | |
378 | ||
379 | /** | |
380 | * @return Returns the default stereotype view as an int compatible with | |
381 | * old users of DiagramAppearance-defined ints. | |
382 | * @deprecated for 0.27.2 by tfmorris. For backward compatibility only. | |
383 | */ | |
384 | public int getDefaultStereotypeViewInt() { | |
385 | 100 | return getDefaultStereotypeView().ordinal(); |
386 | } | |
387 | ||
388 | /** | |
389 | * @param newView the default stereotype view | |
390 | * @deprecated for 0.27.2 by tfmorris. Not for use in new code. Only for | |
391 | * help in transitioning to enum based methods. Use | |
392 | * {@link #setDefaultStereotypeView(StereotypeStyle)}. | |
393 | */ | |
394 | public void setDefaultStereotypeView(final int newView) { | |
395 | 968 | StereotypeStyle sv = StereotypeStyle.getEnum(newView); |
396 | 968 | if (sv == null) { |
397 | 0 | throw new IllegalArgumentException("Bad argument " + newView); |
398 | } | |
399 | 968 | setDefaultStereotypeView(sv); |
400 | 968 | } |
401 | ||
402 | /** | |
403 | * @param newView the default stereotype view | |
404 | */ | |
405 | public void setDefaultStereotypeView(final StereotypeStyle newView) { | |
406 | 968 | if (defaultStereotypeView != null && defaultStereotypeView == newView) { |
407 | 0 | return; |
408 | } | |
409 | ||
410 | 968 | final StereotypeStyle oldValue = defaultStereotypeView; |
411 | ||
412 | 968 | Memento memento = new Memento() { |
413 | public void redo() { | |
414 | 968 | defaultStereotypeView = newView; |
415 | 968 | } |
416 | ||
417 | public void undo() { | |
418 | 0 | defaultStereotypeView = oldValue; |
419 | 0 | } |
420 | }; | |
421 | 968 | doUndoable(memento); |
422 | 968 | } |
423 | ||
424 | ||
425 | /** | |
426 | * Diagram font name. <p> | |
427 | * | |
428 | * @return diagram font name. | |
429 | */ | |
430 | public String getFontName() { | |
431 | 5170 | if (fontName == null) { |
432 | 3110 | if (parent != null) { |
433 | 0 | return parent.getFontName(); |
434 | } else { | |
435 | 3110 | return "Dialog"; |
436 | } | |
437 | } | |
438 | 2060 | return fontName; |
439 | } | |
440 | ||
441 | /** | |
442 | * Diagram font name. | |
443 | * @param newFontName diagram font name. | |
444 | */ | |
445 | public void setFontName(String newFontName) { | |
446 | 980 | if (fontName != null && fontName.equals(newFontName)) { |
447 | 12 | return; |
448 | } | |
449 | 968 | fontName = newFontName; |
450 | 968 | recomputeFonts(); |
451 | 968 | } |
452 | ||
453 | /** | |
454 | * Diagram font size. <p> | |
455 | * | |
456 | * @return diagram font size. | |
457 | */ | |
458 | public int getFontSize() { | |
459 | 5170 | if (fontSize == null) { |
460 | 4078 | if (parent != null) { |
461 | 0 | return parent.getFontSize(); |
462 | } else { | |
463 | 4078 | return 10; |
464 | } | |
465 | } | |
466 | 1092 | return fontSize; |
467 | } | |
468 | ||
469 | /** | |
470 | * Diagram font size. | |
471 | * @param newFontSize diagram font size. | |
472 | */ | |
473 | public void setFontSize(int newFontSize) { | |
474 | 980 | if (fontSize != null && fontSize == newFontSize) { |
475 | 12 | return; |
476 | } | |
477 | 968 | fontSize = newFontSize; |
478 | 968 | recomputeFonts(); |
479 | 968 | } |
480 | ||
481 | private void recomputeFonts() { | |
482 | // If we've got a local (uninherited) font name or size or if we've got | |
483 | // no parent to inherit from recompute our cached fonts | |
484 | 3975 | if ((fontName != null && !"".equals(fontName) && fontSize != null) |
485 | || parent == null) { | |
486 | 3975 | String name = getFontName(); |
487 | 3975 | int size = getFontSize(); |
488 | 3975 | fontPlain = new Font(name, Font.PLAIN, size); |
489 | 3975 | fontItalic = new Font(name, Font.ITALIC, size); |
490 | 3975 | fontBold = new Font(name, Font.BOLD, size); |
491 | 3975 | fontBoldItalic = new Font(name, Font.BOLD | Font.ITALIC, size); |
492 | 3975 | } else { |
493 | 0 | fontPlain = null; |
494 | 0 | fontItalic = null; |
495 | 0 | fontBold = null; |
496 | 0 | fontBoldItalic = null; |
497 | } | |
498 | 3975 | } |
499 | ||
500 | /** | |
501 | * Returns the Plain diagram font which corresponds | |
502 | * to selected parameters. | |
503 | * | |
504 | * @return plain diagram font | |
505 | */ | |
506 | public Font getFontPlain() { | |
507 | 0 | if (fontPlain == null) { |
508 | 0 | return parent.getFontPlain(); |
509 | } | |
510 | 0 | return fontPlain; |
511 | } | |
512 | ||
513 | /** | |
514 | * Returns the Italic diagram font which corresponds | |
515 | * to selected parameters. | |
516 | * | |
517 | * @return italic diagram font | |
518 | */ | |
519 | public Font getFontItalic() { | |
520 | 0 | if (fontItalic == null) { |
521 | 0 | return parent.getFontItalic(); |
522 | } | |
523 | 0 | return fontItalic; |
524 | } | |
525 | ||
526 | /** | |
527 | * Returns the Bold diagram font which corresponds | |
528 | * to selected parameters. | |
529 | * | |
530 | * @return bold diagram font | |
531 | */ | |
532 | public Font getFontBold() { | |
533 | 0 | if (fontBold == null) { |
534 | 0 | return parent.getFontBold(); |
535 | } | |
536 | 0 | return fontBold; |
537 | } | |
538 | ||
539 | /** | |
540 | * Returns the Bold-Italic diagram font which corresponds | |
541 | * to selected parameters. | |
542 | * | |
543 | * @return bold-italic diagram font | |
544 | */ | |
545 | public Font getFontBoldItalic() { | |
546 | 0 | if (fontBoldItalic == null) { |
547 | 0 | return parent.getFontBoldItalic(); |
548 | } | |
549 | 0 | return fontBoldItalic; |
550 | } | |
551 | ||
552 | /** | |
553 | * Utility function to convert a font style integer into a Font. | |
554 | * | |
555 | * @param fontStyle the style; see the predefined constants in Font | |
556 | * @return the Font that corresponds to the style | |
557 | */ | |
558 | public Font getFont(int fontStyle) { | |
559 | 0 | if ((fontStyle & Font.ITALIC) != 0) { |
560 | 0 | if ((fontStyle & Font.BOLD) != 0) { |
561 | 0 | return getFontBoldItalic(); |
562 | } else { | |
563 | 0 | return getFontItalic(); |
564 | } | |
565 | } else { | |
566 | 0 | if ((fontStyle & Font.BOLD) != 0) { |
567 | 0 | return getFontBold(); |
568 | } else { | |
569 | 0 | return getFontPlain(); |
570 | } | |
571 | } | |
572 | } | |
573 | ||
574 | private void doUndoable(Memento memento) { | |
575 | // TODO: Undo should be managed externally or we should be given | |
576 | // an Undo manager to use (the project's) rather than using a global one | |
577 | // if (DiagramUndoManager.getInstance().isGenerateMementos()) { | |
578 | // DiagramUndoManager.getInstance().addMemento(memento); | |
579 | // } | |
580 | 3872 | memento.redo(); |
581 | // TODO: Mark diagram/project as dirty? | |
582 | 3872 | } |
583 | } | |
584 |