/* $Id: ResourceLoaderWrapper.java 18324 2010-04-22 11:33:25Z bobtarling $
*****************************************************************************
* Copyright (c) 2009-2010 Contributors - see below
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Thomas Neustupny
* Bob Tarling
*
*****************************************************************************
*
* Some portions of this file was previously release using the BSD License:
*/
// Copyright (c) 1996-2008 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.application.helpers;
import java.net.URL;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.UIManager;
import org.apache.log4j.Logger;
import org.argouml.i18n.Translator;
import org.argouml.model.DataTypesHelper;
import org.argouml.model.InvalidElementException;
import org.argouml.model.Model;
/**
* Wrapper around org.tigris.gef.util.ResourceLoader.<p>
*
* Necessary since ArgoUML needs some extra init.
*
* @since Nov 24, 2002
* @author jaap.branderhorst@xs4all.nl
* @stereotype singleton
*/
public final class ResourceLoaderWrapper {
/**
* Logger.
*/
private static final Logger LOG =
Logger.getLogger(ResourceLoaderWrapper.class);
private static ImageIcon initialStateIcon;
private static ImageIcon deepIcon;
private static ImageIcon shallowIcon;
private static ImageIcon forkIcon;
private static ImageIcon joinIcon;
private static ImageIcon branchIcon;
private static ImageIcon junctionIcon;
private static ImageIcon realizeIcon;
private static ImageIcon signalIcon;
private static ImageIcon exceptionIcon;
private static ImageIcon commentIcon;
private Hashtable<Class, Icon> iconCache = new Hashtable<Class, Icon>();
/**
* Singleton implementation.
*/
private static ResourceLoaderWrapper instance = new ResourceLoaderWrapper();
/**
* Returns the singleton instance.
*
* @return ResourceLoaderWrapper
*/
public static ResourceLoaderWrapper getInstance() {
return instance;
}
/**
* Constructor for ResourceLoaderWrapper.
*/
private ResourceLoaderWrapper() {
initResourceLoader();
}
/**
* Calculate the path to a look and feel object.
*
* @param classname
* The look and feel classname
* @param element
* The en part of the path.
* @return the complete path.
*/
private static String lookAndFeelPath(String classname, String element) {
return "/org/argouml/Images/plaf/"
+ classname.replace('.', '/')
+ "/toolbarButtonGraphics/"
+ element;
}
/**
* Initializes the resourceloader.
*
* LookupIconResource checks if there are locations and extensions known.
* If there are none, this method is called to initialize the resource
* loader. Originally, this method was placed within Main but this coupled
* Main and the resourceLoader too much.
*/
private static void initResourceLoader() {
String lookAndFeelClassName;
if ("true".equals(System.getProperty("force.nativelaf", "false"))) {
lookAndFeelClassName = UIManager.getSystemLookAndFeelClassName();
} else {
lookAndFeelClassName = "javax.swing.plaf.metal.MetalLookAndFeel";
}
String lookAndFeelGeneralImagePath =
lookAndFeelPath(lookAndFeelClassName, "general");
String lookAndFeelNavigationImagePath =
lookAndFeelPath(lookAndFeelClassName, "navigation");
String lookAndFeelDiagramImagePath =
lookAndFeelPath(lookAndFeelClassName, "argouml/diagrams");
String lookAndFeelElementImagePath =
lookAndFeelPath(lookAndFeelClassName, "argouml/elements");
String lookAndFeelArgoUmlImagePath =
lookAndFeelPath(lookAndFeelClassName, "argouml");
ResourceLoader.addResourceExtension("gif");
ResourceLoader.addResourceExtension("png");
ResourceLoader.addResourceLocation(lookAndFeelGeneralImagePath);
ResourceLoader.addResourceLocation(lookAndFeelNavigationImagePath);
ResourceLoader.addResourceLocation(lookAndFeelDiagramImagePath);
ResourceLoader.addResourceLocation(lookAndFeelElementImagePath);
ResourceLoader.addResourceLocation(lookAndFeelArgoUmlImagePath);
ResourceLoader.addResourceLocation("/org/argouml/Images");
ResourceLoader.addResourceLocation("/org/tigris/gef/Images");
// Initialze GEF's version of the loader too
// TODO: We should probably be passing icons that we loaded ourselves
// but there doesn't seem to be a way to do that with GEF - tfm
org.tigris.gef.util.ResourceLoader.addResourceExtension("gif");
org.tigris.gef.util.ResourceLoader.addResourceExtension("png");
org.tigris.gef.util.ResourceLoader
.addResourceLocation(lookAndFeelGeneralImagePath);
org.tigris.gef.util.ResourceLoader
.addResourceLocation(lookAndFeelNavigationImagePath);
org.tigris.gef.util.ResourceLoader
.addResourceLocation(lookAndFeelDiagramImagePath);
org.tigris.gef.util.ResourceLoader
.addResourceLocation(lookAndFeelElementImagePath);
org.tigris.gef.util.ResourceLoader
.addResourceLocation(lookAndFeelArgoUmlImagePath);
org.tigris.gef.util.ResourceLoader
.addResourceLocation("/org/argouml/Images");
org.tigris.gef.util.ResourceLoader
.addResourceLocation("/org/tigris/gef/Images");
initialStateIcon = ResourceLoader.lookupIconResource("Initial");
deepIcon = ResourceLoader.lookupIconResource("DeepHistory");
shallowIcon = ResourceLoader.lookupIconResource("ShallowHistory");
forkIcon = ResourceLoader.lookupIconResource("Fork");
joinIcon = ResourceLoader.lookupIconResource("Join");
branchIcon = ResourceLoader.lookupIconResource("Choice");
junctionIcon = ResourceLoader.lookupIconResource("Junction");
realizeIcon = ResourceLoader.lookupIconResource("Realization");
signalIcon = ResourceLoader.lookupIconResource("SignalSending");
exceptionIcon = ResourceLoader.lookupIconResource("Exception");
commentIcon = ResourceLoader.lookupIconResource("Note");
}
/**
* This public operation is needed
* to allow modules to add their own images.
*
* @param location the path were the images are
*/
public static void addResourceLocation(String location) {
ResourceLoader.addResourceLocation(location);
}
/**
* Find the correct icon for a key.
*
* @param resource The name of the resource to look up.
* @return The ImageIcon.
*/
public static ImageIcon lookupIconResource(String resource) {
return ResourceLoader.lookupIconResource(resource);
}
/**
* Find the correct icon for a key.
*
* @param resource The name of the resource to look up.
* @param desc The description for the icon.
* @return The ImageIcon.
*/
public static ImageIcon lookupIconResource(String resource, String desc) {
return ResourceLoader.lookupIconResource(resource, desc);
}
/**
* Look up the Icon for a key.
*
* @param key The key to find.
* @return The found Icon.
*/
public static ImageIcon lookupIcon(String key) {
return lookupIconResource(getImageBinding(key),
Translator.localize(key));
}
/**
* Find the Icon for a given model element.
*
* @return The Icon or <code>null</code> if there is no Icon.
* @param value The model element.
*
* TODO: This should not use string matching on classnames to do this
* since this means that we have knowledge about how the model
* elements are implemented outside of the Model component.
*/
public Icon lookupIcon(Object value) {
if (value == null) {
throw new IllegalArgumentException(
"Attempted to get an icon given a null key");
}
if (value instanceof String) {
return null;
}
Icon icon = iconCache.get(value.getClass());
try {
if (Model.getFacade().isAPseudostate(value)) {
Object kind = Model.getFacade().getKind(value);
DataTypesHelper helper = Model.getDataTypesHelper();
if (helper.equalsINITIALKind(kind)) {
icon = initialStateIcon;
}
if (helper.equalsDeepHistoryKind(kind)) {
icon = deepIcon;
}
if (helper.equalsShallowHistoryKind(kind)) {
icon = shallowIcon;
}
if (helper.equalsFORKKind(kind)) {
icon = forkIcon;
}
if (helper.equalsJOINKind(kind)) {
icon = joinIcon;
}
if (helper.equalsCHOICEKind(kind)) {
icon = branchIcon;
}
if (helper.equalsJUNCTIONKind(kind)) {
icon = junctionIcon;
}
// if (MPseudostateKind.FINAL.equals(kind))
// icon = _FinalStateIcon;
}
if (Model.getFacade().isAAbstraction(value)) {
icon = realizeIcon;
}
if (Model.getFacade().isAException(value)) {
icon = exceptionIcon;
} else {
// needs more work: sending and receiving icons
if (Model.getFacade().isASignal(value)) {
icon = signalIcon;
}
}
if (Model.getFacade().isAComment(value)) {
icon = commentIcon;
}
if (icon == null) {
String cName = Model.getMetaTypes().getName(value);
icon = lookupIconResource(cName);
if (icon == null) {
LOG.debug("Can't find icon for " + cName);
} else {
synchronized (iconCache) {
iconCache.put(value.getClass(), icon);
}
}
}
} catch (InvalidElementException e) {
LOG.debug("Attempted to get icon for deleted element");
return null;
}
return icon;
}
/**
* Map to convert tokens into file names.
*/
private static Map<String, String> images = new HashMap<String, String>();
static {
images.put("action.about-argouml", "AboutArgoUML");
images.put("action.activity-diagram", "Activity Diagram");
images.put("action.class-diagram", "Class Diagram");
images.put("action.collaboration-diagram", "Collaboration Diagram");
images.put("action.deployment-diagram", "Deployment Diagram");
images.put("action.sequence-diagram", "Sequence Diagram");
images.put("action.state-diagram", "State Diagram");
images.put("action.usecase-diagram", "Use Case Diagram");
}
static {
images.put("action.add-concurrent-region", "Add Concurrent Region");
images.put("action.add-message", "Add Message");
images.put("action.configure-perspectives", "ConfigurePerspectives");
images.put("action.copy", "Copy");
images.put("action.cut", "Cut");
images.put("action.delete-concurrent-region", "DeleteConcurrentRegion");
images.put("action.delete-from-model", "DeleteFromModel");
images.put("action.find", "Find...");
images.put("action.import-sources", "Import Sources...");
images.put("action.more-info", "More Info...");
images.put("action.navigate-back", "NavigateBack");
images.put("action.navigate-forward", "NavigateForward");
images.put("action.navigate-up", "NavigateUp");
images.put("action.new", "New");
images.put("action.new-profile", "NewProfile");
images.put("action.new-todo-item", "New To Do Item...");
images.put("action.open-project", "Open Project...");
images.put("action.page-setup", "Page Setup...");
images.put("action.paste", "Paste");
images.put("action.print", "Print...");
images.put("action.properties", "Properties");
images.put("action.remove-from-diagram", "Remove From Diagram");
images.put("action.resolve-item", "Resolve Item...");
images.put("action.save-project", "Save Project");
images.put("action.save-project-as", "Save Project As...");
images.put("action.settings", "Settings...");
images.put("action.snooze-critic", "Snooze Critic");
images.put("action.system-information", "System Information");
}
static {
images.put("button.broom", "Broom");
images.put("button.new-actionstate", "ActionState");
images.put("button.new-actor", "Actor");
images.put("button.new-aggregation", "Aggregation");
images.put("button.new-association", "Association");
images.put("button.new-associationclass", "AssociationClass");
images.put("button.new-association-end", "AssociationEnd");
images.put("button.new-associationrole", "AssociationRole");
images.put("button.new-attribute", "New Attribute");
images.put("button.new-callaction", "CallAction");
images.put("button.new-terminateaction", "TerminateAction");
images.put("button.new-uninterpretedaction", "UninterpretedAction");
images.put("button.new-actionsequence", "ActionSequence");
images.put("button.new-callaction", "CallAction");
images.put("button.new-callevent", "CallEvent");
images.put("button.new-callstate", "CallState");
images.put("button.new-changeevent", "ChangeEvent");
images.put("button.new-choice", "Choice");
images.put("button.new-class", "Class");
images.put("button.new-classifierrole", "ClassifierRole");
images.put("button.new-commentlink", "CommentLink");
images.put("button.new-component", "Component");
images.put("button.new-componentinstance", "ComponentInstance");
images.put("button.new-compositestate", "CompositeState");
images.put("button.new-composition", "Composition");
images.put("button.new-createaction", "CreateAction");
images.put("button.new-datatype", "DataType");
images.put("button.new-deephistory", "DeepHistory");
images.put("button.new-dependency", "Dependency");
images.put("button.new-destroyaction", "DestroyAction");
images.put("button.new-enumeration", "Enumeration");
images.put("button.new-enumerationliteral", "EnumerationLiteral");
images.put("button.new-extension-point", "New Extension Point");
images.put("button.new-extend", "Extend");
images.put("button.new-exception", "Exception");
images.put("button.new-extensionpoint", "ExtensionPoint");
images.put("button.new-guard", "Guard");
images.put("button.new-method", "Method");
images.put("button.new-message", "Message");
images.put("button.new-argument", "Argument");
images.put("button.new-property", "Property");
images.put("button.new-templateparameter", "TemplateParameter");
}
static {
images.put("button.new-finalstate", "FinalState");
images.put("button.new-fork", "Fork");
images.put("button.new-generalization", "Generalization");
images.put("button.new-include", "Include");
images.put("button.new-initial", "Initial");
}
static {
images.put("button.new-inner-class", "Inner Class");
images.put("button.new-interface", "Interface");
images.put("button.new-join", "Join");
images.put("button.new-junction", "Junction");
images.put("button.new-link", "Link");
images.put("button.new-node", "Node");
images.put("button.new-nodeinstance", "NodeInstance");
images.put("button.new-object", "Object");
images.put("button.new-objectflowstate", "ObjectFlowState");
}
static {
images.put("button.new-operation", "New Operation");
images.put("button.new-package", "Package");
images.put("button.new-parameter", "New Parameter");
images.put("button.new-partition", "Partition");
images.put("button.new-permission", "Permission");
images.put("button.new-profile-package", "ProfilePackage");
images.put("button.new-raised-signal", "New Raised Signal");
images.put("button.new-reception", "New Reception");
images.put("button.new-realization", "Realization");
images.put("button.new-returnaction", "ReturnAction");
images.put("button.new-sendaction", "SendAction");
images.put("button.new-shallowhistory", "ShallowHistory");
images.put("button.new-signal", "Signal");
images.put("button.new-signalevent", "SignalEvent");
images.put("button.new-simplestate", "SimpleState");
images.put("button.new-stereotype", "Stereotype");
images.put("button.new-stubstate", "StubState");
images.put("button.new-subactivitystate", "SubactivityState");
images.put("button.new-submachinestate", "SubmachineState");
images.put("button.new-synchstate", "SynchState");
images.put("button.new-timeevent", "TimeEvent");
images.put("button.new-tagdefinition", "TagDefinition");
images.put("button.new-transition", "Transition");
images.put("button.new-uniaggregation", "UniAggregation");
images.put("button.new-uniassociation", "UniAssociation");
images.put("button.new-unicomposition", "UniComposition");
images.put("button.new-usage", "Usage");
images.put("button.new-usecase", "UseCase");
}
static {
images.put("button.select", "Select");
images.put("button.sequence-expand", "SequenceExpand");
images.put("button.sequence-contract", "SequenceContract");
}
/**
* Convert the key to the image file name.
*
* @param name the new i18n key
* @return the file name (base part only).
*/
public static String getImageBinding(String name) {
String found = images.get(name);
if (found == null) {
return name;
}
return found;
}
/**
* Find the path to a given icon and return it as a URL.
*
* @param name base name of the icon to search for
* @param loader class loader to use or null to use the default class loader
* @return the URL where the icon was found
*/
public static URL lookupIconUrl(String name, ClassLoader loader) {
return ResourceLoader.lookupIconUrl(name, loader);
}
/**
* Find the path to a given icon and return it as a URL.
*
* @param name base name of the icon to search for
* @return the URL where the icon was found
*/
public static URL lookupIconUrl(String name) {
return lookupIconUrl(name, null);
}
}