/*****************************************************************************
* Copyright (c) 2009 CEA LIST.
*
* 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:
* Remi Schnekenburger (CEA LIST) remi.schnekenburger@cea.fr - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.common.service;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.eclipse.gef.palette.CombinedTemplateCreationEntry;
import org.eclipse.gef.palette.PaletteContainer;
import org.eclipse.gef.palette.PaletteDrawer;
import org.eclipse.gef.palette.PaletteEntry;
import org.eclipse.gef.palette.PaletteRoot;
import org.eclipse.gef.palette.PaletteSeparator;
import org.eclipse.gef.palette.PaletteStack;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.papyrus.uml.diagram.common.Activator;
import org.w3c.dom.Node;
/**
* Standard implementation of the palette factory. This one should be use to
* provide palette content
*/
public class XMLDefinitionPaletteFactory extends AbstractXMLDefinitionPaletteFactory implements IPapyrusPaletteConstant {
/** palette root for the palette to be built */
protected PaletteRoot root;
/** map of predefined entries */
protected Map<String, PaletteEntry> predefinedEntries;
/**
* Creates a new XMLDefinitionPaletteFactory
*
* @param root
* the palette root to fill
* @param predefinedEntries
* existing predefined entries
*/
public XMLDefinitionPaletteFactory(PaletteRoot root, Map<String, PaletteEntry> predefinedEntries) {
this.root = root;
this.predefinedEntries = predefinedEntries;
}
/**
* {@inheritDoc}
*/
@Override
public void traverseContentNode(Node node) {
// nothing to do here
}
/**
* {@inheritDoc}
*/
@Override
public void traverseDrawerNode(Node node) {
String id = node.getAttributes().getNamedItem(ID).getNodeValue();
PaletteEntry entry = predefinedEntries.get(id);
if(entry == null) {
String name = node.getAttributes().getNamedItem(NAME).getNodeValue();
String iconPath = node.getAttributes().getNamedItem(ICON_PATH).getNodeValue();
entry = new PaletteDrawer(name);
entry.setId(id);
entry.setDescription("Drawer " + name);
if(iconPath != null && !iconPath.equals("")) {
entry.setSmallIcon(Activator.getImageDescriptor(iconPath));
entry.setLargeIcon(Activator.getImageDescriptor(iconPath));
}
predefinedEntries.put(id, entry);
}
appendPaletteEntry(root, predefinedEntries, computePath(node), entry);
}
/**
* returns the path for the given
*
* @param node
* the node for which the path is computed
* @return the path to this element
*/
protected String computePath(Node node) {
String path = "/";
Node parentNode = node;
while(parentNode.getParentNode() != null && !parentNode.getParentNode().getNodeName().equals(CONTENT)) {
parentNode = parentNode.getParentNode();
path = "/" + parentNode.getAttributes().getNamedItem(ID).getNodeValue() + path;
}
return path;
}
/**
* {@inheritDoc}
*/
@Override
public void traverseSeparatorNode(Node node) {
String id = node.getAttributes().getNamedItem(ID).getNodeValue();
PaletteEntry entry = predefinedEntries.get(id);
if(entry == null) {
entry = new PaletteSeparator(id);
predefinedEntries.put(id, entry);
}
appendPaletteEntry(root, predefinedEntries, computePath(node), entry);
}
/**
* {@inheritDoc}
*/
@Override
public void traverseStackNode(Node node) {
String id = node.getAttributes().getNamedItem(ID).getNodeValue();
PaletteEntry entry = predefinedEntries.get(id);
if(entry == null) {
// everything can be null for the constructor
entry = new PaletteStack(null, null, null);
entry.setId(id);
predefinedEntries.put(id, entry);
}
appendPaletteEntry(root, predefinedEntries, computePath(node), entry);
}
/**
* {@inheritDoc}
*/
@Override
public void traverseToolEntryNode(Node node) {
String id = node.getAttributes().getNamedItem(ID).getNodeValue();
PaletteEntry entry = predefinedEntries.get(id);
appendPaletteEntry(root, predefinedEntries, computePath(node), entry);
}
/**
* {@inheritDoc}
*/
@Override
public void traverseAspectToolEntryNode(Node node) {
final String id = node.getAttributes().getNamedItem(ID).getNodeValue();
final String refToolID = node.getAttributes().getNamedItem(REF_TOOL_ID).getNodeValue();
Node nameNode = node.getAttributes().getNamedItem(NAME);
Node descNode = node.getAttributes().getNamedItem(DESCRIPTION);
Node iconPathNode = node.getAttributes().getNamedItem(ICON_PATH);
final Map<Object, Object> properties = new HashMap<Object, Object>();
if(node.getChildNodes().getLength() > 0) {
properties.put(ASPECT_ACTION_KEY, node.getChildNodes());
}
final CombinedTemplateCreationEntry entry = (CombinedTemplateCreationEntry)predefinedEntries.get(refToolID);
if(entry == null) {
Activator.log.error("could not find entry " + refToolID, null);
return;
}
ImageDescriptor iconDesc = null;
String name = null;
String desc = null;
if(iconPathNode != null) {
iconDesc = Activator.getImageDescriptor(iconPathNode.getNodeValue());
} else {
iconDesc = entry.getSmallIcon();
}
if(nameNode != null) {
name = nameNode.getNodeValue();
} else {
name = entry.getLabel();
}
if(descNode != null) {
desc = descNode.getNodeValue();
} else {
desc = entry.getDescription();
}
CombinedTemplateCreationEntry realEntry = new AspectCreationEntry(name, desc, id, iconDesc, entry, properties);
predefinedEntries.put(id, realEntry);
appendPaletteEntry(root, predefinedEntries, computePath(node), realEntry);
}
/**
* Appends the given palette entry to the appropriate location in either a
* predefined palette entry or the palette root.
*
* @param root
* @param predefinedEntries
* map of predefined palette entries where the key is the palette
* entry id and the value is the palette entry
* @param path
* @param paletteEntry
*/
private static void appendPaletteEntry(PaletteRoot root, Map predefinedEntries, String path, PaletteEntry paletteEntry) {
PaletteEntry fEntry = findPaletteEntry(root, path);
if(fEntry == null) {
fEntry = findPredefinedEntry(predefinedEntries, path);
}
if(fEntry == null) {
Activator.log.error("Invalid palette entry path: " + path, null);
} else if(fEntry instanceof PaletteContainer) {
// remove if it already exists
if(!((PaletteContainer)fEntry).getChildren().contains(paletteEntry)) {
((PaletteContainer)fEntry).add(paletteEntry);
}
} else if(fEntry instanceof PaletteSeparator) {
appendTo((PaletteSeparator)fEntry, paletteEntry);
} else
fEntry.getParent().add(fEntry.getParent().getChildren().indexOf(fEntry) + 1, paletteEntry);
}
/**
* Finds a palette container starting from the given root and using the
* given path
*
* @param root
* @param aPath
* @return the container or <code>null</code> if not found
*/
private static PaletteEntry findPaletteEntry(PaletteEntry root, String aPath) {
StringTokenizer tokens = new StringTokenizer(aPath, "/"); //$NON-NLS-1$
while(tokens.hasMoreElements()) {
if(root instanceof PaletteContainer)
root = findChildPaletteEntry((PaletteContainer)root, tokens.nextToken());
else
return null;
}
return root;
}
/**
* Finds a palette entry starting from the given container and using the
* given path
*
* @param root
* @param path
* @return the entry or <code>null</code> if not found
*/
private static PaletteEntry findChildPaletteEntry(PaletteContainer container, String childId) {
Iterator entries = container.getChildren().iterator();
while(entries.hasNext()) {
PaletteEntry entry = (PaletteEntry)entries.next();
if(entry.getId().equals(childId))
return entry;
}
return null;
}
/**
* Searches the predefined entries for a palette entry given the full path
* as it was predefined.
*
* @param predefinedEntries
* map of predefined palette entries where the key is the palette
* entry id and the value is the palette entry
* @param path
* the path to the palette entry starting as it was predefined
* @return the palette entry if one exists; null otherwise.
*/
private static PaletteEntry findPredefinedEntry(Map predefinedEntries, String path) {
StringTokenizer tokens = new StringTokenizer(path, "/"); //$NON-NLS-1$
PaletteEntry root = (PaletteEntry)predefinedEntries.get(tokens.nextToken());
while(tokens.hasMoreElements()) {
if(root instanceof PaletteContainer)
root = findChildPaletteEntry((PaletteContainer)root, tokens.nextToken());
else
return null;
}
return root;
}
/**
* Appends the given entry to the end of the group of the given separator.
*
* @param separator
* @param entry
*/
private static void appendTo(PaletteSeparator separator, PaletteEntry entry) {
List children = separator.getParent().getChildren();
int index = children.indexOf(separator);
for(index++; index < children.size(); index++) {
if(children.get(index) instanceof PaletteSeparator)
break;
}
separator.getParent().add(index, entry);
}
}