/******************************************************************************
* Copyright (c) 2011-2013, Linagora
*
* 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:
* Linagora - initial API and implementation
*******************************************************************************/
package com.ebmwebsourcing.petals.services.eip.designer.actions;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.gef.GraphicalViewer;
import org.eclipse.gef.commands.CompoundCommand;
import org.eclipse.jface.action.Action;
import com.ebmwebsourcing.petals.services.eip.designer.EipChainDiagramEditor;
import com.ebmwebsourcing.petals.services.eip.designer.edit.commands.NodeChangeLayoutCommand;
import com.ebmwebsourcing.petals.services.eip.designer.edit.parts.AbstractNodeEditPart;
import com.ebmwebsourcing.petals.services.eip.designer.helpers.SubGraphStatistics;
import com.ebmwebsourcing.petals.services.eip.designer.model.AbstractNode;
import com.ebmwebsourcing.petals.services.eip.designer.model.EipNode;
import com.ebmwebsourcing.petals.services.eip.designer.model.Endpoint;
/**
* @author Vincent Zurczak - EBM WebSourcing
*/
public class ArrangeAllAction extends Action {
private final EipChainDiagramEditor editor;
/**
* Constructor.
* @param editor
*/
public ArrangeAllAction( EipChainDiagramEditor editor ) {
this.editor = editor;
setId( "com.ebmwebsourcing.petals.services.eip.contextmenu.arrangeall" );
setText( "Arrange All" );
setToolTipText( "Arrange the diagram layout" );
setDescription( "Move all the nodes at their best position." );
}
/*
* (non-Jsdoc)
* @see org.eclipse.jface.action.Action
* #run()
*/
@Override
public void run() {
// Build the map that associates nodes and figures
Map<AbstractNode,IFigure> nodeToFigure = new HashMap<AbstractNode,IFigure> ();
Map<?,?> map = ((GraphicalViewer) this.editor.getAdapter( GraphicalViewer.class )).getEditPartRegistry();
for( Map.Entry<?,?> entry : map.entrySet()) {
if( entry.getKey() instanceof AbstractNode
&& entry.getValue() instanceof AbstractNodeEditPart ) {
IFigure fig = ((AbstractNodeEditPart) entry.getValue()).getFigure();
nodeToFigure.put((AbstractNode) entry.getKey(), fig );
}
}
// Compute node preferred positions
// First, we need to build sub-graphs
List<AbstractNode> subGraphRoots = new ArrayList<AbstractNode> ();
for( EipNode eip : this.editor.getEipChain().getEipNodes()) {
if( eip.getIncomingConnection() == null )
subGraphRoots.add( eip );
}
for( Endpoint edpt : this.editor.getEipChain().getEndpoints()) {
if( edpt.getIncomingConnection() == null )
subGraphRoots.add( edpt );
}
// Then, process each sub-graph
List<SubGraphStatistics> stats = new ArrayList<SubGraphStatistics> ();
for( AbstractNode rootNode : subGraphRoots )
stats.add( new SubGraphStatistics( rootNode, nodeToFigure ));
// Create a compound command to execute in a single transaction all the
// location change commands
CompoundCommand cmd = new CompoundCommand();
// Create a move command for every node
int xOffset = 0, yOffset = 100;
for( SubGraphStatistics stat : stats ) {
// Move the nodes of this sub-graph
int maxY = 0;
for( Map.Entry<AbstractNode,Point> entry : stat.getNodeToRelativeLocation().entrySet()) {
// Keep it for debug
// System.out.print( entry.getKey() instanceof Endpoint ? "Endpoint : " : "EIP : " );
// System.out.println( entry.getKey().getInterfaceName());
// System.out.println( "( " + entry.getValue().x + ", " + entry.getValue().y + " )\n" );
Point newLoc = new Point(
entry.getValue().x + xOffset,
entry.getValue().y + yOffset );
if( entry.getValue().y > maxY )
maxY = entry.getValue().y;
NodeChangeLayoutCommand clm = new NodeChangeLayoutCommand();
clm.setNode( entry.getKey());
clm.setLocation( newLoc );
cmd.add( clm );
}
// Put each sub-graph under another one
yOffset += maxY + 70; // 70 = padding-Y between each sub-graph
}
// Execute it
this.editor.getEditingDomain().getCommandStack().execute( cmd );
}
}