/*****************************************************************************
* 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.helper;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.eclipse.draw2d.IFigure;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.edit.provider.IItemLabelProvider;
import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry;
import org.eclipse.gef.GraphicalEditPart;
import org.eclipse.gmf.runtime.draw2d.ui.figures.WrappingLabel;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.papyrus.infra.emf.appearance.helper.NameLabelIconHelper;
import org.eclipse.papyrus.uml.appearance.helper.AppliedStereotypeHelper;
import org.eclipse.papyrus.uml.appearance.helper.UMLVisualInformationPapyrusConstant;
import org.eclipse.papyrus.uml.diagram.common.Activator;
import org.eclipse.papyrus.uml.tools.utils.StereotypeUtil;
import org.eclipse.swt.graphics.Image;
import org.eclipse.uml2.uml.Element;
import org.eclipse.uml2.uml.NamedElement;
import org.eclipse.uml2.uml.Stereotype;
/**
* Helper class for labels for elements that can have stereotypes
*/
public abstract class StereotypedElementLabelHelper {
/**
* {@inheritDoc}
*/
public Element getUMLElement(GraphicalEditPart editPart) {
return (Element)((View)editPart.getModel()).getElement();
}
/**
* Parses the string containing the complete definition of properties to be
* displayed, and generates a map.
*
* @param editPart
* the edit part for which the label is edited
* @param stereotypesToDisplay
* the list of stereotypes to display
* @param stereotypesPropertiesToDisplay
* the properties of stereotypes to display
* @return a map. The keys are the name of displayed stereotypes, the
* corresponding data is a collection of its properties to be
* displayed
*/
protected Map<String, List<String>> parseStereotypeProperties(GraphicalEditPart editPart, String stereotypesToDisplay, String stereotypesPropertiesToDisplay) {
Map<String, List<String>> propertiesMap = new HashMap<String, List<String>>();
StringTokenizer stringTokenizer = new StringTokenizer(stereotypesPropertiesToDisplay, UMLVisualInformationPapyrusConstant.STEREOTYPE_PROPERTIES_LIST_SEPARATOR);
while(stringTokenizer.hasMoreTokens()) {
String propertyName = stringTokenizer.nextToken();
// retrieve the name of the stereotype for this property
String stereotypeName = propertyName.substring(0, propertyName.lastIndexOf(".")); // stereotypequalifiedName.propertyname
if(!propertiesMap.containsKey(stereotypeName)) {
List<String> propertiesForStereotype = new ArrayList<String>();
propertiesMap.put(stereotypeName, propertiesForStereotype);
}
propertiesMap.get(stereotypeName).add(propertyName.substring(propertyName.lastIndexOf(".") + 1, propertyName.length()));
}
return propertiesMap;
}
/**
* Returns the image to be displayed for the applied stereotypes.
*
* @return the image that represents the first applied stereotype or <code>null</code> if no image has to be displayed
*/
public Collection<Image> stereotypeIconsToDisplay(GraphicalEditPart editPart) {
String stereotypespresentationKind = AppliedStereotypeHelper.getAppliedStereotypePresentationKind((View)editPart.getModel());
if(stereotypespresentationKind == null) {
return null;
}
if(stereotypespresentationKind.equals(UMLVisualInformationPapyrusConstant.ICON_STEREOTYPE_PRESENTATION) || stereotypespresentationKind.equals(UMLVisualInformationPapyrusConstant.TEXT_ICON_STEREOTYPE_PRESENTATION)) {
// retrieve the first stereotype in the list of displayed stereotype
String stereotypesToDisplay = AppliedStereotypeHelper.getStereotypesToDisplay((View)editPart.getModel());
Collection<Stereotype> stereotypes = new ArrayList<Stereotype>();
StringTokenizer tokenizer = new StringTokenizer(stereotypesToDisplay, ",");
while(tokenizer.hasMoreTokens()) {
String firstStereotypeName = tokenizer.nextToken();
stereotypes.add(getUMLElement(editPart).getAppliedStereotype(firstStereotypeName));
}
return Activator.getIconElements(getUMLElement(editPart), stereotypes, false);
}
return new ArrayList<Image>();
}
/**
* Returns a String that displays stereotypes (using their simple name or
* their qualified name) and their properties
*
* @param editPart
* the edit part for which the label is edited
* @param separator
* the separator used to split the string representing the
* stereotypes.
* @param stereotypesToDisplay
* the list of stereotypes displayed
* @param stereotypeWithQualifiedName
* the list of stereotypes displayed using their qualified names
* @param stereotypesPropertiesToDisplay
* the list of properties to display
* @return a string that displays stereotypes (using their simple name or
* their qualified name) and their properties
*/
public String stereotypesAndPropertiesToDisplay(GraphicalEditPart editPart, String separator, String stereotypesToDisplay, String stereotypeWithQualifiedName, String stereotypesPropertiesToDisplay) {
// Get the preference from PreferenceStore. there should be an assert
final IPreferenceStore store = Activator.getDefault().getPreferenceStore();
assert store != null : "The preference store was not found";
if(store == null) {
return "";
}
// retrieve if the name of the stereotype has to put to lower case or
// not
String sNameAppearance = store.getString(UMLVisualInformationPapyrusConstant.P_STEREOTYPE_NAME_APPEARANCE);
// changes the string of properties into a map, where the entries of the
// map are the
// stereotype qualified name, and the properties to display are the data
Map<String, List<String>> propertiesToDisplay = parseStereotypeProperties(editPart, stereotypesToDisplay, stereotypesPropertiesToDisplay);
StringTokenizer strQualifiedName = new StringTokenizer(stereotypesToDisplay, ",");
String out = "";
while(strQualifiedName.hasMoreElements()) {
String currentStereotype = strQualifiedName.nextToken();
// check if current stereotype is applied
final Element umlElement = getUMLElement(editPart);
Stereotype stereotype = umlElement.getAppliedStereotype(currentStereotype);
if(stereotype != null) {
String name = currentStereotype;
if((stereotypeWithQualifiedName.indexOf(currentStereotype)) == -1) {
// property value contains qualifiedName ==> extract name
// from it
StringTokenizer strToken = new StringTokenizer(currentStereotype, "::");
while(strToken.hasMoreTokens()) {
name = strToken.nextToken();
}
}
// AL Changes Feb. 07 - Beg
// Handling STEREOTYPE_NAME_APPEARANCE preference (from
// ProfileApplicationPreferencePage)
// Previously lowercase forced onto first letter (standard UML)
// stereotypesToDisplay = stereotypesToDisplay+name.substring(0,
// 1).toLowerCase()+name.substring(1,
// name.length())+","+separator;
// check that the name has not already been added to the
// displayed string
if(sNameAppearance.equals(UMLVisualInformationPapyrusConstant.P_STEREOTYPE_NAME_DISPLAY_USER_CONTROLLED)) {
if(out.indexOf(name) == -1) {
out = out + Activator.ST_LEFT + name + Activator.ST_RIGHT + separator;
}
} else { // VisualInformationPapyrusConstants.P_STEREOTYPE_NAME_DISPLAY_UML_CONFORM))
// {
name = name.substring(0, 1).toLowerCase() + name.substring(1, name.length());
if(out.indexOf(name) == -1) {
out = out + Activator.ST_LEFT + name + Activator.ST_RIGHT + separator;
}
}
// now should add all properties associated to this stereotype
List<String> properties = propertiesToDisplay.get(stereotype.getQualifiedName());
if(properties != null) {
// retrieve property
for(String propertyName : properties) {
out = out + StereotypeUtil.displayPropertyValue(stereotype, StereotypeUtil.getPropertyByName(stereotype, propertyName), getUMLElement(editPart), " ");
}
}
}
}
if(out.endsWith(",")) {
return out.substring(0, out.length() - 1);
}
if(out.endsWith(separator)) {
return out.substring(0, out.length() - separator.length());
}
return out;
}
/**
* get the list of stereotype to display from the eannotation
*
* @return the list of stereotypes to display
*/
public String stereotypesToDisplay(GraphicalEditPart editPart) {
View view = (View)editPart.getModel();
// retrieve all stereotypes to be displayed
// try to display stereotype properties
String stereotypesPropertiesToDisplay = AppliedStereotypeHelper.getAppliedStereotypesPropertiesToDisplay(view);
String stereotypesToDisplay = AppliedStereotypeHelper.getStereotypesToDisplay(view);
String stereotypespresentationKind = AppliedStereotypeHelper.getAppliedStereotypePresentationKind(view);
// now check presentation.
// if horizontal => equivalent to the inBrace visualization in nodes
// (i.e. only name =
// value, separator = comma, delimited with brace
// if vertical => equivalent to compartment visualization name of
// stereotype, NL, property =
// value, NL, etC.
// check the presentation kind. if only icon => do not display
// stereotype, only values
if(UMLVisualInformationPapyrusConstant.ICON_STEREOTYPE_PRESENTATION.equals(stereotypespresentationKind)) {
return StereotypeUtil.getPropertiesValuesInBrace(stereotypesPropertiesToDisplay, getUMLElement(editPart));
}
String stereotypesToDisplayWithQN = AppliedStereotypeHelper.getStereotypesQNToDisplay(view);
String display = "";
if(UMLVisualInformationPapyrusConstant.STEREOTYPE_TEXT_VERTICAL_PRESENTATION.equals(stereotypespresentationKind)) {
display += stereotypesAndPropertiesToDisplay(editPart, "\n", stereotypesToDisplay, stereotypesToDisplayWithQN, stereotypesPropertiesToDisplay);
} else {
final String st = stereotypesToDisplay(editPart, ", ", stereotypesToDisplay, stereotypesToDisplayWithQN);
if(st != null && !st.equals("")) {
display += Activator.ST_LEFT + st + Activator.ST_RIGHT + " ";
}
final String propSt = StereotypeUtil.getPropertiesValuesInBrace(stereotypesPropertiesToDisplay, getUMLElement(editPart));
if(propSt != null && !propSt.equals("")) {
if(st != null && !st.equals("")) {
// display += "\n";
}
display += "{" + propSt + "} ";
}
}
return display;
}
/**
* Computes the string that displays the stereotypes for the current element
*
* @param separator
* the separator used to split the string representing the
* stereotypes.
* @param stereotypesToDisplay
* the list of stereotypes displayed
* @param stereotypeWithQualifiedName
* the list of stereotypes displayed using their qualified names
* @return the string that represent the stereotypes
*/
public String stereotypesToDisplay(GraphicalEditPart editPart, String separator, String stereotypesToDisplay, String stereotypeWithQualifiedName) {
// AL Changes Feb. 07 - Beg
// Style Handling for STEREOTYPE_NAME_APPEARANCE from
// ProfileApplicationPreferencePage
// Stereotype displayed according to UML standard (first letter forced
// to lower case) -
// default -
// or kept as entered by user (user controlled)
// Get the preference from PreferenceStore. there should be an assert
final IPreferenceStore store = Activator.getDefault().getPreferenceStore();
assert store != null : "The preference store was not found";
if(store == null) {
return "";
}
String sNameAppearance = store.getString(UMLVisualInformationPapyrusConstant.P_STEREOTYPE_NAME_APPEARANCE);
StringTokenizer strQualifiedName = new StringTokenizer(stereotypesToDisplay, ",");
String out = "";
while(strQualifiedName.hasMoreElements()) {
String currentStereotype = strQualifiedName.nextToken();
// check if current stereotype is applied
final Element umlElement = getUMLElement(editPart);
Stereotype stereotype = umlElement.getAppliedStereotype(currentStereotype);
if(stereotype != null) {
String name = currentStereotype;
if((stereotypeWithQualifiedName.indexOf(currentStereotype)) == -1) {
// property value contains qualifiedName ==> extract name
// from it
StringTokenizer strToken = new StringTokenizer(currentStereotype, "::");
while(strToken.hasMoreTokens()) {
name = strToken.nextToken();
}
}
// AL Changes Feb. 07 - Beg
// Handling STEREOTYPE_NAME_APPEARANCE preference (from
// ProfileApplicationPreferencePage)
// Previously lowercase forced onto first letter (standard UML)
// stereotypesToDisplay = stereotypesToDisplay+name.substring(0,
// 1).toLowerCase()+name.substring(1,
// name.length())+","+separator;
// check that the name has not already been added to the
// displayed string
if(sNameAppearance.equals(UMLVisualInformationPapyrusConstant.P_STEREOTYPE_NAME_DISPLAY_USER_CONTROLLED)) {
if(out.indexOf(name) == -1) {
out = out + name + separator;
}
} else { // VisualInformationPapyrusConstants.P_STEREOTYPE_NAME_DISPLAY_UML_CONFORM))
// {
name = name.substring(0, 1).toLowerCase() + name.substring(1, name.length());
if(out.indexOf(name) == -1) {
out = out + name + separator;
}
}
}
}
if(out.endsWith(",")) {
return out.substring(0, out.length() - 1);
}
if(out.endsWith(separator)) {
return out.substring(0, out.length() - separator.length());
}
return out;
}
/**
* Refreshes the label of the figure associated to the specified edit part
*
* @param editPart
* the edit part managing the refreshed figure
*/
public void refreshEditPartDisplay(GraphicalEditPart editPart) {
IFigure figure = editPart.getFigure();
// computes the icon to be displayed
final Collection<Image> imageToDisplay = stereotypeIconsToDisplay(editPart);
// should check if edit part has to display the element icon or not
if(NameLabelIconHelper.showLabelIcon((View)editPart.getModel())) {
imageToDisplay.add(getImage(editPart));
}
// for each element in the list of stereotype icon, adds it to the icons
// list of the
// wrapping label
// problem (RS - CEA LIST): more icons were displayed before refresh:
// has to clean
// problem 2 (RS - CEA LIST): no method to know how many icons were
// displayed => should fix
// a max number ?!
// solution: set all images to null, and then add the correct icons
int i = 0;
while(((WrappingLabel)figure).getIcon(i) != null) {
((WrappingLabel)figure).setIcon(null, i);
i++;
}
i = 0;
for(Image image : imageToDisplay) {
((WrappingLabel)figure).setIcon(image, i);
i++;
}
((WrappingLabel)figure).setText(labelToDisplay(editPart));
}
/**
* Computes the label to be displayed for the property
*/
protected String labelToDisplay(GraphicalEditPart editPart) {
StringBuffer buffer = new StringBuffer();
// computes the label for the stereotype (horizontal presentation)
buffer.append(stereotypesToDisplay(editPart));
// computes the string label to be displayed
buffer.append(elementLabel(editPart));
// buffer.append(PropertyUtil.getCustomLabel(getUMLElement(), 0));
return buffer.toString();
}
/**
* Computes the label corresponding to the semantic element
*
* @param editPart
* the graphical part managing the semantic element
* @return the string corresponding to the display of the semantic element
*/
protected abstract String elementLabel(GraphicalEditPart editPart);
/**
* Returns the image for the element
*
* @param editPart
* the edit part that displays the element
* @return the image
*/
public Image getImage(GraphicalEditPart editPart) {
Element element = getUMLElement(editPart);
String key = "";
if(element instanceof NamedElement) {
key = ((NamedElement)element).getName() + "::" + ((NamedElement)element).getVisibility();
} else if(element != null) {
key = element.getClass().getName();
}
ImageRegistry imageRegistry = Activator.getDefault().getImageRegistry();
Image image = imageRegistry.get(key);
ImageDescriptor descriptor = null;
if(image == null) {
AdapterFactory factory = Activator.getDefault().getItemProvidersAdapterFactory();
IItemLabelProvider labelProvider = (IItemLabelProvider)factory.adapt(getUMLElement(editPart), IItemLabelProvider.class);
if(labelProvider != null) {
descriptor = ExtendedImageRegistry.getInstance().getImageDescriptor(labelProvider.getImage(getUMLElement(editPart)));
}
if(descriptor == null) {
descriptor = ImageDescriptor.getMissingImageDescriptor();
}
imageRegistry.put(key, descriptor);
image = imageRegistry.get(key);
}
return image;
}
}