/*****************************************************************************
* 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.customization.palette.dialog;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
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.PaletteStack;
import org.eclipse.gef.palette.PaletteToolbar;
import org.eclipse.gef.palette.ToolEntry;
import org.eclipse.gef.ui.palette.PaletteCustomizer;
import org.eclipse.gmf.runtime.common.core.service.ProviderPriority;
import org.eclipse.gmf.runtime.diagram.ui.parts.DiagramEditorWithFlyOutPalette;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.util.LocalSelectionTransfer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.papyrus.customization.palette.proxies.XMLDefinitionPaletteProxyFactory;
import org.eclipse.papyrus.uml.diagram.common.Activator;
import org.eclipse.papyrus.uml.diagram.common.Messages;
import org.eclipse.papyrus.uml.diagram.common.part.PaletteUtil;
import org.eclipse.papyrus.uml.diagram.common.part.PapyrusPalettePreferences;
import org.eclipse.papyrus.uml.diagram.common.service.AspectCreationEntry;
import org.eclipse.papyrus.uml.diagram.common.service.IPapyrusPaletteConstant;
import org.eclipse.papyrus.uml.diagram.common.service.PapyrusPaletteService;
import org.eclipse.papyrus.uml.diagram.common.service.XMLDefinitionPaletteParser;
import org.eclipse.papyrus.uml.diagram.common.service.palette.IAspectAction;
import org.eclipse.papyrus.uml.diagram.common.service.palette.StereotypeAspectActionProvider;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TreeDropTargetEffect;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IEditorPart;
import org.eclipse.uml2.uml.Class;
import org.eclipse.uml2.uml.Package;
import org.eclipse.uml2.uml.Profile;
import org.eclipse.uml2.uml.Stereotype;
import org.eclipse.uml2.uml.UMLPackage;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
/**
* Wizard page for information about the new local palette definition
*/
public class LocalPaletteContentPage extends WizardPage implements Listener {
/** editor part in which the palette is created */
protected IEditorPart editorPart;
/** available tools viewer */
protected TreeViewer availableToolsViewer;
/** label provider for the tree viewer */
protected PaletteLabelProvider paletteLabelProvider;
/** icon path when tools are hidden */
protected static final String HIDDEN_TOOLS_ICON = "/icons/tools_hidden.gif";
/** icon path when tools are shown */
protected static final String SHOWN_TOOLS_ICON = "/icons/tools_shown.gif";
/** path to the icon */
protected static final String WIZARD_ICON = "/icons/local_desc_wiz.png";
/** icon path when drawers are hidden */
protected static final String SHOWN_DRAWERS_ICON = "/icons/drawers_shown.gif";
/** icon path when drawers are shown */
protected static final String HIDDEN_DRAWERS_ICON = "/icons/drawers_hidden.gif";
/** icon path for the add button */
protected static final String ADD_ICON = "/icons/arrow_right.gif";
/** icon path for the remove button */
protected static final String REMOVE_ICON = "/icons/arrow_left.gif";
/** icon path for the delete button */
protected static final String DELETE_ICON = "/icons/delete.gif";
/** icon path for the create drawer button */
protected static final String CREATE_DRAWERS_ICON = "/icons/new_drawer.gif";
/** icon path for the create separator button */
protected String CREATE_SEPARATOR_ICON = "/icons/separator.gif";
/** icon path for the create stack button */
protected String CREATE_STACK_ICON = "/icons/stack.gif";
/** icon path for the delete drawer button */
protected static final String DELETE_DRAWERS_ICON = "/icons/delete.gif";
/** icon for the content provider switch button */
protected String SWITCH_CONTENT_PROVIDER_ICON = "/icons/switch_provider.gif";
/** label for the standard tools */
protected static final String UML_TOOLS_LABEL = "UML tools";
/** icon path for the edit drawer button */
protected static final String EDIT_ICON = "/icons/obj16/file.gif";
/** instance of the filter used to show/hide drawers */
protected final ViewerFilter drawerFilter = new DrawerFilter();
/** instance of the filter used to show/hide tools */
protected final ViewerFilter toolFilter = new ToolFilter();
/** stored preferences */
protected List<String> storedPreferences;
/** add button */
protected Button addButton;
/** remove button */
protected Button removeButton;
/** tree viewer for the new palette */
protected TreeViewer paletteTreeViewer;
/** document for element creation */
protected Document document;
/** content node for the palette viewer */
protected PaletteContainerProxy contentNode;
/** combo to select which profile tools should be visible */
protected Combo profileCombo;
/** list of profiles that can provide tools */
protected List<String> profileComboList = new ArrayList<String>();
/** tool item in charge of toggling content providers in the available tool viewer */
protected ToolItem toggleContentProvider;
/** required profile by this palette */
protected Set<String> requiredProfiles;
/** palette customizer used for the palette */
protected PaletteCustomizer customizer;
/** current selected entry proxy */
protected PaletteEntryProxy selectedEntryProxy;
/** class in charge of the information composite */
protected PaletteEntryProxyInformationComposite informationComposite = new PaletteEntryProxyInformationComposite();
/** class in charge of the aspect tool information composite */
protected AspectActionsInformationComposite aspectActionComposite = new AspectActionsInformationComposite();
protected ToolBar toolbar;
/** validator key for toolbar items */
protected final static String VALIDATOR = "validator";
/** priority of the current edited palette */
protected ProviderPriority priority;
/**
* Creates a new wizard page with the given name, title, and image.
*
* @param part
* the editor part in which the wizard was created
*/
public LocalPaletteContentPage(IEditorPart part, PaletteCustomizer customizer) {
super(Messages.Local_Palette_ContentPage_Name, Messages.Local_Palette_ContentPage_Title, Activator.getImageDescriptor(WIZARD_ICON));
this.editorPart = part;
this.customizer = customizer;
}
/**
* {@inheritDoc}
*/
public void createControl(Composite parent) {
// initialize dialog units
initializeDialogUnits(parent);
// Create a new composite as there is the title bar seperator
// to deal with
Composite control = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(4, false);
control.setLayout(layout);
control.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
setControl(control);
// create Available Tools Group
createAvailableToolsGroup();
// create add/remove buttons
createAddRemoveButtons();
// create Palette Group
createPalettePreviewGroup();
// create tool description group (custom name, description, and perhaphs icon.... Just under this group, another one with aspect actions)
createToolDescriptionGroup();
// just under, creates a new line of composites...
createAspectActionComposite();
// add listeners inter-groups
ISelectionChangedListener listener = createToolsViewerSelectionChangeListener();
availableToolsViewer.addSelectionChangedListener(listener);
paletteTreeViewer.addSelectionChangedListener(listener);
// end of the control creation
Dialog.applyDialogFont(control);
validatePage();
// Show description on opening
setErrorMessage(null);
setMessage(null);
setControl(control);
}
/**
* Creates the composite group that presents information about ascpect actions for aspect tools
*/
protected void createAspectActionComposite() {
aspectActionComposite.createComposite((Composite)getControl(), getAllAppliedProfiles());
}
/**
* Creates the composite group that presents information about current selected tool
*/
protected void createToolDescriptionGroup() {
informationComposite.createComposite((Composite)getControl(), getAllAppliedProfiles());
}
/**
* update the preferences to have all tools accessible
*/
protected void updatePreferences() {
// change => set to no hidden palettes
storedPreferences = PapyrusPalettePreferences.getHiddenPalettes(editorPart);
// remove all, but should only remove visible palettes
for(String id : storedPreferences) {
PapyrusPalettePreferences.changePaletteVisibility(id, editorPart, true);
}
}
/**
* Restore preferences
*/
public void restorePreferences() {
// remove all, but should only remove visible palettes
for(String id : storedPreferences) {
PapyrusPalettePreferences.changePaletteVisibility(id, editorPart, false);
}
}
/**
* creates the palette preview group
*/
protected void createPalettePreviewGroup() {
Composite parent = (Composite)getControl();
Composite paletteComposite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(2, true);
layout.marginHeight = 0;
layout.marginWidth = 0;
paletteComposite.setLayout(layout);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
paletteComposite.setLayoutData(data);
Label label = new Label(paletteComposite, SWT.NONE);
label.setText(Messages.Local_Palette_Palette_Preview);
data = new GridData(SWT.LEFT, SWT.CENTER, true, false);
label.setLayoutData(data);
toolbar = new ToolBar(paletteComposite, SWT.HORIZONTAL);
data = new GridData(SWT.RIGHT, SWT.FILL, false, false);
toolbar.setLayoutData(data);
populatePalettePreviewToolBar(toolbar);
Tree tree = new Tree(paletteComposite, SWT.SINGLE | SWT.BORDER);
data = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1);
data.widthHint = 185;
// Make the tree this tall even when there is nothing in it. This will keep the
// dialog from shrinking to an unusually small size.
data.heightHint = 200;
tree.setLayoutData(data);
paletteTreeViewer = new TreeViewer(tree);
paletteTreeViewer.setContentProvider(new PaletteContentProvider(paletteTreeViewer));
paletteTreeViewer.setLabelProvider(new PaletteProxyLabelProvider());
paletteTreeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
handlePalettePreviewSelectionChanged(event);
}
});
addPalettePreviewDropSupport();
addPalettePreviewDragSupport();
addPalettePreviewEditSupport();
paletteTreeViewer.setInput(contentNode);
}
/**
* handle the selection change event for the palette preview
*
* @param event
* the event that is thrown by the palette viewer
*/
protected void handlePalettePreviewSelectionChanged(SelectionChangedEvent event) {
// retrieve current selection
ITreeSelection selection = (TreeSelection)event.getSelection();
Object firstSelected = selection.getFirstElement();
if(firstSelected instanceof PaletteEntryProxy) {
// update the current selected palette entry proxy
selectedEntryProxy = ((PaletteEntryProxy)firstSelected);
informationComposite.setSelectedEntryProxy(selectedEntryProxy);
aspectActionComposite.setSelectedEntryProxy(selectedEntryProxy);
}
// update toolbar
if(toolbar != null && !toolbar.isDisposed()) {
for(int i = 0; i < toolbar.getItemCount(); i++) {
ToolItem item = toolbar.getItem(i);
Object validator = item.getData(VALIDATOR);
if(validator instanceof ToolBarItemValidator) {
item.setEnabled(((ToolBarItemValidator)validator).isEnable());
}
}
}
}
/**
* @{inheritDoc
*/
@Override
public void dispose() {
super.dispose();
}
/**
* Adds the behavior for the double click strategy
*/
protected void addPalettePreviewEditSupport() {
paletteTreeViewer.addDoubleClickListener(new IDoubleClickListener() {
/**
* {@inheritDoc}
*/
public void doubleClick(DoubleClickEvent event) {
// retrieve current item double clicked...
ITreeSelection selection = (TreeSelection)event.getSelection();
Object firstSelected = selection.getFirstElement();
if(firstSelected instanceof PaletteLocalDrawerProxy) {
UpdateLocalDrawerWizard wizard = new UpdateLocalDrawerWizard(((PaletteLocalDrawerProxy)firstSelected).getParent(), (PaletteLocalDrawerProxy)firstSelected);
WizardDialog dialog = new WizardDialog(getShell(), wizard);
dialog.open();
//paletteTreeViewer.refresh();
}
}
});
}
/**
* Add drop behavior for the palette preview
*/
protected void addPalettePreviewDropSupport() {
// transfer types
Transfer[] transfers = new Transfer[]{ LocalSelectionTransfer.getTransfer() };
// drag listener
DropTargetListener listener = new TreeDropTargetEffect(paletteTreeViewer.getTree()) {
/**
* {@inheritDoc}
*/
@Override
public void drop(DropTargetEvent event) {
super.drop(event);
// create proxy and adds it to its target parent
PaletteEntryProxy target = (PaletteEntryProxy)((TreeItem)event.item).getData();
if(target == null) {
target = (PaletteContainerProxy)paletteTreeViewer.getInput();
}
// get the elements from the drag listener (either a palette entry or a palette
// entry proxy)
IStructuredSelection transferedSelection = (IStructuredSelection)LocalSelectionTransfer.getTransfer().nativeToJava(event.currentDataType);
Object entry = transferedSelection.getFirstElement();
// creates the proxy for the element to be dropped
PaletteEntryProxy entryProxy = createNodeFromEntry(entry);
if(entryProxy == null) {
return;
}
if(target instanceof PaletteContainerProxy) {
// tries to remove from its parent if possible
if(entryProxy.getParent() != null) {
entryProxy.getParent().removeChild(entryProxy);
}
((PaletteContainerProxy)target).addChild(entryProxy);
paletteTreeViewer.expandToLevel(target, 1);
} else if(target instanceof PaletteEntryProxy) {
// tries to remove from its parent if possible
if(entryProxy.getParent() != null) {
entryProxy.getParent().removeChild(entryProxy);
}
target.getParent().addChild(entryProxy, target);
paletteTreeViewer.expandToLevel(target.getParent(), 1);
} else {
// add to parent...
target.getParent().addChild(entryProxy);
paletteTreeViewer.expandToLevel(target.getParent(), TreeViewer.ALL_LEVELS);
}
setPageComplete(validatePage());
}
/**
* {@inheritDoc}
*/
@Override
public void dragOver(DropTargetEvent event) {
super.dragOver(event);
IStructuredSelection transferedSelection = (IStructuredSelection)LocalSelectionTransfer.getTransfer().nativeToJava(event.currentDataType);
// check selection is compatible for drop target
TreeItem item = paletteTreeViewer.getTree().getItem(paletteTreeViewer.getTree().toControl(new Point(event.x, event.y)));
checkSelectionForDrop(transferedSelection, item, event);
}
};
paletteTreeViewer.addDropSupport(DND.DROP_LINK | DND.DROP_MOVE, transfers, listener);
}
/**
* Adds drag ability to the palette preview composite
*/
protected void addPalettePreviewDragSupport() {
// transfer types
Transfer[] transfers = new Transfer[]{ LocalSelectionTransfer.getTransfer() };
// drag listener
DragSourceListener listener = new DragSourceAdapter() {
/**
* {@inheritDoc}
*/
@Override
public void dragStart(DragSourceEvent event) {
super.dragStart(event);
event.data = paletteTreeViewer.getSelection();
}
/**
* {@inheritDoc}
*/
@Override
public void dragSetData(DragSourceEvent event) {
super.dragSetData(event);
LocalSelectionTransfer.getTransfer().setSelection(paletteTreeViewer.getSelection());
}
};
paletteTreeViewer.addDragSupport(DND.DROP_MOVE, transfers, listener);
}
/**
* Checks if the selection can be added to the target widget
*
* @param transferedSelection
* the selection to be dropped
* @param widget
* the widget where to drop
* @return <code>true</code> if element can be dropped
*/
protected void checkSelectionForDrop(IStructuredSelection transferedSelection, TreeItem item, DropTargetEvent event) {
event.detail = DND.DROP_NONE;
Object entry = transferedSelection.getFirstElement();
// handle only first selected element
if(item == null) {
// adding to the root, should only be a drawer
if(entry instanceof PaletteDrawer) {
event.detail = DND.DROP_LINK;
}
} else {
PaletteEntryProxy targetProxy = (PaletteEntryProxy)item.getData();
switch(targetProxy.getType()) {
case DRAWER:
if(entry instanceof ToolEntry) {
event.detail = DND.DROP_LINK;
} else if(entry instanceof PaletteEntryProxy) {
event.detail = DND.DROP_MOVE;
}
break;
case STACK:
if(entry instanceof ToolEntry) {
event.detail = DND.DROP_LINK;
} else if(entry instanceof PaletteEntryProxy && !(entry instanceof PaletteLocalStackProxy)) {
event.detail = DND.DROP_MOVE;
}
break;
case TOOL:
if(entry instanceof ToolEntry) {
event.detail = DND.DROP_LINK; // add the selected tool before the destination
// tool
} else if(entry instanceof PaletteEntryProxy) {
event.detail = DND.DROP_MOVE; // moves the element before the entry
}
break;
case SEPARATOR:
if(entry instanceof PaletteEntryProxy) {
event.detail = DND.DROP_MOVE;
}
break;
default:
break;
}
}
}
/**
* Sets an empty content for the palette preview
*/
public void initializeContent() {
contentNode = new PaletteContainerProxy(null);
// adds a default local drawer
PaletteLocalDrawerProxy proxy = new PaletteLocalDrawerProxy("Default", generateID("Drawer_"), "/icons/drawer.gif", "Default Drawer");
contentNode.addChild(proxy);
setPageComplete(false);
}
/**
* Sets the initial content for the palette preview
*/
public void initializeContent(PapyrusPaletteService.LocalProviderDescriptor descriptor) {
// retrieve the xml definition file
String xmlPath = PapyrusPalettePreferences.getPalettePathFromID(descriptor.getContributionID());
// parse the content file
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
try {
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
// Bundle bundle = Platform.getBundle(pluginID);
// URL url = bundle.getEntry(path);
File file = Activator.getDefault().getStateLocation().append(xmlPath).toFile();
if(!file.exists()) {
Activator.log.error("Impossible to load file: " + file, null);
} else {
Document document = documentBuilder.parse(file);
Map<String, PaletteEntry> entries = PaletteUtil.getAvailableEntriesSet(editorPart, ProviderPriority.HIGHEST);
XMLDefinitionPaletteProxyFactory factory = new XMLDefinitionPaletteProxyFactory(entries);
XMLDefinitionPaletteParser parser = new XMLDefinitionPaletteParser(factory);
for(int i = 0; i < document.getChildNodes().getLength(); i++) {
Node node = document.getChildNodes().item(i);
if(IPapyrusPaletteConstant.PALETTE_DEFINITION.equals(node.getNodeName())) {
parser.parsePaletteDefinition(node);
}
}
contentNode = factory.getRootProxy();
// tells that the page can be closed directly without modifying the palette
setPageComplete(true);
return;
}
} catch (ParserConfigurationException e) {
Activator.log.error(e);
} catch (IOException e) {
Activator.log.error(e);
} catch (SAXException e) {
Activator.log.error(e);
}
// paletteTreeViewer.setInput(contentNode);
contentNode = new PaletteContainerProxy(null);
}
/**
* Saves the xml document into file
*
* @param document
* the document to save
* @param path
* name of the file
* @return the file created or updated
*/
protected File loadDocument(Document document, String path) {
File file = null;
try {
// create the file that stores the XML configuration
file = Activator.getDefault().getStateLocation().append(path).toFile();
Transformer aTransformer = TransformerFactory.newInstance().newTransformer();
Source src = new DOMSource(document);
Result dest = new StreamResult(file);
aTransformer.transform(src, dest);
} catch (TransformerConfigurationException e) {
Activator.log.error(e);
} catch (TransformerException e) {
Activator.log.error(e);
}
return file;
}
/**
* populates the preview palette toolbar
*
* @param toolbar
* the toolbar to populate
*/
protected void populatePalettePreviewToolBar(ToolBar toolbar) {
PaletteEntryProxySelectedValidator validator = new PaletteEntryProxySelectedValidator();
createToolBarItem(toolbar, DELETE_ICON, Messages.PapyrusPaletteCustomizerDialog_RemoveButtonTooltip, createRemoveElementListener(), validator);
createToolBarItem(toolbar, EDIT_ICON, Messages.PapyrusPaletteCustomizerDialog_EditButtonTooltip, createEditElementListener(), new EditElementToolBarItemValidator());
createToolBarItem(toolbar, CREATE_DRAWERS_ICON, Messages.Local_Palette_Create_Drawer_Tooltip, createNewDrawerListener(), null);
createToolBarItem(toolbar, CREATE_SEPARATOR_ICON, Messages.Local_Palette_Create_Separator_Tooltip, createNewSeparatorListener(), validator);
createToolBarItem(toolbar, CREATE_STACK_ICON, Messages.Local_Palette_Create_Stack_Tooltip, createNewStackListener(), validator);
}
/**
* Edits the current selected elements. This works for drawers, should work on more elements
*
* @return the listener for the edit button
*/
protected Listener createEditElementListener() {
return new Listener() {
/**
* {@inheritDoc}
*/
public void handleEvent(Event event) {
IStructuredSelection selection = (IStructuredSelection)paletteTreeViewer.getSelection();
if(selection == null || selection.size() < 1) {
return;
}
Object selected = selection.getFirstElement();
if(selected instanceof PaletteLocalDrawerProxy) {
UpdateLocalDrawerWizard wizard = new UpdateLocalDrawerWizard(((PaletteLocalDrawerProxy)selected).getParent(), (PaletteLocalDrawerProxy)selected);
WizardDialog dialog = new WizardDialog(getShell(), wizard);
dialog.open();
}
// paletteTreeViewer.refresh();
}
};
}
/**
* Creates the listener for the remove item(s) button
*
* @return the listener for the remove button
*/
protected Listener createRemoveElementListener() {
return new Listener() {
/**
* {@inheritDoc}
*/
public void handleEvent(Event event) {
IStructuredSelection selection = (IStructuredSelection)paletteTreeViewer.getSelection();
if(selection == null || selection.size() < 1) {
return;
}
Iterator<Object> it = selection.iterator();
while(it.hasNext()) {
Object o = it.next();
if(o instanceof PaletteEntryProxy) {
PaletteEntryProxy proxyToDelete = (PaletteEntryProxy)o;
// create a new entry in the document
// get container of the proxy to be deleted
PaletteContainerProxy parentProxy = proxyToDelete.getParent();
if(parentProxy != null) {
parentProxy.removeChild(proxyToDelete);
}
}
}
// paletteTreeViewer.refresh();
}
};
}
/**
* Creates the listener for the new drawer tool item
*
* @return the listener created
*/
protected Listener createNewDrawerListener() {
return new Listener() {
/**
* {@inheritDoc}
*/
public void handleEvent(Event event) {
// retrieve selected container
PaletteContainerProxy containerProxy;
containerProxy = (PaletteContainerProxy)paletteTreeViewer.getInput();
NewDrawerWizard wizard = new NewDrawerWizard(containerProxy);
WizardDialog wizardDialog = new WizardDialog(new Shell(), wizard);
wizardDialog.open();
// paletteTreeViewer.refresh();
setPageComplete(validatePage());
}
};
}
/**
* Creates the listener for the new stack tool item
*
* @return the listener created
*/
protected Listener createNewStackListener() {
return new Listener() {
/**
* {@inheritDoc}
*/
public void handleEvent(Event event) {
// retrieve selected element
Object object = ((IStructuredSelection)paletteTreeViewer.getSelection()).getFirstElement();
// if element = drawer => the new stack must be created at the end of the drawer's
// children list
// if element = tool => must be placed before this tool
// else : nothinng to do
if(object instanceof PaletteLocalDrawerProxy) {
String id = generateID("Stack");
PaletteLocalStackProxy proxy = new PaletteLocalStackProxy(id);
((PaletteLocalDrawerProxy)object).addChild(proxy);
} else if(object instanceof PaletteEntryProxy) {
String id = generateID("Stack");
PaletteLocalStackProxy proxy = new PaletteLocalStackProxy(id);
// retrieve parent
PaletteEntryProxy childProxy = (PaletteEntryProxy)object;
PaletteContainerProxy parentProxy = childProxy.getParent();
parentProxy.addChild(proxy, childProxy);
}
// paletteTreeViewer.refresh();
setPageComplete(validatePage());
}
};
}
/**
* Generates the ID for a local element
*
* @param base
* the begining of the id
* @return the separator id
*/
protected String generateID(String base) {
StringBuffer id = new StringBuffer();
id.append(base);
id.append("_");
id.append(System.currentTimeMillis());
return id.toString();
}
/**
* Creates the listener for the new separator tool item
*
* @return the listener created
*/
protected Listener createNewSeparatorListener() {
return new Listener() {
/**
* {@inheritDoc}
*/
public void handleEvent(Event event) {
// retrieve selected element
Object object = ((IStructuredSelection)paletteTreeViewer.getSelection()).getFirstElement();
// if element = drawer => the new stack must be created at the end of the drawer's
// children list
// if element = tool => must be placed before this tool
// else : nothinng to do
if(object instanceof PaletteLocalDrawerProxy) {
String id = generateID("Separator");
PaletteLocalSeparatorProxy proxy = new PaletteLocalSeparatorProxy(id);
((PaletteLocalDrawerProxy)object).addChild(proxy);
} else if(object instanceof PaletteEntryProxy) {
String id = generateID("Separator");
PaletteLocalSeparatorProxy proxy = new PaletteLocalSeparatorProxy(id);
// retrieve parent
PaletteEntryProxy childProxy = (PaletteEntryProxy)object;
PaletteContainerProxy parentProxy = childProxy.getParent();
parentProxy.addChild(proxy, childProxy);
}
setPageComplete(validatePage());
}
};
}
/**
* Creates a toolbar item.
*
* @param toolbar
* the parent toolbar
* @param itemIcon
* path for icon
* @param tooltip
* tooltip text for the toolbar item
* @param listener
* listener for tool bar item
*/
protected void createToolBarItem(ToolBar toolbar, String itemIcon, String tooltip, Listener listener, ToolBarItemValidator validator) {
ToolItem item = new ToolItem(toolbar, SWT.BORDER);
item.setImage(Activator.getPluginIconImage(Activator.ID, itemIcon));
item.setToolTipText(tooltip);
item.addListener(SWT.Selection, listener);
item.setData(VALIDATOR, validator);
}
/**
* creates the buttons to add/remove entries
*/
protected void createAddRemoveButtons() {
Composite composite = new Composite((Composite)getControl(), SWT.NONE);
GridLayout layout = new GridLayout(1, true);
composite.setLayout(layout);
GridData data = new GridData(SWT.CENTER, SWT.CENTER, false, true);
composite.setLayoutData(data);
addButton = new Button(composite, SWT.NONE);
addButton.setImage(Activator.getPluginIconImage(Activator.ID, ADD_ICON));
addButton.setToolTipText(Messages.PapyrusPaletteCustomizerDialog_AddButtonTooltip);
addButton.addMouseListener(createAddButtonListener());
addButton.setEnabled(false);
addButton.addListener(SWT.MouseUp, this);
removeButton = new Button(composite, SWT.NONE);
removeButton.setImage(Activator.getPluginIconImage(Activator.ID, REMOVE_ICON));
removeButton.setToolTipText(Messages.PapyrusPaletteCustomizerDialog_RemoveButtonTooltip);
removeButton.addMouseListener(createRemoveButtonListener());
removeButton.setEnabled(false);
removeButton.addListener(SWT.MouseUp, this);
}
/**
* selection listener for the tools viewer , to update the state of the add button
*
* @return the new created selection listener
*/
protected ISelectionChangedListener createToolsViewerSelectionChangeListener() {
return new ISelectionChangedListener() {
/**
* {@inheritDoc}
*/
public void selectionChanged(SelectionChangedEvent event) {
// get source and target selection
// check source entry can be added to target entry
Object source = ((IStructuredSelection)availableToolsViewer.getSelection()).getFirstElement();
Object target = ((IStructuredSelection)paletteTreeViewer.getSelection()).getFirstElement();
// manage add button
if(isAddValidTarget(source, target)) {
addButton.setEnabled(true);
} else {
addButton.setEnabled(false);
}
// manage remove button
if(isRemoveValidSource(target)) {
removeButton.setEnabled(true);
} else {
removeButton.setEnabled(false);
}
}
/**
* Returns true if the source can be added to the target
*
* @param source
* the source object
* @param target
* the target object
* @return <code>true</code> if the source can be added to the target
*/
protected boolean isAddValidTarget(Object source, Object target) {
if(!(source instanceof PaletteEntry)) {
return false;
}
// case1: source is a drawer.
// it can only be added to the root element (no selection)
// case2: source is a palette tool
// it can't be added to the root element
// it can only be added to a container element (drawer or stack)
if(source instanceof PaletteDrawer) {
if(target == null) {
return true;
}
return false;
} else if(source instanceof ToolEntry) {
if(target instanceof PaletteEntryProxy) {
EntryType type = ((PaletteEntryProxy)target).getType();
switch(type) {
case DRAWER:
case STACK:
return true;
default:
return false;
}
}
return false;
}
return false;
}
/**
* Returns true if the source can be added to the target
*
* @param source
* the source object
* @return <code>true</code> if the source can be removed (not null and instanceof
* PaletteEntryProxy)
*/
protected boolean isRemoveValidSource(Object source) {
if(source instanceof PaletteEntryProxy) {
return true;
}
return false;
}
};
}
/**
* Creates the add button listener
*/
protected MouseListener createAddButtonListener() {
return new MouseListener() {
public void mouseUp(MouseEvent e) {
// add the element selected on the left to the right tree
// check the selection.
IStructuredSelection selection = (IStructuredSelection)availableToolsViewer.getSelection();
if(selection == null || selection.size() < 1) {
return;
}
PaletteEntry entry = (PaletteEntry)selection.getFirstElement();
if(entry == null) {
return;
}
// find the selection on the right
selection = (IStructuredSelection)paletteTreeViewer.getSelection();
PaletteEntryProxy parentNode = (PaletteEntryProxy)selection.getFirstElement();
// Bugfix: only drawers can be added to root element
if(parentNode == null && entry instanceof PaletteDrawer) {
parentNode = (PaletteContainerProxy)paletteTreeViewer.getInput();
}
// check we have a containe here
if(!(parentNode instanceof PaletteContainerProxy)) {
return;
}
// create a new entry in the document
PaletteEntryProxy proxy = createNodeFromEntry(entry);
((PaletteContainerProxy)parentNode).addChild(proxy);
paletteTreeViewer.expandToLevel(parentNode, 1);
}
/**
* {@inheritDoc}
*/
public void mouseDown(MouseEvent e) {
// do nothing
}
/**
* {@inheritDoc}
*/
public void mouseDoubleClick(MouseEvent e) {
// do nothing
}
};
}
/**
* Creates a node in the xml document from the given entry
*
* @param entry
* the palette entry from which to create the node
* @param parentNode
* the parent node for the newly created node
* @return the created entry proxy or <code>null</code>
*/
protected PaletteEntryProxy createNodeFromEntry(Object entry) {
PaletteEntryProxy entryProxy = null;
if(entry instanceof AspectCreationEntry) {
// should modify id of the element here, otherwise, different elements would have the same id...
entryProxy = new PaletteAspectToolEntryProxy(((AspectCreationEntry)entry).clone());
} else if(entry instanceof CombinedTemplateCreationEntry) {
CombinedTemplateCreationEntry originalEntry = (CombinedTemplateCreationEntry)entry;
// create a new Aspect entry proxy
AspectCreationEntry aspectEntry = new AspectCreationEntry(originalEntry.getLabel(), originalEntry.getDescription(), originalEntry.getId() + "_" + System.currentTimeMillis(), originalEntry.getSmallIcon(), originalEntry, new HashMap<Object, Object>());
entryProxy = new PaletteAspectToolEntryProxy(aspectEntry);
} else if(entry instanceof PaletteContainer) {
entryProxy = new PaletteContainerProxy((PaletteContainer)entry);
} else if(entry instanceof PaletteEntryProxy) {
entryProxy = ((PaletteEntryProxy)entry);
}
return entryProxy;
}
/**
* Creates the add button listener
*/
protected MouseListener createRemoveButtonListener() {
return new MouseListener() {
public void mouseUp(MouseEvent e) {
// remove the element selected on the right
// add the element selected on the left to the right tree
// check the selection.
IStructuredSelection selection = (IStructuredSelection)paletteTreeViewer.getSelection();
if(selection == null || selection.size() < 1) {
return;
}
PaletteEntryProxy proxyToDelete = (PaletteEntryProxy)selection.getFirstElement();
if(proxyToDelete == null) {
return;
}
// create a new entry in the document
// get container of the proxy to be deleted
PaletteContainerProxy parentProxy = proxyToDelete.getParent();
parentProxy.removeChild(proxyToDelete);
}
/**
* {@inheritDoc}
*/
public void mouseDown(MouseEvent e) {
// do nothing
}
/**
* {@inheritDoc}
*/
public void mouseDoubleClick(MouseEvent e) {
// do nothing
}
};
}
/**
* creates the available entries group
*/
protected void createAvailableToolsGroup() {
Composite parent = (Composite)getControl();
Composite availableToolsComposite = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(2, true);
layout.marginHeight = 0;
layout.marginWidth = 0;
availableToolsComposite.setLayout(layout);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
availableToolsComposite.setLayoutData(data);
Label label = new Label(availableToolsComposite, SWT.NONE);
label.setText(Messages.Local_Palette_Available_Tools);
data = new GridData(SWT.LEFT, SWT.CENTER, true, false);
label.setLayoutData(data);
ToolBar toolbar = new ToolBar(availableToolsComposite, SWT.HORIZONTAL);
data = new GridData(SWT.RIGHT, SWT.FILL, false, false);
toolbar.setLayoutData(data);
populateAvailableToolsToolBar(toolbar);
createProfileCombo(availableToolsComposite);
Tree tree = new Tree(availableToolsComposite, SWT.SINGLE | SWT.BORDER);
data = new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1);
data.widthHint = 185;
// Make the tree this tall even when there is nothing in it. This will keep the
// dialog from shrinking to an unusually small size.
data.heightHint = 200;
tree.setLayoutData(data);
availableToolsViewer = new TreeViewer(tree);
availableToolsViewer.setContentProvider(new UMLToolsTreeContentProvider());
paletteLabelProvider = new PaletteLabelProvider();
availableToolsViewer.setLabelProvider(paletteLabelProvider);
ViewerComparator labelComparator = new LabelViewerComparator();
availableToolsViewer.setComparator(labelComparator);
// remove the note stack and standard group
availableToolsViewer.addFilter(new ViewerFilter() {
/**
* {@inheritDoc}
*/
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
if(element instanceof PaletteStack && "noteStack".equals(((PaletteStack)element).getId())) {
return false;
} else if(element instanceof PaletteToolbar && "standardGroup".equals(((PaletteToolbar)element).getId())) {
return false;
}
return true;
}
});
availableToolsViewer.addFilter(new DrawerFilter());
// add drag support
addAvailableToolsDragSupport();
// availableToolsViewer.setInput(getAllVisibleStandardEntries());
}
/**
* Creates the profile combo
*
* @param availableToolsComposite
* the available tools composite
* @return the created combo
*/
protected Combo createProfileCombo(Composite availableToolsComposite) {
// retrieve top package, to know which profiles are available
// creates the combo
profileCombo = new Combo(availableToolsComposite, SWT.BORDER | SWT.READ_ONLY);
GridData data = new GridData(SWT.FILL, SWT.FILL, true, false, 2, 1);
profileCombo.setLayoutData(data);
// retrieve all applied profiles
List<Profile> profiles = getAllAppliedProfiles();
int profileNumber = profiles.size();
for(int i = 0; i < profileNumber; i++) {
profileComboList.add(i, profiles.get(i).getName());
}
profileComboList.add(UML_TOOLS_LABEL);
profileCombo.setItems(profileComboList.toArray(new String[]{}));
// add selection listener for the combo. selects the "UML tools" item
ProfileComboSelectionListener listener = new ProfileComboSelectionListener();
profileCombo.addSelectionListener(listener);
profileCombo.addModifyListener(listener);
// profileCombo.select(profileNumber);
return profileCombo;
}
/**
* returns the list of applied profile for the nearest package of the top element
*
* @return the list of applied profile for the nearest package of the top element or an empty
* list
*/
protected List<Profile> getAllAppliedProfiles() {
Package topPackage = null;
if(editorPart instanceof DiagramEditorWithFlyOutPalette) {
EObject element = ((DiagramEditorWithFlyOutPalette)editorPart).getDiagram().getElement();
if(element instanceof org.eclipse.uml2.uml.Element) {
topPackage = ((org.eclipse.uml2.uml.Element)element).getNearestPackage();
}
}
if(topPackage != null) {
return topPackage.getAllAppliedProfiles();
}
return Collections.EMPTY_LIST;
}
/**
* Add drag support from the available tools viewer
*/
protected void addAvailableToolsDragSupport() {
// transfer types
Transfer[] transfers = new Transfer[]{ LocalSelectionTransfer.getTransfer() };
// drag listener
DragSourceListener listener = new DragSourceAdapter() {
/**
* {@inheritDoc}
*/
@Override
public void dragStart(DragSourceEvent event) {
super.dragStart(event);
event.data = availableToolsViewer.getSelection();
}
/**
* {@inheritDoc}
*/
@Override
public void dragSetData(DragSourceEvent event) {
super.dragSetData(event);
LocalSelectionTransfer.getTransfer().setSelection(availableToolsViewer.getSelection());
}
};
availableToolsViewer.addDragSupport(DND.DROP_LINK, transfers, listener);
}
/**
* Adds elements to the tool bar for available tools viewer
*
* @param toolbar
* the toolbar to populate
*/
protected void populateAvailableToolsToolBar(ToolBar toolbar) {
toggleContentProvider = createCheckToolBarItem(toolbar, SWITCH_CONTENT_PROVIDER_ICON, Messages.Local_Palette_SwitchToolsContentProvider_Tooltip, createSwitchToolsContentProviderListener());
toggleContentProvider.setSelection(true);
toggleContentProvider.setEnabled(false);
createCheckToolBarItem(toolbar, SHOWN_TOOLS_ICON, Messages.Local_Palette_ShowTools_Tooltip, createsShowToolListener());
}
/**
* Creates the listener for the available tools content provider
*
* @return the listener created
*/
protected Listener createSwitchToolsContentProviderListener() {
return new Listener() {
/**
* {@inheritDoc}
*/
public void handleEvent(Event event) {
if(!(event.widget instanceof ToolItem)) {
return;
}
ToolItem item = ((ToolItem)event.widget);
// retrieve current profile selected in the combo profile
int index = profileCombo.getSelectionIndex();
Collection<PaletteEntry> standardEntries = getAllVisibleStandardEntries();
Profile profile = getAllAppliedProfiles().get(index);
if(item.getSelection()) {
availableToolsViewer.setContentProvider(new ProfileToolsStereotypeMetaclassTreeContentProvider(profile, standardEntries));
item.setSelection(true);
} else {
availableToolsViewer.setContentProvider(new ProfileToolsMetaclassStereotypeTreeContentProvider(profile, standardEntries));
item.setSelection(false);
}
// generate tools for given profile
availableToolsViewer.setInput(profile);
}
};
}
/**
* creates the tool item for drawers visibility listener
*
* @return the listener for the tool button
*/
protected Listener createShowDrawerListener() {
return new Listener() {
/**
* {@inheritDoc}
*/
public void handleEvent(Event event) {
if(!(event.widget instanceof ToolItem)) {
return;
}
ToolItem item = ((ToolItem)event.widget);
if(item.getSelection()) {
// elements should be hidden
availableToolsViewer.addFilter(drawerFilter);
item.setSelection(true);
} else {
availableToolsViewer.removeFilter(drawerFilter);
item.setSelection(false);
}
}
};
}
/**
* creates the tool item for tools visibility listener
*
* @return the listener for the tool button
*/
protected Listener createsShowToolListener() {
return new Listener() {
/**
* {@inheritDoc}
*/
public void handleEvent(Event event) {
if(!(event.widget instanceof ToolItem)) {
return;
}
ToolItem item = ((ToolItem)event.widget);
if(item.getSelection()) {
// elements should be hidden
availableToolsViewer.addFilter(toolFilter);
item.setSelection(true);
} else {
availableToolsViewer.removeFilter(toolFilter);
item.setSelection(false);
}
}
};
}
/**
* Creates a toolbar item which can be checked.
*
* @param toolbar
* the parent toolbar
* @param shownElementsIcon
* path for shown elements icon
* @param listener
* listener for button action
* @param tooltip
* tooltip text for the toolbar item
*/
protected ToolItem createCheckToolBarItem(ToolBar toolbar, String shownElementsIcon, String tooltip, Listener listener) {
ToolItem item = new ToolItem(toolbar, SWT.CHECK | SWT.BORDER);
item.setImage(Activator.getPluginIconImage(Activator.ID, shownElementsIcon));
item.setToolTipText(tooltip);
item.addListener(SWT.Selection, listener);
return item;
}
/**
* Validates the content of the fields in this page
*/
protected boolean validatePage() {
boolean valid = true;
if(valid) {
setMessage(null);
setErrorMessage(null);
}
return valid;
}
/**
* The <code>WizardNewFileCreationPage</code> implementation of this <code>Listener</code> method handles all events and enablements for controls
* on this page. Subclasses may extend.
*/
public void handleEvent(Event event) {
setPageComplete(validatePage());
}
/**
* Content provider for available tools viewer
*/
public class UMLToolsTreeContentProvider implements ITreeContentProvider {
/**
* Constructor
*
* @param viewer
* The viewer whose ContentProvider this content provider is
*/
public UMLToolsTreeContentProvider() {
}
/**
* {@inheritDoc}
*/
public Object[] getElements(Object inputElement) {
Object[] elements = null;
if(inputElement instanceof Collection<?>) {
elements = ((Collection<?>)inputElement).toArray();
} else if(inputElement instanceof PaletteRoot) {
// paletteUil.getAllEntries(...) to add drawers
// if so, uncomment the addFilterbutton for drawers in populate tool bar
elements = PaletteUtil.getAllToolEntries(((PaletteRoot)inputElement)).toArray();
}
if(elements == null) {
elements = new Object[0];
}
return elements;
}
/**
* {@inheritDoc}
*/
public void dispose() {
}
/**
* {@inheritDoc}
*/
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
/**
* {@inheritDoc}
*/
public Object[] getChildren(Object parentElement) {
Object[] elements = null;
if(parentElement instanceof Collection<?>) {
elements = ((Collection<?>)parentElement).toArray();
} else if(parentElement instanceof PaletteRoot) {
// paletteUil.getAllEntries(...) to add drawers
// if so, uncomment the addFilterbutton for drawers in populate tool bar
elements = PaletteUtil.getAllToolEntries(((PaletteRoot)parentElement)).toArray();
}
return elements;
}
/**
* {@inheritDoc}
*/
public Object getParent(Object element) {
return null;
}
/**
* {@inheritDoc}
*/
public boolean hasChildren(Object element) {
return getChildren(element) != null && getChildren(element).length > 0;
}
}
/**
* Label provider for palette tools.
* <P>
* We should be using the Palette label provider from GEF, if it was not with visibility "package"...
*
* @see org.eclipse.gef.ui.palette.customize.PaletteLabelProvider </P>
*
*/
public class PaletteLabelProvider implements ILabelProvider {
/**
* {@inheritDoc}
*/
public Image getImage(Object element) {
if(element instanceof PaletteEntry) {
ImageDescriptor descriptor = ((PaletteEntry)element).getSmallIcon();
if(descriptor == null) {
return null;
}
return Activator.getPluginIconImage(Activator.ID, descriptor);
} else if(element instanceof Stereotype) {
return Activator.getPluginIconImage(Activator.ID, "/icons/stereotype.gif");
}
return null;
}
/**
* {@inheritDoc}
*/
public String getText(Object element) {
if(element instanceof PaletteEntry) {
return ((PaletteEntry)element).getLabel();
} else if(element instanceof Stereotype) {
return ((Stereotype)element).getName();
}
return "unknown element";
}
/**
* {@inheritDoc}
*/
public void addListener(ILabelProviderListener listener) {
}
/**
* {@inheritDoc}
*/
public void dispose() {
}
/**
* {@inheritDoc}
*/
public boolean isLabelProperty(Object element, String property) {
return false;
}
/**
* {@inheritDoc}
*/
public void removeListener(ILabelProviderListener listener) {
}
}
/**
* Label provider for palette tools.
* <P>
* We should be using the Palette label provider from GEF, if it was not with visibility "package"...
*
* @see org.eclipse.gef.ui.palette.customize.PaletteLabelProvider </P>
*
*/
public class PaletteProxyLabelProvider implements ILabelProvider {
/**
* {@inheritDoc}
*/
public Image getImage(Object element) {
if(element instanceof PaletteEntryProxy) {
return ((PaletteEntryProxy)element).getImage();
}
return null;
}
/**
* {@inheritDoc}
*/
public String getText(Object element) {
if(element instanceof PaletteEntryProxy) {
return ((PaletteEntryProxy)element).getLabel();
}
return "unknown element";
}
/**
* {@inheritDoc}
*/
public void addListener(ILabelProviderListener listener) {
}
/**
* {@inheritDoc}
*/
public void dispose() {
}
/**
* {@inheritDoc}
*/
public boolean isLabelProperty(Object element, String property) {
return false;
}
/**
* {@inheritDoc}
*/
public void removeListener(ILabelProviderListener listener) {
}
}
/**
* Filter for the viewer. Hide/show Drawers
*/
public class DrawerFilter extends ViewerFilter {
/**
* {@inheritDoc}
*/
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
if(element instanceof PaletteDrawer) {
return false;
}
return true;
}
}
/**
* Filter for the viewer. Hide/show Drawers
*/
public class ToolFilter extends ViewerFilter {
/**
* {@inheritDoc}
*/
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
if(element instanceof ToolEntry) {
return false;
}
return true;
}
}
/**
* Content provider for the palette
*/
public class PaletteContentProvider implements ITreeContentProvider {
/** tree viewer this provider provides content */
protected final TreeViewer viewer;
/** the document root where to build the palette */
protected PaletteContainerProxy rootProxy;
/** model listener that will listens for all modifications in the entries */
protected PropertyChangeListener modelListener = new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
handlePropertyChanged(evt);
}
};
/**
* Creates a new PaletteContentProvider.
*
* @param treeviewer
* tree viewer this provider provides content
*/
public PaletteContentProvider(TreeViewer treeviewer) {
this.viewer = treeviewer;
}
/**
* {@inheritDoc}
*/
public void dispose() {
// remove all listeners
traverseModel(rootProxy, false);
}
/**
* {@inheritDoc}
*/
public Object[] getChildren(Object parentElement) {
if(parentElement instanceof PaletteEntryProxy) {
List<PaletteEntryProxy> children = ((PaletteEntryProxy)parentElement).getChildren();
return (children != null) ? children.toArray() : new Object[0];
}
return null;
}
/**
* {@inheritDoc}
*/
public boolean hasChildren(Object element) {
if(element instanceof PaletteEntryProxy) {
return ((PaletteEntryProxy)element).getChildren() != null && !((PaletteEntryProxy)element).getChildren().isEmpty();
}
return false;
}
/**
* {@inheritDoc}
*/
public Object[] getElements(Object inputElement) {
Object[] elements = getChildren(inputElement);
if(elements == null) {
elements = new Object[0];
}
return elements;
}
/**
* {@inheritDoc}
*/
public Object getParent(Object element) {
if(element instanceof PaletteEntryProxy) {
return ((PaletteEntryProxy)element).getParent();
}
return null;
}
/**
* {@inheritDoc}
*/
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
if(rootProxy != null) {
// warning.. the root has no entry, this is a virtual node
traverseModel(rootProxy, false);
}
if(newInput != null) {
rootProxy = ((PaletteContainerProxy)newInput);
traverseModel(rootProxy, true);
}
}
/**
* This method is invoked whenever there is any change in the model. It updates the
* viewer with the changes that were made to the model. Sub-classes may override this
* method to change or extend its functionality.
*
* @param evt
* The {@link PropertyChangeEvent} that was fired from the model
*/
protected void handlePropertyChanged(PropertyChangeEvent evt) {
PaletteEntryProxy entry = ((PaletteEntryProxy)evt.getSource());
String property = evt.getPropertyName();
if(property.equals(PaletteEntry.PROPERTY_LABEL) || property.equals(PaletteEntry.PROPERTY_SMALL_ICON) || property.equals(PaletteEntryProxy.PROPERTY_ICON_PATH)) {
viewer.update(entry, null);
} else if(property.equals(PaletteContainerProxy.PROPERTY_ADD_CHILDREN)) {
viewer.refresh(entry.getParent());
// add the listeners to the child
traverseModel(((PaletteEntryProxy)evt.getNewValue()), true);
} else if(property.equals(PaletteContainerProxy.PROPERTY_REMOVE_CHILDREN)) {
viewer.refresh(entry.getParent());
// add the listeners to the child
traverseModel(((PaletteEntryProxy)evt.getOldValue()), false);
}
}
protected void traverseModel(PaletteEntryProxy entryProxy, boolean isHook) {
if(entryProxy != null) {
if(isHook) {
entryProxy.addPropertyChangeListener(modelListener);
} else {
entryProxy.removePropertyChangeListener(modelListener);
}
}
if(entryProxy.getChildren() != null && !entryProxy.getChildren().isEmpty()) {
for(PaletteEntryProxy proxy : entryProxy.getChildren()) {
traverseModel(proxy, isHook);
}
}
}
}
/**
* Performs all action on finish
*
* @param id
* the path for the file
*/
public void performFinish(String path) {
// creates the document
Document document = createXMLDocumentFromPalettePreview();
saveDocument(document, path);
requiredProfiles = collectRequiredProfiles();
}
/**
* collect the required profiles from all tool provided by the local palette definition
*/
protected Set<String> collectRequiredProfiles() {
Set<String> profiles = new HashSet<String>();
PaletteContainerProxy rootProxy = (PaletteContainerProxy)paletteTreeViewer.getInput();
collectRequiredProfiles(rootProxy.getChildren(), profiles);
return profiles;
}
/**
* collect the required profiles from all tool provided by the local palette definition
*/
protected void collectRequiredProfiles(List<PaletteEntryProxy> proxies, Set<String> requiredProfiles) {
for(PaletteEntryProxy proxy : proxies) {
// add profile(s) if relevant, check for children
if(proxy instanceof PaletteAspectToolEntryProxy) {
// list of profiles
for(String stereotypeQN : ((PaletteAspectToolEntryProxy)proxy).getStereotypesQNList()) {
// retrieve list of profiles from the stereotype QN (only remove last segment
// ?!)
String profileName = PaletteUtil.findProfileNameFromStereotypeName(stereotypeQN);
requiredProfiles.add(profileName);
}
}
if(proxy.getChildren() != null) {
collectRequiredProfiles(proxy.getChildren(), requiredProfiles);
}
}
}
/**
* Saves the xml document into file
*
* @param document
* the document to save
* @param path
* name of the file
* @return the file created or updated
*/
protected File saveDocument(Document document, String path) {
File file = null;
try {
// create the file that stores the XML configuration
file = Activator.getDefault().getStateLocation().append(path).toFile();
TransformerFactory tranFactory = TransformerFactory.newInstance();
Transformer aTransformer;
aTransformer = tranFactory.newTransformer();
Source src = new DOMSource(document);
Result dest = new StreamResult(file);
aTransformer.transform(src, dest);
} catch (TransformerConfigurationException e) {
Activator.log.error(e);
} catch (TransformerException e) {
Activator.log.error(e);
}
return file;
}
/**
* Creates the document from the palette preview
*
* @return the dom structure of the document
*/
protected Document createXMLDocumentFromPalettePreview() {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
documentBuilderFactory.setNamespaceAware(true);
DocumentBuilder documentBuilder;
try {
documentBuilder = documentBuilderFactory.newDocumentBuilder();
document = documentBuilder.newDocument();
Element paletteDefElement = document.createElement(IPapyrusPaletteConstant.PALETTE_DEFINITION);
document.appendChild(paletteDefElement);
Element contentElement = document.createElement(IPapyrusPaletteConstant.CONTENT);
paletteDefElement.appendChild(contentElement);
generateXMLPaletteContent(document, contentElement);
return document;
} catch (ParserConfigurationException e) {
Activator.getDefault().logError("impossible to create the palette tree viewer content", e);
}
return null;
}
/**
* Generates the xml content for the palette
*
* @param document
* the document to fill
* @param contentElement
* the root for the xml content
*/
protected void generateXMLPaletteContent(Document document, Element contentElement) {
PaletteContainerProxy rootProxy = (PaletteContainerProxy)paletteTreeViewer.getInput();
for(PaletteEntryProxy proxy : rootProxy.getChildren()) {
generateXMLPaletteContainerProxy(document, contentElement, proxy);
}
}
/**
* Generates the xml content for the given container
*
* @param document
* the document to fill
* @param containerProxy
* the entry proxy
*/
protected void generateXMLPaletteContainerProxy(Document document, Element contentElement, PaletteEntryProxy containerProxy) {
Element element = null;
List<PaletteEntryProxy> children = containerProxy.getChildren();
// generate the element
switch(containerProxy.getType()) {
case DRAWER:
element = document.createElement(IPapyrusPaletteConstant.DRAWER);
element.setAttribute(IPapyrusPaletteConstant.NAME, containerProxy.getLabel());
if(containerProxy instanceof PaletteLocalDrawerProxy) {
element.setAttribute(IPapyrusPaletteConstant.ICON_PATH, ((PaletteLocalDrawerProxy)containerProxy).getImagePath());
}
break;
case TOOL:
element = document.createElement(IPapyrusPaletteConstant.TOOL);
break;
case SEPARATOR:
element = document.createElement(IPapyrusPaletteConstant.SEPARATOR);
break;
case STACK:
element = document.createElement(IPapyrusPaletteConstant.STACK);
break;
case ASPECT_TOOL:
element = document.createElement(IPapyrusPaletteConstant.ASPECT_TOOL);
// try to cast the element into PaletteAspectToolEntryProxy
if(containerProxy instanceof PaletteAspectToolEntryProxy) {
PaletteAspectToolEntryProxy aspectEntryProxy = (PaletteAspectToolEntryProxy)containerProxy;
// element.setAttribute(IPapyrusPaletteConstant.ID, aspectEntryProxy.getId());
element.setAttribute(IPapyrusPaletteConstant.NAME, aspectEntryProxy.getLabel());
element.setAttribute(IPapyrusPaletteConstant.DESCRIPTION, aspectEntryProxy.getEntry().getDescription());
element.setAttribute(IPapyrusPaletteConstant.REF_TOOL_ID, aspectEntryProxy.getReferencedPaletteID());
if(aspectEntryProxy.getImagePath() != null && !aspectEntryProxy.getImagePath().equals("")) {
element.setAttribute(IPapyrusPaletteConstant.ICON_PATH, aspectEntryProxy.getImagePath());
}
// add post action, stereotype list
for(IAspectAction action : ((PaletteAspectToolEntryProxy)containerProxy).getPostActions()) {
Element postActionNode = document.createElement(IPapyrusPaletteConstant.POST_ACTION);
postActionNode.setAttribute(IPapyrusPaletteConstant.ID, action.getFactoryId());
action.save(postActionNode);
element.appendChild(postActionNode);
}
}
default:
break;
}
element.setAttribute(IPapyrusPaletteConstant.ID, containerProxy.getId());
contentElement.appendChild(element);
if(children != null) {
for(PaletteEntryProxy proxy : children) {
generateXMLPaletteContainerProxy(document, element, proxy);
}
}
}
public enum EntryType {
DRAWER, TOOL, STACK, SEPARATOR, ASPECT_TOOL
}
public class LabelViewerComparator extends ViewerComparator {
/**
* Creates a new LabelViewerComparator.
*/
public LabelViewerComparator() {
super();
}
/**
* {@inheritDoc}
*/
@Override
public int compare(Viewer testViewer, Object e1, Object e2) {
String label1 = "";
String label2 = "";
if(e1 instanceof PaletteEntry) {
label1 = ((PaletteEntry)e1).getLabel();
} else if(e1 instanceof Stereotype) {
label1 = ((Stereotype)e1).getName();
}
if(e2 instanceof PaletteEntry) {
label2 = ((PaletteEntry)e2).getLabel();
} else if(e2 instanceof Stereotype) {
label2 = ((Stereotype)e2).getName();
}
if(label1 == null) {
return 1;
}
if(label2 == null) {
return -1;
}
return label1.compareTo(label2);
}
}
/**
* Listener for the profile combo. It changes the input of the following viewer.
*/
public class ProfileComboSelectionListener implements SelectionListener, ModifyListener {
/**
* {@inheritDoc}
*/
public void widgetDefaultSelected(SelectionEvent e) {
// nothing to do
}
/**
* {@inheritDoc}
*/
public void widgetSelected(SelectionEvent e) {
handleSelectionChanged();
}
/**
* {@inheritDoc}
*/
public void modifyText(ModifyEvent e) {
handleSelectionChanged();
}
/**
* handles the change selection for the combo
*/
protected void handleSelectionChanged() {
int index = profileCombo.getSelectionIndex();
if(index < 0 || index >= profileCombo.getItems().length) {
return;
}
String name = profileComboList.get(index);
Collection<PaletteEntry> standardEntries = getAllVisibleStandardEntries();
// retrieve the profile or uml standards tools to display
if(UML_TOOLS_LABEL.equals(name)) {
// change content provider
availableToolsViewer.setContentProvider(new UMLToolsTreeContentProvider());
availableToolsViewer.setInput(standardEntries);
toggleContentProvider.setEnabled(false);
} else {
if(toggleContentProvider != null && !toggleContentProvider.isDisposed()) {
toggleContentProvider.setEnabled(true);
}
// switch content provider
// this is a profile in case of uml2 tools
Profile profile = getAllAppliedProfiles().get(index);
if(toggleContentProvider.getSelection()) {
availableToolsViewer.setContentProvider(new ProfileToolsStereotypeMetaclassTreeContentProvider(profile, standardEntries));
} else {
availableToolsViewer.setContentProvider(new ProfileToolsMetaclassStereotypeTreeContentProvider(profile, standardEntries));
}
// generate tools for given profile
availableToolsViewer.setInput(profile);
}
}
}
/**
* Content provider for the available tools viewer, when the tools to see are coming from a
* profile
*/
public class ProfileToolsStereotypeMetaclassTreeContentProvider implements ITreeContentProvider {
/** standard uml tools palette entries */
final protected Collection<PaletteEntry> standardEntries;
/**
* Creates a new ProfileToolsStereotypeMetaclassTreeContentProvider.
*
* @param profile
* the profile for which tools are built
* @param standardEntries
* list of standard uml tools palette entries
*/
public ProfileToolsStereotypeMetaclassTreeContentProvider(Profile profile, Collection<PaletteEntry> standardEntries) {
this.standardEntries = standardEntries;
}
/**
* {@inheritDoc}
*/
public Object[] getChildren(Object parentElement) {
if(parentElement instanceof Profile) {
return ((Profile)parentElement).getOwnedStereotypes().toArray();
} else if(parentElement instanceof Stereotype) {
List<PaletteEntry> entries = new ArrayList<PaletteEntry>();
Stereotype stereotype = (Stereotype)parentElement;
for(PaletteEntry entry : standardEntries) {
// retrieve the element type created by the tool.
if(entry instanceof CombinedTemplateCreationEntry) {
EClass toolMetaclass = PaletteUtil.getToolMetaclass((CombinedTemplateCreationEntry)entry);
if(toolMetaclass != null) {
List<Class> metaclasses = stereotype.getAllExtendedMetaclasses();
for(Class stMetaclass : metaclasses) {
// get Eclass
java.lang.Class metaclassClass = stMetaclass.getClass();
if(metaclassClass != null) {
EClassifier metaClassifier = UMLPackage.eINSTANCE.getEClassifier(stMetaclass.getName());
if(((EClass)metaClassifier).isSuperTypeOf(toolMetaclass)) {
// should create the palette entry
HashMap properties = new HashMap();
properties.put(IPapyrusPaletteConstant.ASPECT_ACTION_KEY, StereotypeAspectActionProvider.createConfigurationNode(stereotype.getQualifiedName()));
AspectCreationEntry aspectEntry = new AspectCreationEntry(stereotype.getName() + " (" + entry.getLabel() + ")", "Create an element with a stereotype", entry.getId() + "_" + System.currentTimeMillis(), entry.getSmallIcon(), (CombinedTemplateCreationEntry)entry, properties);
entries.add(aspectEntry);
}
}
}
}
}
}
return entries.toArray();
} else {
return new Object[0];
}
}
/**
* {@inheritDoc}
*/
public Object getParent(Object element) {
if(element instanceof Stereotype) {
return ((Stereotype)element).getProfile();
}
return null;
}
/**
* {@inheritDoc}
*/
public boolean hasChildren(Object element) {
if(element instanceof Profile) {
return true;
} else if(element instanceof Stereotype) {
return true;
}
return false;
}
/**
* {@inheritDoc}
*/
public Object[] getElements(Object inputElement) {
if(inputElement instanceof Profile) {
List<Stereotype> stereotypes = ((Profile)inputElement).getOwnedStereotypes();
return stereotypes.toArray();
}
return new Object[0];
}
/**
* {@inheritDoc}
*/
public void dispose() {
// nothing to do here
}
/**
* {@inheritDoc}
*/
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// nothing to do here
}
}
/**
* Content provider for the available tools viewer, when the
*/
public class ProfileToolsMetaclassStereotypeTreeContentProvider implements ITreeContentProvider {
/** standard uml tools palette entries */
final protected Collection<PaletteEntry> standardEntries;
/** profile to display */
final protected Profile profile;
/**
* Creates a new ProfileToolsMetaclassStereotypeTreeContentProvider.
*
* @param profile
* the profile for which tools are built
* @param standardEntries
* list of standard uml tools palette entries
*/
public ProfileToolsMetaclassStereotypeTreeContentProvider(Profile profile, Collection<PaletteEntry> standardEntries) {
this.profile = profile;
this.standardEntries = standardEntries;
}
/**
* {@inheritDoc}
*/
public Object[] getChildren(Object parentElement) {
if(parentElement instanceof Profile) {
return standardEntries.toArray();
} else if(parentElement instanceof AspectCreationEntry) {
return new Object[0];
} else if(parentElement instanceof PaletteEntry) {
List<AspectCreationEntry> entries = new ArrayList<AspectCreationEntry>();
// display all stereotypes applicable to the type of element created by this tool
if(parentElement instanceof CombinedTemplateCreationEntry) {
CombinedTemplateCreationEntry entry = (CombinedTemplateCreationEntry)parentElement;
EClass toolMetaclass = PaletteUtil.getToolMetaclass(entry);
if(toolMetaclass != null) {
for(Stereotype stereotype : profile.getOwnedStereotypes()) {
List<Class> metaclasses = stereotype.getAllExtendedMetaclasses();
for(Class stMetaclass : metaclasses) {
// get Eclass
java.lang.Class metaclassClass = stMetaclass.getClass();
if(metaclassClass != null) {
EClassifier metaClassifier = UMLPackage.eINSTANCE.getEClassifier(stMetaclass.getName());
if(((EClass)metaClassifier).isSuperTypeOf(toolMetaclass)) {
// should create the palette entry
HashMap properties = new HashMap();
ArrayList<String> stereotypesQNToApply = new ArrayList<String>();
properties.put(IPapyrusPaletteConstant.ASPECT_ACTION_KEY, StereotypeAspectActionProvider.createConfigurationNode(stereotype.getQualifiedName()));
AspectCreationEntry aspectEntry = new AspectCreationEntry(stereotype.getName() + " (" + entry.getLabel() + ")", "Create an element with a stereotype", entry.getId() + "_" + System.currentTimeMillis(), entry.getSmallIcon(), entry, properties);
entries.add(aspectEntry);
}
}
}
}
}
}
return entries.toArray();
} else {
return new Object[0];
}
}
/**
* {@inheritDoc}
*/
public Object getParent(Object element) {
if(element instanceof Stereotype) {
return ((Stereotype)element).getProfile();
}
return null;
}
/**
* {@inheritDoc}
*/
public boolean hasChildren(Object element) {
if(element instanceof Profile) {
return true;
} else if(element instanceof AspectCreationEntry) {
return false;
} else if(element instanceof PaletteEntry) {
return true;
}
return false;
}
/**
* {@inheritDoc}
*/
public Object[] getElements(Object inputElement) {
if(inputElement instanceof Profile) {
return standardEntries.toArray();
}
return new Object[0];
}
/**
* {@inheritDoc}
*/
public void dispose() {
// nothing to do here
}
/**
* {@inheritDoc}
*/
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// nothing to do here
}
}
/**
* Returns the list of all visible palette entries
*
* @return the list of all visible palette entries
*/
protected Collection<PaletteEntry> getAllVisibleStandardEntries() {
HashSet<PaletteEntry> result = new HashSet<PaletteEntry>();
for(PaletteEntry entry : PaletteUtil.getAvailableEntriesSet(editorPart, priority).values()) {
// the entry is not just a defineOnly entry but a visible one
if(getRootParent(entry) != null) {
result.add(entry);
}
}
return result;
}
/**
* Returns the Root element for the palette entry. It searches recursively from parent to parent, until it find the root element
*
* @param entry
* the palette entry for which root element is searched
* @return the root element or <code>null</code> if none was found
*/
protected PaletteRoot getRootParent(PaletteEntry entry) {
PaletteContainer parent = entry.getParent();
if(parent instanceof PaletteRoot) {
return (PaletteRoot)parent;
} else if(parent != null) {
return getRootParent(parent);
} else {
return null;
}
}
/**
* Returns the list of required profiles by this local palette definition
*
* @return the profiles required by this palette
*/
public Set<String> getRequiredProfiles() {
return requiredProfiles;
}
/**
* Item validator
*/
protected abstract class ToolBarItemValidator {
/**
* Checks if the button should be enable or not
*
* @return <code>true</code> if the button should be enable
*/
public abstract boolean isEnable();
}
/**
* validator for the edit element tool item. It does not remove
*/
protected class EditElementToolBarItemValidator extends ToolBarItemValidator {
/**
* @{inheritDoc
*/
@Override
public boolean isEnable() {
// retrieve selection
if(paletteTreeViewer != null && !paletteTreeViewer.getControl().isDisposed()) {
// retrieve selection. first element should be a drawer
IStructuredSelection selection = (IStructuredSelection)paletteTreeViewer.getSelection();
if(selection == null) {
return false;
} else {
// look for first element. should be an instance of drawer
return (selection.getFirstElement() instanceof PaletteLocalDrawerProxy);
}
}
return false;
}
}
/**
* validator for the create separator or stack tool item. Only valid when selection is a {@link PaletteEntryProxy} or a
* {@link PaletteLocalDrawerProxy}
*/
protected class PaletteEntryProxySelectedValidator extends ToolBarItemValidator {
/**
* @{inheritDoc
*/
@Override
public boolean isEnable() {
// retrieve selection
if(paletteTreeViewer != null && !paletteTreeViewer.getControl().isDisposed()) {
// retrieve selection. first element should be a drawer
IStructuredSelection selection = (IStructuredSelection)paletteTreeViewer.getSelection();
if(selection == null) {
return false;
} else {
Object object = selection.getFirstElement();
return (object instanceof PaletteEntryProxy);
}
}
return false;
}
}
/**
* Sets the priority of the current edited palette
*
* @param priority
* the priority of the current edited palette
*/
public void setPriority(ProviderPriority priority) {
this.priority = priority;
}
}