/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.transformation.ui.part; import java.beans.PropertyChangeEvent; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.eclipse.draw2d.ConnectionLayer; import org.eclipse.draw2d.FanRouter; import org.eclipse.draw2d.Figure; import org.eclipse.draw2d.IFigure; import org.eclipse.emf.ecore.EObject; import org.eclipse.gef.DragTracker; import org.eclipse.gef.EditPart; import org.eclipse.gef.EditPolicy; import org.eclipse.gef.LayerConstants; import org.eclipse.gef.Request; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.widgets.Display; import org.teiid.designer.diagram.ui.DiagramUiConstants; import org.teiid.designer.diagram.ui.DiagramUiPlugin; import org.teiid.designer.diagram.ui.actions.ScaledFontManager; import org.teiid.designer.diagram.ui.connection.NodeConnectionEditPart; import org.teiid.designer.diagram.ui.connection.NodeConnectionModel; import org.teiid.designer.diagram.ui.layout.DefaultLayoutNode; import org.teiid.designer.diagram.ui.layout.LayoutGroup; import org.teiid.designer.diagram.ui.layout.LayoutHelper; import org.teiid.designer.diagram.ui.layout.LayoutNode; import org.teiid.designer.diagram.ui.layout.LayoutUtilities; import org.teiid.designer.diagram.ui.layout.MmTreeLayout; import org.teiid.designer.diagram.ui.layout.TreeLayout; import org.teiid.designer.diagram.ui.layout.spring.SpringLayout; import org.teiid.designer.diagram.ui.model.AbstractFreeDiagramModelNode; import org.teiid.designer.diagram.ui.model.DiagramModelNode; import org.teiid.designer.diagram.ui.part.AbstractDefaultEditPart; import org.teiid.designer.diagram.ui.part.AbstractDiagramEditPart; import org.teiid.designer.diagram.ui.part.AbstractFreeEditPart; import org.teiid.designer.diagram.ui.part.DiagramEditPart; import org.teiid.designer.diagram.ui.util.DiagramUiUtilities; import org.teiid.designer.diagram.ui.util.DiagramXYLayoutEditPolicy; import org.teiid.designer.diagram.ui.util.LassoDragTracker; import org.teiid.designer.metamodels.diagram.Diagram; import org.teiid.designer.transformation.ui.PluginConstants; import org.teiid.designer.ui.IDiagramTypeEditPart; import org.teiid.designer.ui.common.graphics.GlobalUiColorManager; import org.teiid.designer.ui.editors.ModelEditorManager; import org.teiid.query.ui.UiConstants; import org.teiid.query.ui.UiPlugin; /** * TransformationDiagramEditPart * * @since 8.0 */ public class TransformationDiagramEditPart extends AbstractDiagramEditPart implements IPropertyChangeListener, IDiagramTypeEditPart { /** Singleton instance of MarqueeDragTracker. */ static DragTracker m_dragTracker = null; private boolean isDependencyDiagram = false; private TransformationDiagramLayout diagramLayout = new TransformationDiagramLayout(); private String sCurrentRouterStyle = DiagramUiConstants.DiagramRouterStyles.FAN_ROUTER; /** * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure() **/ @Override protected IFigure createFigure() { Figure newFigure = getFigureFactory().createFigure(getModel()); setCurrentDiagramFont(ScaledFontManager.getFont()); // Set dependency diagram boolean if necessary. if( getDiagramType() != null && getDiagramType().equals(PluginConstants.DEPENDENCY_DIAGRAM_TYPE_ID) ) isDependencyDiagram = true; return newFigure; } private String getDiagramType() { return ((Diagram)((DiagramModelNode)getModel()).getModelObject()).getType(); } /** * @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies() * You need to tell how children nodes will be layed out... **/ @Override protected void createEditPolicies() { setSelectablePart(false); installEditPolicy(EditPolicy.LAYOUT_ROLE, new DiagramXYLayoutEditPolicy()); } /** * This method is not mandatory to implement, but if you do not implement * it, you will not have the ability to rectangle-selects several figures... **/ @Override public DragTracker getDragTracker(Request req) { // Unlike in Logical Diagram Editor example, I use a singleton because this // method is Entered >> several time, so I prefer to save memory ; and it works! if (m_dragTracker == null) { m_dragTracker = new LassoDragTracker(); } return m_dragTracker; } private boolean hasChildren() { if( getViewer().getContents().getChildren().size() > 0 ) return true; return false; } /* (non-JavaDoc) * @see java.beans.PropertyChangeListener#propertyChange(PropertyChangeEvent) **/ @Override public void propertyChange(PropertyChangeEvent evt) { super.propertyChange(evt); String prop = evt.getPropertyName(); if (prop.equals(DiagramUiConstants.DiagramNodeProperties.CHILDREN)) { layout(); } if (prop.equals(DiagramUiConstants.DiagramNodeProperties.LAYOUT)) { layout(); } } /** * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent) * @since 5.0 */ @Override public void propertyChange(org.eclipse.jface.util.PropertyChangeEvent theEvent) { if (theEvent.getProperty().equals(UiConstants.Prefs.TREE_DIAGRAM_LAYOUT)) { // We need to re-open the diagram to fully re-draw and layout. Display.getDefault().asyncExec(new Runnable() { @Override public void run() { ModelEditorManager.open(getModelObject(), true); } }); // now we need to re-layout the diagram } } @Override public void layout(boolean layoutChildren) { if( !hasChildren() ) return; if( layoutChildren) { EditPart canvasEditPart = getViewer().getContents(); List canvasChildren = canvasEditPart.getChildren(); Iterator iter = canvasChildren.iterator(); EditPart nextEditPart = null; while (iter.hasNext()) { nextEditPart = (EditPart)iter.next(); if ( nextEditPart instanceof DiagramEditPart ) { ((DiagramEditPart)nextEditPart).layout(layoutChildren); } } } // super.layout(layoutChildren); // Check it's model node, if was layed out, don't re-layout!! if( !((DiagramModelNode)getModel()).wasLayedOut() || isDependencyDiagram ) { layout(); } else { ((DiagramModelNode)getModel()).recoverObjectProperties(); } // now process the Association Labels, if any: List arylSourceConnections = new ArrayList(); if ( !arylSourceConnections.isEmpty() ) { Iterator itSourceConns = arylSourceConnections.iterator(); while( itSourceConns.hasNext() ) { NodeConnectionModel ncmSourceConn = (NodeConnectionModel)itSourceConns.next(); ncmSourceConn.setRouterStyle( sCurrentRouterStyle ); ncmSourceConn.layout(); } } } @Override public void layout() { if( !hasChildren() ) return; if( getDiagramType() != null && getDiagramType().equals(PluginConstants.DEPENDENCY_DIAGRAM_TYPE_ID) ) { runDependencyLayout(); } else { // Let's just use the TransformationDiagramLayout here and not the manager. diagramLayout.setDiagramNode((DiagramModelNode)getModel()); diagramLayout.run(); this.getFigure().repaint(); } // Update Anchors and Links updateAnchorsAndLinks(); } private void runDependencyLayout() { EObject primaryVG = ((Diagram)((DiagramModelNode)getModel()).getModelObject()).getTarget(); DiagramModelNode vgDiagramNode = DiagramUiUtilities.getDiagramModelNode(primaryVG, (DiagramModelNode)getModel()); // Now let's create a layoutGroup with only TNodes and Tables List tNodesAndTables = new ArrayList(); List allChildren = ((DiagramModelNode)getModel()).getChildren(); Iterator iter = allChildren.iterator(); Object nextNode = null; while (iter.hasNext()) { nextNode = iter.next(); if ( nextNode instanceof DiagramModelNode && !(nextNode instanceof AbstractFreeDiagramModelNode)) { // Add each component (table or transformation) to the layout manager. tNodesAndTables.add( nextNode ); } } LayoutGroup layoutGroup = new LayoutGroup(tNodesAndTables); if( layoutGroup.getType() == LayoutHelper.SIMPLE_LAYOUT ) { LayoutNode rootNode = new DefaultLayoutNode(vgDiagramNode); // LayoutUtilities.runTreeLayout(layoutGroup, rootNode); TreeLayout layout = new TreeLayout(layoutGroup.getLayoutNodes(), 10, 10, 400, 400); layout.setRoot(rootNode); layout.setOrientation(MmTreeLayout.ORIENTATION_ROOT_LEFT); layout.setFixedSpacing(true); layout.setFixedXSpacing(100); layout.setFixedYSpacing(100); layout.setUseObjectsSizes(true); layout.run(); layoutGroup.setFinalPositions(); } else { // Use Spring Layout here LayoutUtilities.runColumnLayout(layoutGroup, 20); SpringLayout layout = new SpringLayout(layoutGroup.getLayoutNodes()); layout.setAutoEdgeLength(true); layout.setStartLocation(20, 20); layout.setAutomaticSingleSpacing(true); layout.setSpecifyLayoutSize(true); layout.setEpsilon(.2); layout.setHorizontalAlignment(SpringLayout.LEFT_ALIGNMENT); layout.setUseObjectsSizes(false); layout.setVerticalAlignment(SpringLayout.TOP_ALIGNMENT); layout.setXSpacing(400); layout.setYSpacing(400); int size = (int)layout.getSizeEstimate(); layout.setLayoutSize(size*2); layout.run(); layoutGroup.setFinalPositions(); } } private void updateAnchorsAndLinks() { EditPart canvasEditPart = getViewer().getContents(); List canvasChildren = canvasEditPart.getChildren(); Iterator iter = canvasChildren.iterator(); EditPart nextEditPart = null; while (iter.hasNext()) { nextEditPart = (EditPart)iter.next(); if ( nextEditPart instanceof DiagramEditPart && ! (nextEditPart instanceof AbstractFreeEditPart )) { ((DiagramEditPart)nextEditPart).createOrUpdateAnchorsLocations(false); ((AbstractDefaultEditPart)nextEditPart).refreshAllLabels(); } } } public boolean hasConnections() { EditPart canvasEditPart = getViewer().getContents(); Iterator iter = canvasEditPart.getChildren().iterator(); DiagramEditPart nextEditPart = null; while (iter.hasNext()) { nextEditPart = (DiagramEditPart)iter.next(); if( !nextEditPart.getSourceConnections().isEmpty() || !nextEditPart.getTargetConnections().isEmpty() ) return true; } return false; } /** * Reset font from Font Managar and call layout on all diagram objects. **/ @Override public void refreshFont(boolean refreshChildren) { // Diagram needs to also do a layout here super.refreshFont(refreshChildren); // But not at the diagram level if( hasChildren()) { EditPart canvasEditPart = getViewer().getContents(); List canvasChildren = canvasEditPart.getChildren(); Iterator iter = canvasChildren.iterator(); EditPart nextEditPart = null; while (iter.hasNext()) { nextEditPart = (EditPart)iter.next(); if ( nextEditPart instanceof DiagramEditPart ) { ((DiagramEditPart)nextEditPart).layout(true); } } } } /** * @see org.eclipse.gef.editparts.AbstractEditPart#refreshVisuals() **/ @Override protected void refreshVisuals() { ConnectionLayer cLayer = (ConnectionLayer)getLayer(LayerConstants.CONNECTION_LAYER); if ( sCurrentRouterStyle.equals( DiagramUiConstants.DiagramRouterStyles.FAN_ROUTER ) ) { cLayer.setConnectionRouter(new FanRouter()); } } public DiagramEditPart getTransformEditPart() { EditPart canvasEditPart = getViewer().getContents(); Iterator iter = canvasEditPart.getChildren().iterator(); DiagramEditPart nextEditPart = null; while (iter.hasNext()) { nextEditPart = (DiagramEditPart)iter.next(); if( nextEditPart instanceof TransformationEditPart ) return nextEditPart; } return null; } public DiagramModelNode getTargetOfTransform() { DiagramModelNode targetGroupNode = null; // get TransformDiagramNode. DiagramEditPart transformEP = getTransformEditPart(); if( transformEP != null ) { // get it's source connections. List sourceConnections = transformEP.getSourceConnections(); // get the "targetNode" on this connection. if( sourceConnections.size() == 1 ) { NodeConnectionEditPart sourceConnection = (NodeConnectionEditPart)sourceConnections.iterator().next(); targetGroupNode = (DiagramModelNode)((NodeConnectionModel)sourceConnection.getModel()).getTargetNode(); } } return targetGroupNode; } @Override public void updateForPreferences() { RGB currentBkgdColor; if (isDependencyDiagram) { // dependency diagram: currentBkgdColor = PreferenceConverter.getColor( DiagramUiPlugin.getDefault().getPreferenceStore(), PluginConstants.Prefs.Appearance.DEPENDENCY_BKGD_COLOR); } else { // regular transformation diagram: currentBkgdColor = PreferenceConverter.getColor( DiagramUiPlugin.getDefault().getPreferenceStore(), PluginConstants.Prefs.Appearance.TRANSFORM_BKGD_COLOR); } // endif this.getFigure().setBackgroundColor(GlobalUiColorManager.getColor(currentBkgdColor)); refreshFont(true); layout(false); } /** * @see org.teiid.designer.diagram.ui.part.AbstractDefaultEditPart#activate() * @since 5.0 */ @Override public void activate() { super.activate(); UiPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this); } /** * @see org.teiid.designer.diagram.ui.part.AbstractDefaultEditPart#deactivate() * @since 5.0 */ @Override public void deactivate() { super.deactivate(); UiPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this); } }