/*****************************************************************************
* Copyright (c) 2010 Atos Origin.
*
*
* 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:
* Atos Origin - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.uml.diagram.activity.draw2d;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.StackLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.papyrus.uml.diagram.common.draw2d.CenterLayout;
/**
* This implementation is based on {@link CenterLayout}, except it avoids
* superposing figures. Elements are centered and placed in a row. Available
* extra place is dispatched between figures with fill constraint.
*
* @see CenteredColumnConstraint
*/
public class CenteredColumnLayout extends StackLayout {
private static final Rectangle RECTANGLE = new Rectangle();
/** Extra margin (for avoiding cut) */
private static final int MARGIN = 5;
private Map<IFigure, CenteredColumnConstraint> constraints = new HashMap<IFigure, CenteredColumnConstraint>();
@Override
public void layout(IFigure figure) {
Rectangle rect = figure.getClientArea();
final int centerX = rect.x + rect.width / 2;
int yAxe = rect.y;
int availableExtraHeight = rect.height;
int numberOfFillChildren = 0;
List<IFigure> orderedFigures = new LinkedList<IFigure>();
List<?> children = figure.getChildren();
IFigure child;
for(int i = 0; i < children.size(); i++) {
child = (IFigure)children.get(i);
Dimension prefSize = child.getPreferredSize(-1, -1);
availableExtraHeight -= prefSize.height + MARGIN;
if(constraints.get(child) != null && constraints.get(child).isAvailableSpaceFilled()) {
numberOfFillChildren++;
}
if(!constraints.containsKey(child)) {
constraints.put(child, null);
}
orderedFigures.add(i, child);
}
int fillExtraHeight = 0;
if(numberOfFillChildren > 0) {
fillExtraHeight = availableExtraHeight / numberOfFillChildren;
}
for(IFigure childF : orderedFigures) {
boolean fill = constraints.get(childF).isAvailableSpaceFilled();
Dimension prefSize = childF.getPreferredSize(-1, -1);
RECTANGLE.x = centerX - prefSize.width / 2;
RECTANGLE.y = yAxe;
RECTANGLE.width = prefSize.width;
if(!fill) {
RECTANGLE.height = prefSize.height + MARGIN;
} else {
RECTANGLE.height = prefSize.height + MARGIN + fillExtraHeight;
}
// Workaround for 209648
childF.setBounds(RECTANGLE);
yAxe += RECTANGLE.height;
}
}
@Override
public void setConstraint(IFigure child, Object constraint) {
if(constraint instanceof CenteredColumnConstraint) {
constraints.put(child, (CenteredColumnConstraint)constraint);
}
super.setConstraint(child, constraint);
}
@Override
public Object getConstraint(IFigure child) {
return constraints.get(child);
}
@Override
protected Dimension calculateMinimumSize(IFigure figure, int wHint, int hHint) {
if(wHint > -1)
wHint = Math.max(0, wHint - figure.getInsets().getWidth());
if(hHint > -1)
hHint = Math.max(0, hHint - figure.getInsets().getHeight());
Dimension d = new Dimension();
List children = figure.getChildren();
IFigure child;
for(int i = 0; i < children.size(); i++) {
child = (IFigure)children.get(i);
if(!isObservingVisibility() || child.isVisible()) {
Dimension childSize = child.getMinimumSize(wHint, hHint);
d.height += childSize.height;
d.width = Math.max(d.width, childSize.width);
}
}
d.expand(figure.getInsets().getWidth(), figure.getInsets().getHeight());
d.union(getBorderPreferredSize(figure));
return d;
}
}