/***************************************************************************** * Copyright (c) 2010 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.palette; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Status; import org.eclipse.emf.transaction.RecordingCommand; import org.eclipse.emf.transaction.Transaction; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.emf.workspace.AbstractEMFOperation; import org.eclipse.gef.EditPart; import org.eclipse.gef.EditPartViewer; import org.eclipse.gmf.runtime.common.core.command.CompositeCommand; import org.eclipse.gmf.runtime.common.core.util.StringStatics; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramGraphicalViewer; import org.eclipse.gmf.runtime.diagram.ui.util.EditPartUtil; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.ColumnViewer; import org.eclipse.jface.viewers.ComboBoxCellEditor; import org.eclipse.jface.viewers.EditingSupport; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.Viewer; import org.eclipse.papyrus.commands.wrappers.EMFtoGMFCommandWrapper; import org.eclipse.papyrus.uml.appearance.helper.AppliedStereotypeHelper; import org.eclipse.papyrus.uml.diagram.common.Activator; import org.eclipse.papyrus.uml.diagram.common.service.IPapyrusPaletteConstant; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Table; import org.eclipse.uml2.uml.Profile; import org.eclipse.uml2.uml.Stereotype; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Post action that manages the display of applied stereotypes. */ public class DisplayAppliedStereotypePostAction extends GraphicalPostAction { /** list of stereotypes to display with their names */ protected List<String> stereotypesToDisplay = new ArrayList<String>(); /** list of stereotypes to display with their qualified names */ protected List<String> stereotypesQNToDisplay = new ArrayList<String>(); /** entry proxy "parent" of this action when configuring the action */ protected IPaletteEntryProxy entryProxy; /** list of applied profiles */ protected List<Profile> appliedProfiles; /** add icon path */ protected static final String ICONS_ADD = "/icons/obj16/Add_16x16.gif"; //$NON-NLS-1$ /** remove icon path */ protected static final String ICONS_REMOVE = "/icons/delete.gif"; //$NON-NLS-1$ /** TableViewer that shows the stereotypes to display */ private TableViewer stereotypesToShowTableViewer; /** HashMap of displayable Stereotypes */ protected HashMap<String, Integer> listOfDisplayableStereotypes = new HashMap<String, Integer>(); /** Constants for the display options */ private final int DONT_DISPLAY = 0; private final int DISPLAY_SIMPLE_NAME = 1; private final int DISPLAY_QUALIFIED_NAME = 2; /** The display options */ private String[] diplayOptions = { "Do not display", "Display the stereotype", "Display qualified name of the stereotype" }; /** * @{inheritDoc */ @Override public void init(Node configurationNode, IAspectActionProvider factory) { super.init(configurationNode, factory); if(configurationNode == null) { return; } NodeList childNodes = configurationNode.getChildNodes(); for(int i = 0; i < childNodes.getLength(); i++) { String nodeName = childNodes.item(i).getNodeName(); if("displayName".equals(nodeName)) { Node stereotypeNameNode = childNodes.item(i).getAttributes().getNamedItem(IPapyrusPaletteConstant.NAME); if(stereotypeNameNode != null) { stereotypesToDisplay.add(stereotypeNameNode.getNodeValue()); } } else if("displayQualifiedName".equals(nodeName)) { Node stereotypeNameNode = childNodes.item(i).getAttributes().getNamedItem(IPapyrusPaletteConstant.NAME); if(stereotypeNameNode != null) { stereotypesQNToDisplay.add(stereotypeNameNode.getNodeValue()); } } } } /** * @{inheritDoc */ @Override public void save(Node parentNode) { for(String stereotypeName : listOfDisplayableStereotypes.keySet()) { switch(listOfDisplayableStereotypes.get(stereotypeName)) { case DISPLAY_SIMPLE_NAME: Element displayName = ((Element)parentNode).getOwnerDocument().createElement("displayName"); displayName.setAttribute(IPapyrusPaletteConstant.NAME, stereotypeName); ((Element)parentNode).appendChild(displayName); break; case DISPLAY_QUALIFIED_NAME: Element displayQualifiedName = ((Element)parentNode).getOwnerDocument().createElement("displayQualifiedName"); displayQualifiedName.setAttribute(IPapyrusPaletteConstant.NAME, stereotypeName); ((Element)parentNode).appendChild(displayQualifiedName); break; default: break; } } } /** * @{inheritDoc */ @Override public void run(EditPart editPart) { final CompositeCommand compositeCommand = new CompositeCommand("Modify Stereotype Display"); View view = (View)editPart.getModel(); TransactionalEditingDomain editingDomain = org.eclipse.papyrus.infra.core.utils.EditorUtils.getTransactionalEditingDomain(); // creates the commands to display simple stereotypes name for(String stereotypeName : stereotypesToDisplay) { String presentationKind = AppliedStereotypeHelper.getAppliedStereotypePresentationKind(view); RecordingCommand command = AppliedStereotypeHelper.getAddAppliedStereotypeCommand(editingDomain, view, stereotypeName, presentationKind); compositeCommand.add(new EMFtoGMFCommandWrapper(command)); } // creates the commands to display qualified names of stereotypes for(String stereotypeName : stereotypesQNToDisplay) { RecordingCommand command = AppliedStereotypeHelper.getAddAppliedStereotypeToDisplayWithQNCommand(editingDomain, view, stereotypeName); compositeCommand.add(new EMFtoGMFCommandWrapper(command)); } org.eclipse.uml2.uml.Element element = (org.eclipse.uml2.uml.Element)((View)editPart.getModel()).getElement(); for(Stereotype stereo : element.getAppliedStereotypes()) { if(!stereotypesQNToDisplay.contains(stereo.getQualifiedName()) && !stereotypesToDisplay.contains(stereo.getQualifiedName())) { String presentationKind = AppliedStereotypeHelper.getAppliedStereotypePresentationKind(view); RecordingCommand command = AppliedStereotypeHelper.getRemoveAppliedStereotypeCommand(editingDomain, view, stereo.getQualifiedName(), presentationKind); compositeCommand.add(new EMFtoGMFCommandWrapper(command)); } } compositeCommand.reduce(); // AppliedStereotypeHelper.ge if(compositeCommand.canExecute()) { boolean isActivating = true; Map<String, Boolean> options = null; // use the viewer to determine if we are still initializing the // diagram // do not use the DiagramEditPart.isActivating since // ConnectionEditPart's // parent will not be a diagram edit part EditPartViewer viewer = editPart.getViewer(); if(viewer instanceof DiagramGraphicalViewer) { isActivating = ((DiagramGraphicalViewer)viewer).isInitializing(); } if(isActivating || !EditPartUtil.isWriteTransactionInProgress((IGraphicalEditPart)editPart, false, false)) { options = Collections.singletonMap(Transaction.OPTION_UNPROTECTED, Boolean.TRUE); } AbstractEMFOperation operation = new AbstractEMFOperation(((IGraphicalEditPart)editPart).getEditingDomain(), StringStatics.BLANK, options) { @Override protected IStatus doExecute(IProgressMonitor monitor, IAdaptable info) throws ExecutionException { compositeCommand.execute(monitor, info); return Status.OK_STATUS; } }; try { operation.execute(new NullProgressMonitor(), null); } catch (ExecutionException e) { Activator.log.error(e); } } else { Activator.log.error("Impossible to execute graphical post action " + propertiesToUpdate, null); } } /** * @{inheritDoc */ @Override public Control createConfigurationComposite(Composite parent, IPaletteEntryProxy entryProxy, List<Profile> appliedProfiles) { this.appliedProfiles = appliedProfiles; this.entryProxy = entryProxy; // retrieve displayable stereotypes if(entryProxy instanceof IPaletteAspectToolEntryProxy) { for(IPostAction postAction : ((IPaletteAspectToolEntryProxy)entryProxy).getPostActions()) { if(postAction instanceof StereotypePostAction) { for(String stereotype : ((StereotypePostAction)postAction).getStereotypesToApply()) { if(!listOfDisplayableStereotypes.containsKey(stereotype)) { listOfDisplayableStereotypes.put(stereotype, DONT_DISPLAY); } } } } } // Load from config for(String stereotypeName : stereotypesToDisplay) { if(listOfDisplayableStereotypes.containsKey(stereotypeName)) { listOfDisplayableStereotypes.put(stereotypeName, DISPLAY_SIMPLE_NAME); } } for(String stereotypeName : stereotypesQNToDisplay) { if(listOfDisplayableStereotypes.containsKey(stereotypeName)) { listOfDisplayableStereotypes.put(stereotypeName, DISPLAY_QUALIFIED_NAME); } } Composite composite = new Composite(parent, SWT.BORDER); composite.setLayout(new GridLayout(1, false)); Label label = new Label(composite, SWT.None); label.setText("Choose applied stereotypes to display : "); GridData data = new GridData(SWT.FILL, SWT.CENTER, true, false); label.setLayoutData(data); stereotypesToShowTableViewer = new TableViewer(composite, SWT.FULL_SELECTION); GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true); stereotypesToShowTableViewer.getControl().setLayoutData(layoutData); createColumns(stereotypesToShowTableViewer); stereotypesToShowTableViewer.setContentProvider(new IStructuredContentProvider() { public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { // TODO Auto-generated method stub } public void dispose() { // TODO Auto-generated method stub } @SuppressWarnings("unchecked") public Object[] getElements(Object inputElement) { if(inputElement instanceof HashMap<?, ?>) { return ((HashMap<String, Integer>)inputElement).keySet().toArray(); } return null; } }); stereotypesToShowTableViewer.setLabelProvider(new StereotypeToDisplayLabelProvider()); stereotypesToShowTableViewer.setInput(listOfDisplayableStereotypes); return composite; } /** * The label provider for the tableviewer : one columns shows the stereotype * name and the other shows the display option */ class StereotypeToDisplayLabelProvider extends LabelProvider implements ITableLabelProvider { public Image getColumnImage(Object element, int columnIndex) { return null; } public String getColumnText(Object element, int columnIndex) { switch(columnIndex) { case 0: return (String)element; case 1: return diplayOptions[listOfDisplayableStereotypes.get(element)]; default: break; } return null; } } /** * EditingSupport for the display option : combo editor */ class StereotypeToDisplayEditingSupport extends EditingSupport { private CellEditor editor; public StereotypeToDisplayEditingSupport(ColumnViewer viewer) { super(viewer); editor = new ComboBoxCellEditor(((TableViewer)viewer).getTable(), diplayOptions); } @Override protected CellEditor getCellEditor(Object element) { return editor; } @Override protected boolean canEdit(Object element) { return true; } @Override protected Object getValue(Object element) { return listOfDisplayableStereotypes.get(element); } @Override protected void setValue(Object element, Object value) { listOfDisplayableStereotypes.put((String)element, (Integer)value); getViewer().update(element, null); } } /** * Creates appropriate columns : one for the stereotype and one for its * display options * * @param viewer * the table to create the columns in */ protected void createColumns(TableViewer viewer) { TableViewerColumn columnStereotype = new TableViewerColumn(viewer, SWT.NONE); columnStereotype.getColumn().setText("Stereotype"); columnStereotype.getColumn().setWidth(300); columnStereotype.getColumn().setResizable(true); columnStereotype.getColumn().setMoveable(false); TableViewerColumn columnDisplay = new TableViewerColumn(viewer, SWT.NONE); columnDisplay.getColumn().setText("Display"); columnDisplay.getColumn().setWidth(300); columnDisplay.getColumn().setResizable(true); columnDisplay.getColumn().setMoveable(false); // enable editing support columnDisplay.setEditingSupport(new StereotypeToDisplayEditingSupport(viewer)); Table table = viewer.getTable(); table.setHeaderVisible(true); table.setLinesVisible(true); } }