/*
* 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.diagram.ui.pakkage;
import java.beans.PropertyChangeEvent;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.eclipse.draw2d.AutomaticRouter;
import org.eclipse.draw2d.BendpointConnectionRouter;
import org.eclipse.draw2d.ConnectionLayer;
import org.eclipse.draw2d.FanRouter;
import org.eclipse.draw2d.Figure;
import org.eclipse.draw2d.IFigure;
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.swt.graphics.RGB;
import org.teiid.designer.diagram.ui.DiagramUiConstants;
import org.teiid.designer.diagram.ui.DiagramUiPlugin;
import org.teiid.designer.diagram.ui.PluginConstants;
import org.teiid.designer.diagram.ui.actions.ScaledFontManager;
import org.teiid.designer.diagram.ui.connection.BlockConnectionRouter;
import org.teiid.designer.diagram.ui.connection.NodeConnectionModel;
import org.teiid.designer.diagram.ui.editor.DiagramEditorUtil;
import org.teiid.designer.diagram.ui.layout.LayoutHelper;
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.DiagramEditPart;
import org.teiid.designer.diagram.ui.part.LabelEditPart;
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.DiagramLinkType;
import org.teiid.designer.ui.IDiagramTypeEditPart;
import org.teiid.designer.ui.common.graphics.GlobalUiColorManager;
/**
* UmlPackageDiagramEditPart
*
* @since 8.0
*/
public class PackageDiagramEditPart extends AbstractDiagramEditPart implements DiagramUiConstants, IDiagramTypeEditPart {
// router style
// private String sCurrentRouterStyle = DiagramRouterStyles.MANHATTAN_ROUTER;
private int routerStyle = DiagramEditorUtil.getCurrentDiagramRouterStyle();
/** Singleton instance of MarqueeDragTracker. */
static DragTracker m_dragTracker = null;
/**
* @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
**/
@Override
protected IFigure createFigure() {
Figure newFigure = getFigureFactory().createFigure(getModel(), "umlDiagramNotation"); //$NON-NLS-1$
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.CONTAINER_ROLE, new HiliteDndNodeSelectionEditPolicy());
// installEditPolicy(EditPolicy.SELECTION_FEEDBACK_ROLE, new HiliteDndNodeSelectionEditPolicy());
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 (!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()) {
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(LinkRouter.types[routerStyle]);
ncmSourceConn.layout();
}
}
if (layoutChildren) {
refreshAssociationLabels();
}
}
private boolean hasChildren() {
if (getViewer().getContents().getChildren().size() > 0) return true;
return false;
}
private void refreshAssociationLabels() {
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 AbstractDefaultEditPart) {
((AbstractDefaultEditPart)nextEditPart).refreshAllLabels();
}
}
}
@Override
public void layout() {
if (!hasChildren()) return;
// Let's check the current selection. If only one edit part is selected and it is a relationship
// then we get it's model object and pass it it.
DiagramModelNode selectedModelNode = null;
if (getViewer().getSelectedEditParts().size() == 1) {
Object selectedPart = getViewer().getSelectedEditParts().get(0);
if (selectedPart != null && selectedPart instanceof DiagramEditPart && !(selectedPart.equals(this))) {
EditPart sep = (EditPart)selectedPart;
if (sep.getParent() == this) selectedModelNode = (DiagramModelNode)((DiagramEditPart)selectedPart).getModel();
}
}
LayoutHelper layoutHelper = new LayoutHelper((DiagramModelNode)getModel(), selectedModelNode);
layoutHelper.layoutAll();
// layout(false);
createOrUpdateAnchorsLocations(true);
refreshAllLabels();
refreshVisuals();
}
/* (non-JavaDoc)
* @see java.beans.PropertyChangeListener#propertyChange(PropertyChangeEvent)
**/
@Override
public void propertyChange( PropertyChangeEvent evt ) {
String prop = evt.getPropertyName();
if (prop.equals(DiagramNodeProperties.CHILDREN)) {
refreshChildren();
// Walk each child EP and tell to layout(true);
layoutChildren();
} else if (prop.equals(DiagramNodeProperties.SIZE)) {
createOrUpdateAnchorsLocations(true);
refreshAllLabels();
refreshVisuals();
} else if (prop.equals(DiagramNodeProperties.LOCATION)) {
createOrUpdateAnchorsLocations(true);
refreshAllLabels();
refreshVisuals();
} else if (prop.equals(DiagramNodeProperties.PROPERTIES)) {
refreshVisuals();
// refreshChildren();
// layout(DiagramEditPart.LAYOUT_CHILDREN);
} else if (prop.equals(DiagramNodeProperties.NAME)) {
refreshName();
refreshAllLabels();
refreshVisuals();
} else if (prop.equals(DiagramNodeProperties.ROUTER)) {
notifyRouterChanged((String)evt.getOldValue(), (String)evt.getNewValue());
}
}
private void layoutChildren() {
Iterator iter = this.getChildren().iterator();
EditPart nextEP = null;
while (iter.hasNext()) {
nextEP = (EditPart)iter.next();
if (nextEP instanceof DiagramEditPart) {
((DiagramEditPart)nextEP).layout(true);
}
}
}
/**
* Set the anchors location based on current figure's rectangle size.
**/
@Override
public void createOrUpdateAnchorsLocations( boolean updateOtherEnds ) {
Iterator iter = this.getChildren().iterator();
EditPart nextEP = null;
while (iter.hasNext()) {
nextEP = (EditPart)iter.next();
if (nextEP instanceof DiagramEditPart && !(nextEP instanceof LabelEditPart)) {
((DiagramEditPart)nextEP).createOrUpdateAnchorsLocations(updateOtherEnds);
((AbstractDefaultEditPart)nextEP).refreshAllLabels();
}
}
}
/**
* @see org.eclipse.gef.editparts.AbstractEditPart#refreshVisuals()
**/
@Override
protected void refreshVisuals() {
ConnectionLayer cLayer = (ConnectionLayer)getLayer(LayerConstants.CONNECTION_LAYER);
switch (routerStyle) {
case LinkRouter.ORTHOGONAL: {
cLayer.setConnectionRouter(new BlockConnectionRouter(30));
}
break;
case LinkRouter.MANUAL: {
// These lines will enable the Bendpoint routing -------------------
AutomaticRouter router = new FanRouter();
router.setNextRouter(new BendpointConnectionRouter());
cLayer.setConnectionRouter(router);
}
break;
case LinkRouter.DIRECT:
default: {
cLayer.setConnectionRouter(new FanRouter());
}
break;
}
}
/**
* 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);
}
}
if (hasConnections()) refreshAssociationLabels();
}
}
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;
}
@Override
public void updateForPreferences() {
RGB currentBkgdColor = PreferenceConverter.getColor(DiagramUiPlugin.getDefault().getPreferenceStore(),
PluginConstants.Prefs.Appearance.PACKAGE_BKGD_COLOR);
this.getFigure().setBackgroundColor(GlobalUiColorManager.getColor(currentBkgdColor));
((PackageDiagramNode)getModel()).refreshAssociationLabels();
refreshFont(true);
// Let's check the router style
// int newRouterStyle = DiagramUiUtilities.getCurrentRouterStyle();
// if( newRouterStyle != routerStyle) {
// routerStyle = newRouterStyle;
// refreshVisuals();
// // now update all connections
// notifyRouterChanged();
// }
}
private void notifyRouterChanged( String oldValue,
String newValue ) {
int newType = DiagramLinkType.ORTHOGONAL;
if (newValue != null) {
newType = DiagramLinkType.get(newValue).getValue();
}
// int newRouterStyle = ((Diagram)((DiagramModelNode)getModel()).getModelObject()).getLinkType().getValue();
// if( newRouterStyle != routerStyle) {
routerStyle = newType;
refreshVisuals();
// }
List allSourceConnections = DiagramUiUtilities.getAllSourceConnections((DiagramModelNode)getModel());
if (allSourceConnections != null && !allSourceConnections.isEmpty()) {
Iterator iter = allSourceConnections.iterator();
Object nextObj = null;
String routerType = LinkRouter.types[routerStyle];
while (iter.hasNext()) {
nextObj = iter.next();
if (nextObj instanceof NodeConnectionModel) {
((NodeConnectionModel)nextObj).setRouterStyle(routerType);
((NodeConnectionModel)nextObj).firePropertyChange(DiagramNodeProperties.ROUTER, oldValue, newValue);
}
}
}
}
}