// $Id: DiagramSettings.java 41 2010-04-03 20:04:12Z marcusvnac $
// Copyright (c) 2008, 2009 The Regents of the University of California. All
// Rights Reserved. Permission to use, copy, modify, and distribute this
// software and its documentation without fee, and without a written
// agreement is hereby granted, provided that the above copyright notice
// and this paragraph appear in all copies. This software program and
// documentation are copyrighted by The Regents of the University of
// California. The software program and documentation are supplied "AS
// IS", without any accompanying services from The Regents. The Regents
// does not warrant that the operation of the program will be
// uninterrupted or error-free. The end-user understands that the program
// was developed for research purposes and is advised not to rely
// exclusively on the program for any reason. IN NO EVENT SHALL THE
// UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS,
// ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
// THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE. THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY
// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
// PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
// CALIFORNIA HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT,
// UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
package org.argouml.uml.diagram;
import java.awt.Font;
import org.argouml.notation.NotationSettings;
import org.tigris.gef.undo.Memento;
/**
* Diagram appearance settings. This includes basic things like colors and
* fonts, as well as the {@link NotationSettings} which contain all the settings
* that control text formatting.
* <p>
* The settings are designed to work in a hierarchical fashion with any settings
* that are defaulted at the current level inheriting from the next level in
* the hierarchy. A typical hierarchy would be Fig->StyleSheet->Project where
* a style sheet is a named set of attributes that can be applied as a set to
* a fig (perhaps in conjunction with a stereotype). The hierarchy which is
* currently used in ArgoUML is Fig->Diagram->Project, although there's no
* support for changing anything but the Project (and a few of the attributes
* managed directly by GEF).
*
* @author Tom Morris <tfmorris@gmail.com>
*/
public class DiagramSettings {
/*
* The special value <code>null</code> is used internally to indicate that
* the default value should be inherited from the next level of settings.
*/
/**
* Enumeration representing different stereotype presentation styles
*/
public enum StereotypeStyle {
// *IMPORTANT* - These MUST remain in order!
/**
* Textual rendering for stereotype
*/
TEXTUAL(DiagramAppearance.STEREOTYPE_VIEW_TEXTUAL),
/**
* Stereotype rendered with large icon
*/
BIG_ICON(DiagramAppearance.STEREOTYPE_VIEW_BIG_ICON),
/**
* Stereotype rendered with small icon
*/
SMALL_ICON(DiagramAppearance.STEREOTYPE_VIEW_SMALL_ICON);
StereotypeStyle(int value) {
assert value == this.ordinal();
}
/**
* Convert old style int representation to an enum. The enum returned
* is the one at the given ordinal (ie this is the inverse of the
* mapping done by ordinal()).
*
* @param value one of the defined int values in DiagramAppearance
* @return the corresponding StereotypeView enum
*/
public static StereotypeStyle getEnum(int value) {
int counter = 0;
for (StereotypeStyle sv : StereotypeStyle.values()) {
if (counter == value) {
return sv;
}
counter++;
}
return null;
}
}
// private static final StereotypeView[] stereotypeViewMap;
//
// static {
// stereotypeViewMap = new StereotypeView[3];
// StereotypeView.
// stereotypeViewMap[DiagramAppearance.STEREOTYPE_VIEW_TEXTUAL] =
// StereotypeView.TEXTUAL;
// stereotypeViewMap[DiagramAppearance.STEREOTYPE_VIEW_BIG_ICON] =
// StereotypeView.BIG_ICON;
// stereotypeViewMap[DiagramAppearance.STEREOTYPE_VIEW_SMALL_ICON] =
// StereotypeView.SMALL_ICON;
// }
/**
* Next level in the settings hierarchy to inherit from if the value
* isn't set (ie is <default>) at the current level.
*/
private DiagramSettings parent;
private NotationSettings notationSettings;
/* Diagram appearance settings with project scope: */
private String fontName;
private Integer fontSize;
// TODO: Can we remove this and have the application manage things directly
// based on the font?
private Boolean showBoldNames;
/* Some cached fonts based on the above settings */
private Font fontPlain;
private Font fontItalic;
private Font fontBold;
private Font fontBoldItalic;
private Boolean showBidirectionalArrows;
private Integer defaultShadowWidth;
private StereotypeStyle defaultStereotypeView;
/**
* Construct an empty project settings with no parent and all values
* defaulted. <p>
*/
public DiagramSettings() {
this(null);
}
/**
* Construct a DiagramSettings object which inherits from the given
* parent settings (e.g. project default diagram settings).
*
* @param parentSettings settings to inherit from if default values aren't
* overridden.
*/
public DiagramSettings(DiagramSettings parentSettings) {
super();
parent = parentSettings;
if (parentSettings == null) {
notationSettings = new NotationSettings();
} else {
notationSettings =
new NotationSettings(parent.getNotationSettings());
}
recomputeFonts();
}
/**
* @return Returns the notationSettings.
*/
public NotationSettings getNotationSettings() {
return notationSettings;
}
/**
* @param notationSettings The notationSettings to set.
*/
public void setNotationSettings(NotationSettings notationSettings) {
this.notationSettings = notationSettings;
}
/**
* @return Returns <code>true</code> if we show bold names.
*/
public boolean isShowBoldNames() {
if (showBoldNames == null) {
if (parent != null) {
return parent.isShowBoldNames();
} else {
return false;
}
}
return showBoldNames;
}
/**
* @param showem <code>true</code> if names are to be shown in bold font.
*/
public void setShowBoldNames(final boolean showem) {
if (showBoldNames != null && showBoldNames == showem) {
return;
}
Memento memento = new Memento() {
public void redo() {
showBoldNames = showem;
}
public void undo() {
showBoldNames = !showem;
}
};
doUndoable(memento);
}
/**
* @return Returns <code>true</code> if we show the arrows when
* both association ends of an association are navigable.
*/
public boolean isShowBidirectionalArrows() {
if (showBidirectionalArrows == null) {
if (parent != null) {
return parent.isShowBidirectionalArrows();
} else {
return false;
}
}
return showBidirectionalArrows;
}
/**
* @param showem <code>true</code> if both arrows are to be shown when
* both association ends of an association are navigable.
*/
public void setShowBidirectionalArrows(final boolean showem) {
if (showBidirectionalArrows != null
&& showBidirectionalArrows == showem) {
return;
}
Memento memento = new Memento() {
public void redo() {
showBidirectionalArrows = showem;
}
public void undo() {
showBidirectionalArrows = !showem;
}
};
doUndoable(memento);
}
/**
* @return Returns the shadow width.
*/
public int getDefaultShadowWidth() {
if (defaultShadowWidth == null) {
if (parent != null) {
return parent.getDefaultShadowWidth();
} else {
return 0;
}
}
return defaultShadowWidth;
}
/**
* @param newWidth The Shadow Width.
*/
public void setDefaultShadowWidth(final int newWidth) {
if (defaultShadowWidth != null && defaultShadowWidth == newWidth) {
return;
}
final Integer oldValue = defaultShadowWidth;
Memento memento = new Memento() {
public void redo() {
defaultShadowWidth = newWidth;
}
public void undo() {
defaultShadowWidth = oldValue;
}
};
doUndoable(memento);
}
/**
* @return Returns the default stereotype view
* TODO: Enumeration here?
*/
public StereotypeStyle getDefaultStereotypeView() {
if (defaultStereotypeView == null) {
if (parent != null) {
return parent.getDefaultStereotypeView();
} else {
return StereotypeStyle.TEXTUAL;
}
}
return defaultStereotypeView;
}
/**
* @return Returns the default stereotype view as an int compatible with
* old users of DiagramAppearance-defined ints.
* @deprecated for 0.27.2 by tfmorris. For backward compatibility only.
*/
public int getDefaultStereotypeViewInt() {
return getDefaultStereotypeView().ordinal();
}
/**
* @param newView the default stereotype view
* @deprecated for 0.27.2 by tfmorris. Not for use in new code. Only for
* help in transitioning to enum based methods. Use
* {@link #setDefaultStereotypeView(StereotypeStyle)}.
*/
public void setDefaultStereotypeView(final int newView) {
StereotypeStyle sv = StereotypeStyle.getEnum(newView);
if (sv == null) {
throw new IllegalArgumentException("Bad argument " + newView);
}
setDefaultStereotypeView(sv);
}
/**
* @param newView the default stereotype view
*/
public void setDefaultStereotypeView(final StereotypeStyle newView) {
if (defaultStereotypeView != null && defaultStereotypeView == newView) {
return;
}
final StereotypeStyle oldValue = defaultStereotypeView;
Memento memento = new Memento() {
public void redo() {
defaultStereotypeView = newView;
}
public void undo() {
defaultStereotypeView = oldValue;
}
};
doUndoable(memento);
}
/**
* Diagram font name. <p>
*
* @return diagram font name.
*/
public String getFontName() {
if (fontName == null) {
if (parent != null) {
return parent.getFontName();
} else {
return "Dialog";
}
}
return fontName;
}
/**
* Diagram font name.
* @param newFontName diagram font name.
*/
public void setFontName(String newFontName) {
if (fontName != null && fontName.equals(newFontName)) {
return;
}
fontName = newFontName;
recomputeFonts();
}
/**
* Diagram font size. <p>
*
* @return diagram font size.
*/
public int getFontSize() {
if (fontSize == null) {
if (parent != null) {
return parent.getFontSize();
} else {
return 10;
}
}
return fontSize;
}
/**
* Diagram font size.
* @param newFontSize diagram font size.
*/
public void setFontSize(int newFontSize) {
if (fontSize != null && fontSize == newFontSize) {
return;
}
fontSize = newFontSize;
recomputeFonts();
}
private void recomputeFonts() {
// If we've got a local (uninherited) font name or size or if we've got
// no parent to inherit from recompute our cached fonts
if ((fontName != null && !"".equals(fontName) && fontSize != null)
|| parent == null) {
String name = getFontName();
int size = getFontSize();
fontPlain = new Font(name, Font.PLAIN, size);
fontItalic = new Font(name, Font.ITALIC, size);
fontBold = new Font(name, Font.BOLD, size);
fontBoldItalic = new Font(name, Font.BOLD | Font.ITALIC, size);
} else {
fontPlain = null;
fontItalic = null;
fontBold = null;
fontBoldItalic = null;
}
}
/**
* Returns the Plain diagram font which corresponds
* to selected parameters.
*
* @return plain diagram font
*/
public Font getFontPlain() {
if (fontPlain == null) {
return parent.getFontPlain();
}
return fontPlain;
}
/**
* Returns the Italic diagram font which corresponds
* to selected parameters.
*
* @return italic diagram font
*/
public Font getFontItalic() {
if (fontItalic == null) {
return parent.getFontItalic();
}
return fontItalic;
}
/**
* Returns the Bold diagram font which corresponds
* to selected parameters.
*
* @return bold diagram font
*/
public Font getFontBold() {
if (fontBold == null) {
return parent.getFontBold();
}
return fontBold;
}
/**
* Returns the Bold-Italic diagram font which corresponds
* to selected parameters.
*
* @return bold-italic diagram font
*/
public Font getFontBoldItalic() {
if (fontBoldItalic == null) {
return parent.getFontBoldItalic();
}
return fontBoldItalic;
}
/**
* Utility function to convert a font style integer into a Font.
*
* @param fontStyle the style; see the predefined constants in Font
* @return the Font that corresponds to the style
*/
public Font getFont(int fontStyle) {
if ((fontStyle & Font.ITALIC) != 0) {
if ((fontStyle & Font.BOLD) != 0) {
return getFontBoldItalic();
} else {
return getFontItalic();
}
} else {
if ((fontStyle & Font.BOLD) != 0) {
return getFontBold();
} else {
return getFontPlain();
}
}
}
private void doUndoable(Memento memento) {
// TODO: Undo should be managed externally or we should be given
// an Undo manager to use (the project's) rather than using a global one
// if (DiagramUndoManager.getInstance().isGenerateMementos()) {
// DiagramUndoManager.getInstance().addMemento(memento);
// }
memento.redo();
// TODO: Mark diagram/project as dirty?
}
}