/******************************************************************************* * Copyright (c) 2011 University of Mannheim: Chair for Software Engineering * 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: * Ralph Gerbig - initial API and implementation and initial documentation *******************************************************************************/ package de.uni_mannheim.informatik.swt.plm.visualization.editor.views; import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.List; import org.eclipse.core.runtime.CoreException; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.EContentAdapter; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.edit.command.CommandParameter; import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.emf.edit.provider.ComposedAdapterFactory; import org.eclipse.emf.edit.provider.IEditingDomainItemProvider; import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory; import org.eclipse.emf.edit.provider.resource.ResourceItemProviderAdapterFactory; import org.eclipse.emf.edit.ui.action.CopyAction; import org.eclipse.emf.edit.ui.action.CreateChildAction; import org.eclipse.emf.edit.ui.action.CreateSiblingAction; import org.eclipse.emf.edit.ui.action.CutAction; import org.eclipse.emf.edit.ui.action.DeleteAction; import org.eclipse.emf.edit.ui.action.EditingDomainActionBarContributor; import org.eclipse.emf.edit.ui.action.PasteAction; import org.eclipse.emf.edit.ui.action.RedoAction; import org.eclipse.emf.edit.ui.action.UndoAction; import org.eclipse.emf.edit.ui.dnd.EditingDomainViewerDropAdapter; import org.eclipse.emf.edit.ui.dnd.LocalTransfer; import org.eclipse.emf.edit.ui.dnd.ViewerDragAdapter; import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider; import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; import org.eclipse.emf.edit.ui.view.ExtendedPropertySheetPage; import org.eclipse.emf.transaction.util.TransactionUtil; import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart; import org.eclipse.jface.action.ActionContributionItem; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.action.IContributionManager; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.action.SubContributionItem; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.Transfer; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Menu; import org.eclipse.ui.IActionBars; import org.eclipse.ui.INullSelectionListener; import org.eclipse.ui.ISharedImages; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.IGotoMarker; import org.eclipse.ui.part.ViewPart; import org.eclipse.ui.views.properties.IPropertySheetEntry; import org.eclipse.ui.views.properties.IPropertySheetPage; import org.eclipse.ui.views.properties.PropertySheetPage; import org.eclipse.ui.views.properties.PropertySheetSorter; import de.uni_mannheim.informatik.swt.mlm.workbench.ExtensionPointService; import de.uni_mannheim.informatik.swt.mlm.workbench.interfaces.IVisualizationServiceBase; import de.uni_mannheim.informatik.swt.models.plm.PLM.Element; import de.uni_mannheim.informatik.swt.models.plm.PLM.LMLVisualizer; import de.uni_mannheim.informatik.swt.models.plm.PLM.PLMPackage; import de.uni_mannheim.informatik.swt.models.plm.diagram.part.PLMDiagramEditor; import de.uni_mannheim.informatik.swt.models.plm.PLM.presentation.PLMEditorPlugin; import de.uni_mannheim.informatik.swt.models.plm.PLM.provider.PLMItemProviderAdapterFactory; /** * Contains code from the EMF generated editor plug-in * * BUG: getPropertySheetPage() does use the domain of the first opened diagram. Maybe here an * own EditingDomain is needed so that the View is not polluting the domains of diagrams if * more than one is opened. * */ public class VisualizationEditorView extends ViewPart implements INullSelectionListener, ISelectionProvider{ /** * The ID of the view as specified by the extension. */ public static final String ID = "de.uni_mannheim.informatik.swt.plm.visualization.editor.views.VisualizationEditorView"; //A list of all active visualization services List<IVisualizationServiceBase> activeVisualizationServices = new ArrayList<>(); TreeViewer viewer; EContentAdapter adapter; //Used by the menuBuilder SelectionChangedListener MenuManager createChildMenuManager = new MenuManager(PLMEditorPlugin.INSTANCE.getString("_UI_CreateChild_menu_item")); MenuManager createSiblingMenuManager = new MenuManager(PLMEditorPlugin.INSTANCE.getString("_UI_CreateSibling_menu_item")); Collection<IAction> createSiblingActions; Collection<IAction> createChildActions; ComposedAdapterFactory factory; EObject model = null; ChangeListener modelListener = new ChangeListener(); public void addPropertyListener(org.eclipse.ui.IPropertyListener listener) {}; PropertySheetPage propertySheetPage; EditingDomain domain = null; /** * This is need to return a property sheet page. If not implemented the * property sheet does not get updated correctly in some cases. * * This is how the framework determines which interfaces we implement. * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ @SuppressWarnings("rawtypes") @Override public Object getAdapter(Class key) { if (key.equals(IPropertySheetPage.class)) { return getPropertySheetPage(); } else if (key.equals(IGotoMarker.class)) { return this; } else { return super.getAdapter(key); } } public IPropertySheetPage getPropertySheetPage() { if (propertySheetPage == null) { if (getSite().getWorkbenchWindow().getActivePage().getActiveEditor() == null || ! (getSite().getWorkbenchWindow().getActivePage().getActiveEditor() instanceof PLMDiagramEditor)) return null; //The domain is null so we need to get on by the active editor if (domain == null) domain = ((PLMDiagramEditor)getSite().getWorkbenchWindow().getActivePage().getActiveEditor()).getEditingDomain(); viewer.getSelection(); propertySheetPage = new MyExtendedPropertySheetPage((AdapterFactoryEditingDomain)domain); propertySheetPage.setPropertySourceProvider(new AdapterFactoryContentProvider(factory)); } return propertySheetPage; } /** * This class is needed to prevent sorting of RGB color Attributes. * Everything else is sorted using the default behaviour. */ private class MyExtendedPropertySheetPage extends ExtendedPropertySheetPage { public MyExtendedPropertySheetPage(AdapterFactoryEditingDomain domain){ super(domain); setSorter(new PropertySheetSorter()); } @Override public void setSelectionToViewer(List<?> selection) { this.setSelectionToViewer(selection); this.setFocus(); } @Override public void setActionBars(IActionBars actionBars) { super.setActionBars(actionBars); //getActionBarContributor().shareGlobalActions(this, actionBars); } /** * This is used to not sort RGB color properties * alphabetically */ @Override protected void setSorter(PropertySheetSorter sorter) { sorter = new PropertySheetSorter(){ @Override public void sort(IPropertySheetEntry[] entries) { boolean isRGB = true; for (IPropertySheetEntry entry :entries){ isRGB = entry.getDisplayName().equals("R") || entry.getDisplayName().equals("G") || entry.getDisplayName().equals("B"); } //For RGB Colors nothing is done if (isRGB) return; //Everything else gets sorted alpabetically super.sort(entries); } }; super.setSorter(sorter); } } public EditingDomainActionBarContributor getActionBarContributor() { return null; //(EditingDomainActionBarContributor)getEditorSite().getActionBarContributor(); } /** * @throws CoreException * */ public VisualizationEditorView() throws CoreException { if (ExtensionPointService.Instance().getActiveGraphicalVisualizationService() != null) activeVisualizationServices.add(ExtensionPointService.Instance().getActiveGraphicalVisualizationService()); if (ExtensionPointService.Instance().getActiveTextualVisualizationService() != null) activeVisualizationServices.add(ExtensionPointService.Instance().getActiveTextualVisualizationService()); } /* (non-Javadoc) * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite) */ @Override public void createPartControl(Composite parent) { viewer = new TreeViewer(parent); //Allow only visualizers to be displayed viewer.addFilter(new ViewerFilter() { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { for (IVisualizationServiceBase visualizationService : activeVisualizationServices) if (visualizationService.isVisibleInVisualizerEditorView((EObject)element)) return true; return false; // return //Graphical Model // (element instanceof GraphicalDSLVisualizer) || (element instanceof LMLVisualizer) // || (element instanceof VisualizationDescriptor) || (element instanceof Point) // || (element instanceof LayoutInformationDescriptor) || (element instanceof FontDescriptor) // || (element instanceof LinkDecoration) || (element instanceof SpacingDescriptor) // Textual Model // || (element instanceof TextualDSLVisualizer) || (element instanceof TextualVisualizationDescriptor) // || (element instanceof AbstractColor) // ; } }); factory = new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE); factory.addAdapterFactory(new ResourceItemProviderAdapterFactory()); factory.addAdapterFactory(new PLMItemProviderAdapterFactory()); factory.addAdapterFactory(new ReflectiveItemProviderAdapterFactory()); //Add the visualization service adapter factories for (IVisualizationServiceBase visualizationService : activeVisualizationServices) factory.addAdapterFactory(visualizationService.getItemProviderAdapterFactory()); viewer.setContentProvider(new AdapterFactoryContentProvider(factory)); viewer.setLabelProvider(new AdapterFactoryLabelProvider(factory)); viewer.addSelectionChangedListener(menuBuilder); //************************************************************************************* // BEGIN Register the context menu //************************************************************************************* MenuManager menu = new MenuManager(); menu.setRemoveAllWhenShown(true); menu.addMenuListener(new IMenuListener() { @Override public void menuAboutToShow(IMenuManager manager) { manager.add(new Separator("additions")); manager.insertBefore("additions", createChildMenuManager); manager.insertBefore("additions", createSiblingMenuManager); //EditingDomain domain = ((PLMDiagramEditor)getSite().getWorkbenchWindow().getActivePage().getActiveEditor()).getEditingDomain(); ISharedImages sharedImages = PlatformUI.getWorkbench().getSharedImages(); DeleteAction deleteAction = new DeleteAction(domain); deleteAction.selectionChanged((IStructuredSelection)viewer.getSelection()); deleteAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_DELETE)); manager.add(deleteAction); CutAction cutAction = new CutAction(domain); cutAction.selectionChanged((IStructuredSelection)viewer.getSelection()); cutAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_CUT)); manager.add(cutAction); CopyAction copyAction = new CopyAction(domain); copyAction.selectionChanged((IStructuredSelection)viewer.getSelection()); copyAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_COPY)); manager.add(copyAction); PasteAction pasteAction = new PasteAction(domain); pasteAction.selectionChanged((IStructuredSelection)viewer.getSelection()); pasteAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_PASTE)); manager.add(pasteAction); UndoAction undoAction = new UndoAction(domain); undoAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_UNDO)); manager.add(undoAction); RedoAction redoAction = new RedoAction(domain); redoAction.setImageDescriptor(sharedImages.getImageDescriptor(ISharedImages.IMG_TOOL_REDO)); manager.add(redoAction); } }); Menu m = menu.createContextMenu(viewer.getTree()); viewer.getTree().setMenu(m); getSite().registerContextMenu(menu, viewer); //************************************************************************************* // END Register the context menu //************************************************************************************* int dndOperations = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK; Transfer[] transfers = new Transfer[] { LocalTransfer.getInstance() }; viewer.addDragSupport(dndOperations, transfers, new ViewerDragAdapter(viewer)); viewer.addDropSupport(dndOperations, transfers, new EditingDomainViewerDropAdapter(domain, viewer)); //Better use this but does not work due to bug // getSite().getPage().addSelectionListener(PLMDiagramEditor.ID ,this); getSite().getPage().addSelectionListener(this); getSite().setSelectionProvider(this); } @Override public void selectionChanged(IWorkbenchPart part, ISelection selection) { if (! (selection instanceof IStructuredSelection)) return; IStructuredSelection structeredSelection = (IStructuredSelection)selection; if (! (structeredSelection.getFirstElement() instanceof IGraphicalEditPart)) return; IGraphicalEditPart editPart = (IGraphicalEditPart)structeredSelection.getFirstElement(); if(! (editPart.resolveSemanticElement() instanceof Element)) return; Element ele = (Element)editPart.resolveSemanticElement(); viewer.setInput(ele); //We need to install/uninstall listeners to the model EObject newModel = EcoreUtil.getRootContainer(ele); if (newModel != model) { //No previous model if (model != null) model.eAdapters().remove(modelListener); model = newModel; model.eAdapters().add(modelListener); } viewer.expandAll(); } ISelectionChangedListener menuBuilder = new ISelectionChangedListener() { /** * This implements {@link org.eclipse.jface.viewers.ISelectionChangedListener}, * handling {@link org.eclipse.jface.viewers.SelectionChangedEvent}s by querying for the children and siblings * that can be added to the selected object and updating the menus accordingly. * <!-- begin-user-doc --> * <!-- end-user-doc --> * @generated */ @Override public void selectionChanged(SelectionChangedEvent event) { // Remove any menu items for old selection. // if (createChildMenuManager != null) { depopulateManager(createChildMenuManager, createChildActions); } if (createSiblingMenuManager != null) { depopulateManager(createSiblingMenuManager, createSiblingActions); } // Query the new selection for appropriate new child/sibling descriptors // Collection<?> newChildDescriptors = null; Collection<?> newSiblingDescriptors = null; ISelection selection = event.getSelection(); if (selection instanceof IStructuredSelection && ((IStructuredSelection)selection).size() == 1) { Object object = ((IStructuredSelection)selection).getFirstElement(); //We set the domain according to the current selection in the view if (event.getSelection() instanceof IStructuredSelection && ((IStructuredSelection)event.getSelection()).getFirstElement() instanceof EObject){ domain = TransactionUtil.getEditingDomain(((EObject)((IStructuredSelection)event.getSelection()).getFirstElement())); } else domain = ((PLMDiagramEditor)getSite().getWorkbenchWindow().getActivePage().getActiveEditor()).getEditingDomain(); // If there is an adapter of the correct type... // IEditingDomainItemProvider provider = (IEditingDomainItemProvider) factory.adapt(object, IEditingDomainItemProvider.class); newChildDescriptors = provider.getNewChildDescriptors(object, domain, null); //*************************************************************** // This is a workaround to be able to add a DSLVisualizer to // a LMLVisualizer //*************************************************************** if (object instanceof LMLVisualizer) newChildDescriptors = getDomainSpecificVisualizerChildMenuEntries(object); //Needs to be replaced with similar code as for children newSiblingDescriptors = domain.getNewChildDescriptors(null, object); } // Generate actions for selection; populate and redraw the menus. // createChildActions = generateCreateChildActions(newChildDescriptors, selection); createSiblingActions = generateCreateSiblingActions(newSiblingDescriptors, selection); if (createChildMenuManager != null) { populateManager(createChildMenuManager, createChildActions, null); createChildMenuManager.update(true); } if (createSiblingMenuManager != null) { populateManager(createSiblingMenuManager, createSiblingActions, null); createSiblingMenuManager.update(true); } setSelection(selection); propertySheetPage.refresh(); } /** * This method is used as workaround to support splitted meta-models. The * LMLVisualizerItemProvider does not know about the types available in * visualization meta-models which reference the PLM. Thus these types * are added manually to the childe menu with this method. This is done * by searching for meta-models provided through IVisualizationServiceBase * in future releases. * * @param object The owner of the newly created model element * @return an array with command parameters for all DSL extensions */ private Collection<?> getDomainSpecificVisualizerChildMenuEntries( Object object) { Collection<?> newChildDescriptors; ArrayList<CommandParameter> commands = new ArrayList<CommandParameter>(); for(IVisualizationServiceBase visualizationService : activeVisualizationServices){ CommandParameter parameter = new CommandParameter(object, PLMPackage.eINSTANCE.getLMLVisualizer_DslVisualizer(), visualizationService.createNewSpecificDSLVisualizer()); commands.add(parameter); } newChildDescriptors = commands; return newChildDescriptors; } protected void depopulateManager(IContributionManager manager, Collection<? extends IAction> actions) { if (actions != null) { IContributionItem[] items = manager.getItems(); for (int i = 0; i < items.length; i++) { // Look into SubContributionItems // IContributionItem contributionItem = items[i]; while (contributionItem instanceof SubContributionItem) { contributionItem = ((SubContributionItem)contributionItem).getInnerItem(); } // Delete the ActionContributionItems with matching action. // if (contributionItem instanceof ActionContributionItem) { IAction action = ((ActionContributionItem)contributionItem).getAction(); if (actions.contains(action)) { manager.remove(contributionItem); } } } } } protected void populateManager(IContributionManager manager, Collection<? extends IAction> actions, String contributionID) { if (actions != null) { for (IAction action : actions) { if (contributionID != null) { manager.insertBefore(contributionID, action); } else { manager.add(action); } } } } protected Collection<IAction> generateCreateChildActions(Collection<?> descriptors, ISelection selection) { Collection<IAction> actions = new ArrayList<IAction>(); if (descriptors != null) { for (Object descriptor : descriptors) { //EditingDomain domain = ((PLMDiagramEditor)getSite().getWorkbenchWindow().getActivePage().getActiveEditor()).getEditingDomain(); actions.add(new CreateChildAction(domain, selection, descriptor)); } } return actions; } protected Collection<IAction> generateCreateSiblingActions(Collection<?> descriptors, ISelection selection) { Collection<IAction> actions = new ArrayList<IAction>(); if (descriptors != null) { for (Object descriptor : descriptors) { //EditingDomain domain = ((PLMDiagramEditor)getSite().getWorkbenchWindow().getActivePage().getActiveEditor()).getEditingDomain(); actions.add(new CreateSiblingAction(domain, selection, descriptor)); } } return actions; } }; @Override public void setFocus() { // TODO Auto-generated method stub } @Override public void dispose() { //Throws exception if workbench is closing -> We do not care about this try{ //Remove the listener getSite().getPage().removeSelectionListener(this); getSite().setSelectionProvider(null); propertySheetPage = null; }catch(Exception ex){} super.dispose(); } private class ChangeListener extends EContentAdapter{ @Override public void notifyChanged(Notification notification) { super.notifyChanged(notification); viewer.refresh(); if (viewer.getTree().getSelection().length > 0) viewer.getTree().getSelection()[0].setExpanded(true); viewer.refresh(); } } List<ISelectionChangedListener> listeners = new LinkedList<ISelectionChangedListener>(); @Override public void addSelectionChangedListener(ISelectionChangedListener listener) { listeners.add(listener); } @Override public ISelection getSelection() { return viewer.getSelection(); } @Override public void removeSelectionChangedListener( ISelectionChangedListener listener) { listeners.remove(listener); } ISelection viewSelection; @Override public void setSelection(ISelection selection) { for (ISelectionChangedListener l : listeners) l.selectionChanged(new SelectionChangedEvent(viewer, selection)); viewSelection = selection; } }