/******************************************************************************* * Copyright (c) 2014, 2015 Cisco Systems, Inc. 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 * *******************************************************************************/ package com.cisco.yangide.ext.model.editor.editors; import org.eclipse.core.resources.IFile; import org.eclipse.emf.common.notify.Notification; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EContentAdapter; import org.eclipse.emf.transaction.RecordingCommand; import org.eclipse.gef.GraphicalViewer; import org.eclipse.graphiti.features.IRemoveFeature; import org.eclipse.graphiti.features.context.impl.RemoveContext; import org.eclipse.graphiti.mm.pictograms.ContainerShape; import org.eclipse.graphiti.mm.pictograms.Diagram; import org.eclipse.graphiti.mm.pictograms.PictogramElement; import org.eclipse.graphiti.services.Graphiti; import org.eclipse.graphiti.ui.editor.DiagramBehavior; import org.eclipse.graphiti.ui.editor.DiagramEditor; import org.eclipse.graphiti.ui.editor.IDiagramEditorInput; import org.eclipse.graphiti.ui.platform.GraphitiShapeEditPart; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.ControlListener; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.ui.IEditorInput; import com.cisco.yangide.core.dom.ASTNode; import com.cisco.yangide.editor.editors.YangEditor; import com.cisco.yangide.ext.model.ModelPackage; import com.cisco.yangide.ext.model.Module; import com.cisco.yangide.ext.model.Node; import com.cisco.yangide.ext.model.editor.diagram.EditorFeatureProvider; import com.cisco.yangide.ext.model.editor.util.DiagramImportSupport; import com.cisco.yangide.ext.model.editor.util.LayoutUtil; import com.cisco.yangide.ext.model.editor.util.YangModelUIUtil; import com.cisco.yangide.ext.model.editor.util.YangModelUtil; public class YangDiagramEditor extends DiagramEditor { private Module module; private YangDiagramModuleInfoPanel infoPane; private ISourceModelManager sourceModelManager; private final YangEditor sourceEditor; public YangDiagramEditor(YangEditor sourceEditor) { super(); this.sourceEditor = sourceEditor; } private IModelChangeHandler modelChangeHandler = new IModelChangeHandler() { @Override public void nodeRemoved(Node node) { System.out.println("Removed " + node); PictogramElement[] elements = getDiagramTypeProvider().getFeatureProvider() .getAllPictogramElementsForBusinessObject(node); for (PictogramElement element : elements) { RemoveContext context = new RemoveContext(element); IRemoveFeature feature = getDiagramTypeProvider().getFeatureProvider().getRemoveFeature(context); getDiagramBehavior().executeFeature(feature, context); } infoPane.update(); } @Override public void nodeChanged(Node node, EObject object, Object newValue) { System.out.println("Changed " + node); if (object instanceof EAttribute) { PictogramElement pe = YangModelUIUtil.getBusinessObjectPropShape( getDiagramTypeProvider().getFeatureProvider(), node, (EAttribute) object); if (null != pe) { YangModelUIUtil.updatePictogramElement(getDiagramTypeProvider().getFeatureProvider(), pe); } } infoPane.update(); } @Override public void nodeAdded(Node parent, Node child, int position) { System.out.println("Added " + child); if (null == YangModelUIUtil.getBusinessObjectShape(getDiagramTypeProvider().getFeatureProvider(), child)) { Point p = null; if (parent instanceof Module) { p = ((YangDiagramBehavior) getDiagramBehavior()).getCreatePosition(); } PictogramElement pe = YangModelUIUtil .getBusinessObjectShape(getDiagramTypeProvider().getFeatureProvider(), parent); if (null != pe && pe instanceof ContainerShape) { YangModelUIUtil.drawObject(child, (ContainerShape) pe, getDiagramTypeProvider().getFeatureProvider(), null == p ? 0 : p.x, null == p ? 0 : p.y); if (pe instanceof Diagram && null == p) { getEditingDomain().getCommandStack().execute(new RecordingCommand(getEditingDomain()) { @Override protected void doExecute() { LayoutUtil.layoutDiagram(getDiagramTypeProvider().getFeatureProvider()); } }); } } ((YangDiagramBehavior) getDiagramBehavior()).setCreatePosition(null); infoPane.update(); } } }; private URI uri; @Override protected DiagramBehavior createDiagramBehavior() { return new YangDiagramBehavior(this); } private boolean layouted = false; private Diagram diagram; private Point diagramSize = new Point(1200, 200); private SourceSelectionUpdater sourceSelectionUpdater; @Override public void createPartControl(final Composite parent) { GridLayout layout = new GridLayout(); layout.numColumns = 1; layout.makeColumnsEqualWidth = false; layout.verticalSpacing = 0; layout.marginTop = 0; layout.marginBottom = 0; layout.marginHeight = 0; parent.setLayout(layout); infoPane = new YangDiagramModuleInfoPanel(parent, module, getFile()); super.createPartControl(infoPane.getDiagram()); for (Control c : infoPane.getDiagram().getChildren()) { if (!infoPane.equals(c)) { c.setLayoutData(new GridData(GridData.FILL_BOTH)); } } final GraphicalViewer viewer = (GraphicalViewer) YangDiagramEditor.this.getAdapter(GraphicalViewer.class); viewer.getControl().addControlListener(new ControlListener() { @Override public void controlResized(ControlEvent e) { if (viewer.getControl().isDisposed()) { return; } diagramSize = viewer.getControl().getSize(); ((EditorFeatureProvider) getDiagramTypeProvider().getFeatureProvider()).updateDiagramSize(diagramSize.x, diagramSize.y); if (!layouted && diagramSize.x != 0 && diagramSize.y != 0) { layouted = true; YangModelUIUtil.layoutPictogramElement(diagram, getDiagramTypeProvider().getFeatureProvider()); viewer.select(viewer.getRootEditPart()); viewer.reveal(viewer.getRootEditPart()); } } @Override public void controlMoved(ControlEvent e) { } }); loadDiagram(); } @Override public void initializeGraphicalViewer() { super.initializeGraphicalViewer(); GraphicalViewer graphicalViewer = getGraphicalViewer(); if (graphicalViewer != null) { graphicalViewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { ((YangDiagramBehavior) getDiagramBehavior()).getYangPaletteBehavior() .updateSelection(event.getSelection()); } }); } sourceSelectionUpdater = new SourceSelectionUpdater(); } @Override protected void setInput(IEditorInput input) { super.setInput(input); uri = ((IDiagramEditorInput) input).getUri(); module = ((YangDiagramEditorInput) input).getModule(); // added self changes listener module.eAdapters().add(new EContentAdapter() { @Override public void notifyChanged(Notification notification) { if (notification.getNotifier() instanceof Node) { if (notification.getFeature() == ModelPackage.Literals.NAMED_NODE__NAME || notification.getFeature() == ModelPackage.Literals.USES__QNAME || notification.getFeature() == ModelPackage.Literals.REFERENCE_NODE__REFERENCE || notification.getFeature() == ModelPackage.Literals.SUBMODULE__BELONGS_TO) { if (notification.getNewValue() != null && !notification.getNewValue().equals(notification.getOldValue())) { modelChangeHandler.nodeChanged((Node) notification.getNotifier(), (EObject) notification.getFeature(), notification.getNewValue()); final EClass type = YangModelUtil .getConnectionReferenceSubjectClass(notification.getNotifier()); if (null != type) { getDiagramBehavior().getEditingDomain().getCommandStack() .execute(new RecordingCommand(getDiagramBehavior().getEditingDomain()) { @Override protected void doExecute() { YangModelUIUtil.updateConnections(type, getDiagramTypeProvider().getFeatureProvider()); } }); } } } } super.notifyChanged(notification); } }); loadDiagram(); } private void loadDiagram() { if (getGraphicalViewer() != null) { getEditingDomain().getCommandStack().execute(new RecordingCommand(getEditingDomain()) { @Override protected void doExecute() { ensureDiagramResource(uri); importDiagram(); } }); } } private void ensureDiagramResource(URI uri) { final Resource resource = getEditingDomain().getResourceSet().createResource(uri); getEditingDomain().getCommandStack().execute(new RecordingCommand(getEditingDomain()) { @Override protected void doExecute() { resource.setTrackingModification(true); resource.getContents().add(getDiagramTypeProvider().getDiagram()); } }); } private void importDiagram() { if (null != module) { diagram = getDiagramTypeProvider().getDiagram(); getDiagramTypeProvider().getFeatureProvider().link(diagram, module); DiagramImportSupport.importDiagram(diagram, getDiagramTypeProvider().getFeatureProvider()); } } /** * @return */ public IModelChangeHandler getModelChangeHandler() { return modelChangeHandler; } public void setSourceModelManager(ISourceModelManager sourceModelManager) { ((EditorFeatureProvider) getDiagramTypeProvider().getFeatureProvider()) .setSourceModelManager(sourceModelManager); this.sourceModelManager = sourceModelManager; } private IFile getFile() { return ((YangDiagramEditorInput) getEditorInput()).getFile(); } /** * Enables selection of source code element that corresponds to the selected diagram shape. */ public void startSourceSelectionUpdater() { GraphicalViewer graphicalViewer = getGraphicalViewer(); if (graphicalViewer != null) graphicalViewer.addSelectionChangedListener(sourceSelectionUpdater); } /** * Disables selection of source code element that corresponds to the selected diagram shape. */ public void stopSourceSelectionUpdater() { GraphicalViewer graphicalViewer = getGraphicalViewer(); if (graphicalViewer != null) graphicalViewer.removeSelectionChangedListener(sourceSelectionUpdater); } private class SourceSelectionUpdater implements ISelectionChangedListener { @Override public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection selection = (IStructuredSelection) event.getSelection(); Object object = selection.getFirstElement(); if (object instanceof GraphitiShapeEditPart) { PictogramElement element = (PictogramElement) ((GraphitiShapeEditPart) object).getPictogramElement(); EObject node = Graphiti.getLinkService().getBusinessObjectForLinkedPictogramElement(element); ASTNode moduleNode = sourceModelManager.getModuleNode((Node) node); IRegion region = YangEditor.getSelectionRegion(moduleNode); if (region != null) { sourceEditor.setHighlightRange(region.getOffset(), region.getLength(), true); // sourceEditor.selectAndReveal(...) doesn't work here since projection is // disabled } } } } }