/* * 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.mapping.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.GraphicalEditPart; import org.eclipse.gef.LayerConstants; import org.eclipse.gef.Request; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.swt.graphics.RGB; 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.NodeConnectionModel; import org.teiid.designer.diagram.ui.editor.DiagramViewer; import org.teiid.designer.diagram.ui.model.DiagramModelNode; import org.teiid.designer.diagram.ui.notation.uml.figure.UmlClassifierFigure; import org.teiid.designer.diagram.ui.notation.uml.part.UmlClassifierEditPart; 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.part.ExpandableDiagram; import org.teiid.designer.diagram.ui.util.DiagramXYLayoutEditPolicy; import org.teiid.designer.diagram.ui.util.LassoDragTracker; import org.teiid.designer.mapping.ui.PluginConstants; import org.teiid.designer.mapping.ui.editor.MappingDiagramController; import org.teiid.designer.mapping.ui.model.MappingDiagramNode; import org.teiid.designer.mapping.ui.model.MappingExtentNode; import org.teiid.designer.mapping.ui.util.MappingUiUtil; import org.teiid.designer.metamodels.diagram.Diagram; import org.teiid.designer.metamodels.transformation.MappingClass; import org.teiid.designer.metamodels.xml.XmlDocumentNode; import org.teiid.designer.ui.IDiagramTypeEditPart; import org.teiid.designer.ui.common.graphics.GlobalUiColorManager; /** * TransformationDiagramEditPart * * @since 8.0 */ public class MappingDiagramEditPart extends AbstractDiagramEditPart implements ExpandableDiagram, IDiagramTypeEditPart { // =========================================================================================================================== // Static Variables /** Singleton instance of MarqueeDragTracker. */ private static DragTracker m_dragTracker = null; // =========================================================================================================================== // Variables private String sCurrentRouterStyle = DiagramUiConstants.DiagramRouterStyles.FAN_ROUTER; // private static int layout_ExecutionsCount = 0; private boolean bLayoutInProgress = false; // private List lstTreeOrderedMappingClassList; // =========================================================================================================================== // Methods /** * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#addChildVisual(org.eclipse.gef.EditPart, int) * @since 5.0 */ @Override protected void addChildVisual( EditPart childEditPart, int index ) { IFigure child = ((GraphicalEditPart)childEditPart).getFigure(); Object obj = childEditPart.getModel(); if (obj instanceof DiagramModelNode) { DiagramModelNode model = (DiagramModelNode)obj; obj = model.getModelObject(); if (obj instanceof MappingClass && ((MappingClass)obj).isRecursive() && child instanceof UmlClassifierFigure) { if (MappingUiUtil.getCurrentTreeMappingAdapter() != null) { obj = MappingUiUtil.getCurrentTreeMappingAdapter().getMappingClassLocation((MappingClass)obj); if (obj instanceof XmlDocumentNode && ((XmlDocumentNode)obj).isExcludeFromDocument()) { ((UmlClassifierFigure)child).getEditButton().setEnabled(false); } } } } getContentPane().add(child, index); } /** * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure() */ @Override protected IFigure createFigure() { Figure newFigure = getFigureFactory().createFigure(getModel()); setCurrentDiagramFont(ScaledFontManager.getFont()); return newFigure; } /** * @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; } @Override public void layout( boolean layoutChildren ) { 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()) { 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(); } } } private boolean hasChildren() { if (getViewer().getContents().getChildren().size() > 0) return true; return false; } @Override public void layout() { // System.out.println("\n\n[MappingDiagramLayout.layout_ExecutionsCount] Execution: " + ++layout_ExecutionsCount ); // System.out.println("[MappingDiagramLayout.layout_ExecutionsCount] I am a: " + this.getModelObject() ); if (bLayoutInProgress) { // no action if layout is already in progress // System.out.println("[MappingDiagramEditPart.layout] Bailing out, layout is in progress..."); return; } // System.out.println("[MappingDiagramEditPart.layout] Continuing, starting a new layout..."); bLayoutInProgress = true; // Let's just use the TransformationDiagramLayout here and not the manager. MappingDiagramLayout diagramLayout = new MappingDiagramLayout((DiagramModelNode)getModel(), isCoarseMapping()); // if running in "Detailed" mode, we need find the lowest value "extent" y int yValue = getLowestYExtentValue(); if (!isCoarseMapping()) { MappingDiagramController controller = (MappingDiagramController)((DiagramViewer)getViewer()).getEditor().getDiagramController(); if (controller != null) { yValue = yValue + controller.getScrollOffset(); } } diagramLayout.run(120, yValue); // Update Anchors and Links updateAnchorsAndLinks(); bLayoutInProgress = false; this.getFigure().repaint(); } 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); } } } private int getLowestYExtentValue() { int minYValue = 20; int yValue = -99; EditPart canvasEditPart = getViewer().getContents(); Iterator iter = canvasEditPart.getChildren().iterator(); DiagramEditPart nextEditPart = null; int partY = 0; while (iter.hasNext()) { nextEditPart = (DiagramEditPart)iter.next(); if (nextEditPart instanceof MappingExtentEditPart) { partY = ((DiagramModelNode)nextEditPart.getModel()).getY(); if (yValue < 0) yValue = partY; else yValue = Math.min(partY, yValue); } } if (yValue < minYValue) yValue = minYValue; return yValue; } private boolean isClassifer( DiagramEditPart editPart ) { return editPart instanceof UmlClassifierEditPart; } public TopAndBottomClassifierInfo getTopAndBottomClassifierInfo() { TopAndBottomClassifierInfo tab = new TopAndBottomClassifierInfo(); boolean firstRun = true; EditPart canvasEditPart = getViewer().getContents(); Iterator iter = canvasEditPart.getChildren().iterator(); DiagramEditPart nextEditPart = null; while (iter.hasNext()) { nextEditPart = (DiagramEditPart)iter.next(); if (isClassifer(nextEditPart)) { DiagramModelNode diagramModelNode = (DiagramModelNode)nextEditPart.getModel(); int topY = diagramModelNode.getY(); int bottomY = topY + diagramModelNode.getHeight(); if (firstRun) { // first time, just take the current EP as everything: firstRun = false; tab.bottomPart = nextEditPart; tab.topPart = nextEditPart; tab.bottomY = bottomY; tab.topY = topY; } else { // not the first time, check both top and bottom bounds: if (bottomY > tab.bottomY) { tab.bottomY = bottomY; tab.bottomPart = nextEditPart; } // endif if (topY < tab.topY) { tab.topY = topY; tab.topPart = nextEditPart; } // endif } // endif -- firstRun } // endif -- isClassifier } // endwhile -- child editParts return tab; } public int getLowestYValue() { int yValue = 0; EditPart canvasEditPart = getViewer().getContents(); Iterator iter = canvasEditPart.getChildren().iterator(); DiagramEditPart nextEditPart = null; int partY = 0; while (iter.hasNext()) { nextEditPart = (DiagramEditPart)iter.next(); if (nextEditPart.getModel() != null && nextEditPart.getModel() instanceof DiagramModelNode) { partY = ((DiagramModelNode)nextEditPart.getModel()).getY(); yValue = Math.min(partY, yValue); } } return yValue; } public int getHighestYValue() { int yValue = -99; EditPart canvasEditPart = getViewer().getContents(); Iterator iter = canvasEditPart.getChildren().iterator(); DiagramEditPart nextEditPart = null; int partY = 0; while (iter.hasNext()) { nextEditPart = (DiagramEditPart)iter.next(); if (nextEditPart.getModel() != null && nextEditPart.getModel() instanceof DiagramModelNode) { partY = ((DiagramModelNode)nextEditPart.getModel()).getY() + ((DiagramModelNode)nextEditPart.getModel()).getHeight(); yValue = Math.max(partY, yValue); } } return yValue; } /** * Reset font from Font Manager 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 boolean isCoarseMapping() { return ((MappingDiagramNode)getModel()).isCoarse(); } /** * Helper method used to assess whether any edit part contains the same reference EObject as the diagram's target. Implemented * for the MappingClassAnchorManager, so it can treat the MappingClass edit part differently when it's in a Detailed diagram * and it's the primary mapping class, and not a source table * * @param editPart * @return */ public boolean isPrimary( DiagramEditPart editPart ) { boolean primary = false; EObject diagramTarget = ((Diagram)getModelObject()).getTarget(); if (editPart.getModelObject() != null && editPart.getModelObject().equals(diagramTarget)) primary = true; return primary; } @Override public void updateForPreferences() { RGB currentBkgdColor = PreferenceConverter.getColor(DiagramUiPlugin.getDefault().getPreferenceStore(), PluginConstants.Prefs.Appearance.MAPPING_BKGD_COLOR); this.getFigure().setBackgroundColor(GlobalUiColorManager.getColor(currentBkgdColor)); refreshFont(true); layout(false); } /** * @see org.teiid.designer.diagram.ui.part.DiagramEditPart#handleZoomChanged() * @since 4.2 */ @Override public void handleZoomChanged() { // Let's update all mapping extent nodes DiagramEditPart canvasEditPart = (DiagramEditPart)getViewer().getContents(); Iterator iter = canvasEditPart.getChildren().iterator(); DiagramEditPart nextEditPart = null; MappingDiagramNode mdn = (MappingDiagramNode)canvasEditPart.getModel(); int currentYOrigin = mdn.getCurrentYOrigin(); while (iter.hasNext()) { nextEditPart = (DiagramEditPart)iter.next(); if (nextEditPart instanceof MappingExtentEditPart) { MappingExtentNode men = (MappingExtentNode)nextEditPart.getModel(); men.updateModelForExtent(); men.setExtentPosition(currentYOrigin); } } // layout(); } public static class TopAndBottomClassifierInfo { public int topY; public int bottomY; public DiagramEditPart topPart; public DiagramEditPart bottomPart; } @Override public boolean canExpand() { return isCoarseMapping(); } @Override public void collapseAll() { } @Override public void collapse( Object child ) { } @Override public void expandAll() { } @Override public void expand( Object child ) { } @Override public void propertyChange( PropertyChangeEvent evt ) { String prop = evt.getPropertyName(); super.propertyChange(evt); if (prop.equals(DiagramUiConstants.DiagramNodeProperties.COLLAPSE) || prop.equals(DiagramUiConstants.DiagramNodeProperties.EXPAND)) { layout(); } } /** * @see org.teiid.designer.diagram.ui.part.AbstractDefaultEditPart#setUnderConstruction(boolean) * @since 5.0 */ @Override public void setUnderConstruction( boolean theUnderConstruction ) { List contents = this.getChildren(); Iterator iter = contents.iterator(); Object nextObj = null; while (iter.hasNext()) { nextObj = iter.next(); if (nextObj instanceof DiagramEditPart) { ((DiagramEditPart)nextObj).setUnderConstruction(theUnderConstruction); } } super.setUnderConstruction(theUnderConstruction); } }