/** * Copyright (c) 2013 committers of YAKINDU and others. * 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: * committers of YAKINDU - initial API and implementation * */ package org.yakindu.sct.ui.editor.partitioning; import static org.yakindu.sct.ui.editor.partitioning.DiagramPartitioningUtil.openEditor; import java.util.ArrayList; import java.util.Collection; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.edit.domain.IEditingDomainProvider; import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.gef.ContextMenuProvider; import org.eclipse.gef.EditPartViewer; import org.eclipse.gef.GraphicalViewer; import org.eclipse.gmf.runtime.diagram.ui.actions.ActionIds; import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramEditorInput; import org.eclipse.gmf.runtime.diagram.ui.providers.DiagramContextMenuProvider; import org.eclipse.gmf.runtime.diagram.ui.resources.editor.document.IDocumentProvider; import org.eclipse.gmf.runtime.diagram.ui.resources.editor.parts.DiagramDocumentEditor; import org.eclipse.gmf.runtime.notation.Diagram; import org.eclipse.jface.action.IContributionItem; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.viewers.BaseLabelProvider; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITreePathContentProvider; import org.eclipse.jface.viewers.ITreePathLabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TreePath; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerLabel; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorReference; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.ide.FileStoreEditorInput; import org.eclipse.xtext.util.Arrays; import org.yakindu.base.base.NamedElement; import org.yakindu.sct.model.sgraph.Statechart; import org.yakindu.sct.model.sgraph.provider.SGraphItemProviderAdapterFactory; import org.yakindu.sct.ui.editor.StatechartImages; /** * Editor that uses a {@link DiagramPartitioningDocumentProvider} and adds a * {@link DiagramPartitioningBreadcrumbViewer} to the top. * * @author andreas muelder - Initial contribution and API * */ public abstract class DiagramPartitioningEditor extends DiagramDocumentEditor implements ISelectionChangedListener, IEditingDomainProvider { private DiagramPartitioningBreadcrumbViewer viewer; private DiagramPartitioningDocumentProvider documentProvider; public DiagramPartitioningEditor(boolean hasFlyoutPalette) { super(hasFlyoutPalette); documentProvider = new DiagramPartitioningDocumentProvider(); } @Override public TransactionalEditingDomain getEditingDomain() { return DiagramPartitioningUtil.getSharedDomain(); } @Override public IDocumentProvider getDocumentProvider() { return documentProvider; } @Override public void init(IEditorSite site, IEditorInput input) throws PartInitException { if(input instanceof FileStoreEditorInput) { throw new PartInitException( "An error occured while opening the file.\n\n" + "This might have happened because you tried to open a statechart with File->Open File.\n" + "This is not supported. Please import the file into a project instead." ); } super.init(site, input); } @Override public void createPartControl(Composite parent) { GridLayoutFactory.fillDefaults().spacing(0, 0).applyTo(parent); createBreadcrumbViewer(parent); super.createPartControl(parent); } @SuppressWarnings("restriction") @Override protected void sanityCheckState(IEditorInput input) { super.sanityCheckState(input); // Refresh viewer input since the context may have changed if ((getDiagram() != null && viewer != null && !viewer.getControl().isDisposed())) viewer.setInput(DiagramPartitioningUtil.getDiagramContainerHierachy(getDiagram())); } @Override public void setInput(IEditorInput input) { super.setInput(input); if (input instanceof IDiagramEditorInput) { initializeTitle((IDiagramEditorInput) input); } } protected void initializeTitle(IDiagramEditorInput input) { Diagram diagram = input.getDiagram(); EObject element = diagram.getElement(); AdapterFactoryLabelProvider labelProvider = new AdapterFactoryLabelProvider( new SGraphItemProviderAdapterFactory()); setTitleImage(labelProvider.getImage(element)); setPartName(labelProvider.getText(element)); } @Override protected void configureGraphicalViewer() { super.configureGraphicalViewer(); configureContextMenu(); } protected void configureContextMenu() { GraphicalViewer graphicalViewer = getGraphicalViewer(); ContextMenuProvider provider = new FilteringDiagramContextMenuProvider(this, graphicalViewer); graphicalViewer.setContextMenu(provider); getSite().registerContextMenu(ActionIds.DIAGRAM_EDITOR_CONTEXT_MENU, provider, viewer); } protected void createBreadcrumbViewer(Composite parent) { viewer = new DiagramPartitioningBreadcrumbViewer(parent, SWT.READ_ONLY); viewer.addSelectionChangedListener(this); viewer.setContentProvider(new BreadcrumbViewerContentProvider()); viewer.setLabelProvider(new BreadcrumbViewerLabelProvider()); viewer.setInput(DiagramPartitioningUtil.getDiagramContainerHierachy(getDiagram())); parent.pack(true); } @Override protected void createGraphicalViewer(Composite parent) { super.createGraphicalViewer(parent); GridDataFactory.fillDefaults().grab(true, true).applyTo(parent); } public void selectionChanged(SelectionChangedEvent event) { Diagram diagramToOpen = (Diagram) ((IStructuredSelection) event.getSelection()).getFirstElement(); openEditor(diagramToOpen); } @Override public void dispose() { closeSubdiagramEditors(); super.dispose(); } protected void closeSubdiagramEditors() { if (getDiagram() != null && getDiagram().getElement() instanceof Statechart) { List<IEditorReference> refsToClose = new ArrayList<IEditorReference>(); IWorkbenchWindow workbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); if (workbenchWindow == null) return; IWorkbenchPage activePage = workbenchWindow.getActivePage(); if (activePage == null) return; IEditorReference[] refs = activePage.getEditorReferences(); for (IEditorReference ref : refs) { try { if (ref.getEditorInput() instanceof IDiagramEditorInput) { IDiagramEditorInput diagramInput = (IDiagramEditorInput) ref.getEditorInput(); if (diagramInput.getDiagram().eResource() == getDiagram().eResource()) { refsToClose.add(ref); } } } catch (PartInitException e) { e.printStackTrace(); } } if (refsToClose.size() > 0) { boolean close = MessageDialog.openQuestion(activePage.getActivePart().getSite().getShell(), "Close subdiagram editors?", "There are still subdiagram editors open. Do you want to close them?"); if (close) { for (IEditorReference ref : refsToClose) { activePage.closeEditor(ref.getEditor(false), false); } } } } } public static final class BreadcrumbViewerLabelProvider extends BaseLabelProvider implements ITreePathLabelProvider { public void updateLabel(ViewerLabel label, TreePath elementPath) { Diagram lastSegment = (Diagram) elementPath.getLastSegment(); NamedElement element = (NamedElement) lastSegment.getElement(); AdapterFactoryLabelProvider provider = new AdapterFactoryLabelProvider( new SGraphItemProviderAdapterFactory()); label.setText(provider.getText(element)); if (element instanceof Statechart) label.setImage(StatechartImages.LOGO.image()); else label.setImage(provider.getImage(element)); } } public static class FilteringDiagramContextMenuProvider extends DiagramContextMenuProvider { // Default context menu items that should be suppressed protected String[] exclude = new String[] { "addNoteLinkAction", "properties", "org.eclipse.mylyn.context.ui.commands.attachment.retrieveContext", "org.eclipse.mylyn.resources.ui.ui.interest.remove.element", "formatMenu", "filtersMenu", "addGroup", "navigateGroup", "toolbarArrangeAllAction", "selectMenu", "diagramAddMenu", "navigateMenu", "viewGroup", "viewMenu" }; protected FilteringDiagramContextMenuProvider(IWorkbenchPart part, EditPartViewer viewer) { super(part, viewer); } protected boolean allowItem(IContributionItem itemToAdd) { if (Arrays.contains(exclude, itemToAdd.getId())) { itemToAdd.setVisible(false); } return super.allowItem(itemToAdd); } } @SuppressWarnings("unchecked") public static final class BreadcrumbViewerContentProvider implements ITreePathContentProvider { private List<IFile> input; public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { if (newInput != null && newInput instanceof List) { input = (List<IFile>) newInput; } } @SuppressWarnings("rawtypes") public Object[] getElements(Object inputElement) { if (inputElement != null && inputElement instanceof Collection) { return ((Collection) inputElement).toArray(); } return null; } public Object[] getChildren(TreePath parentPath) { return input.subList(parentPath.getSegmentCount(), input.size()).toArray(); } public void dispose() { input = null; } public boolean hasChildren(TreePath path) { return false; } public TreePath[] getParents(Object element) { return null; } } }