/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.gef.draw2d;
import java.util.List;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Rectangle;
public class AdvancedToolbarLayout extends org.eclipse.draw2d.ToolbarLayout {
private int majorAlignment = ALIGN_CENTER;
private boolean stretchMajorAxis = false;
private int innerMinorAlignment = ALIGN_CENTER;
/**
*
*/
public AdvancedToolbarLayout() {
this(false);
}
/**
* @param isHorizontal
*/
public AdvancedToolbarLayout(boolean isHorizontal) {
super(isHorizontal);
setMinorAlignment(ALIGN_CENTER);
}
/**
* @param majorAlignment
* the majorAlignment to set
*/
public void setMajorAlignment(int majorAlignment) {
this.majorAlignment = majorAlignment;
}
/**
* @return the majorAlignment
*/
public int getMajorAlignment() {
return majorAlignment;
}
/**
* @return the stretchMajorAxis
*/
public boolean isStretchMajorAxis() {
return stretchMajorAxis;
}
/**
* @param stretchMajorAxis
* the stretchMajorAxis to set
*/
public void setStretchMajorAxis(boolean stretchMajorAxis) {
this.stretchMajorAxis = stretchMajorAxis;
}
public int getInnerMinorAlignment() {
return innerMinorAlignment;
}
public void setInnerMinorAlignment(int innerMinorAlignment) {
this.innerMinorAlignment = innerMinorAlignment;
}
/**
* @see org.eclipse.draw2d.ToolbarLayout#layout(org.eclipse.draw2d.IFigure)
*/
@Override
public void layout(IFigure parent) {
List children = parent.getChildren();
int numChildren = children.size();
Rectangle clientArea = transposer.t(parent.getClientArea());
int x = clientArea.x;
int y = clientArea.y;
int prefSpacing;
// int availableHeight = clientArea.height;
Dimension prefSizes[] = new Dimension[numChildren];
Dimension minSizes[] = new Dimension[numChildren];
// Calculate the width and height hints. If it's a vertical ToolBarLayout,
// then ignore the height hint (set it to -1); otherwise, ignore the
// width hint. These hints will be passed to the children of the parent
// figure when getting their preferred size.
int wHint = -1;
int hHint = -1;
if (isHorizontal()) {
hHint = parent.getClientArea(Rectangle.SINGLETON).height;
} else {
wHint = parent.getClientArea(Rectangle.SINGLETON).width;
}
/*
* Calculate sum of preferred heights of all children(totalHeight).
* Calculate sum of minimum heights of all children(minHeight). Cache
* Preferred Sizes and Minimum Sizes of all children.
*
* totalHeight is the sum of the preferred heights of all children
* totalMinHeight is the sum of the minimum heights of all children
* prefMinSumHeight is the sum of the difference between all children's
* preferred heights and minimum heights. (This is used as a ratio to
* calculate how much each child will shrink).
*/
IFigure child;
int totalHeight = 0;
int totalWidth = 0;
// int totalMinHeight = 0;
// int prefMinSumHeight = 0;
for (int i = 0; i < numChildren; i++) {
child = (IFigure) children.get(i);
prefSizes[i] = transposer.t(child.getPreferredSize(wHint, hHint));
minSizes[i] = transposer.t(child.getMinimumSize(wHint, hHint));
totalHeight += prefSizes[i].height;
totalWidth = Math.max(totalWidth, prefSizes[i].width);
// totalMinHeight += minSizes[i].height;
}
if (stretchMajorAxis && numChildren > 1) {
prefSpacing = (clientArea.height - totalHeight) / (numChildren - 1);
totalHeight = clientArea.height;
} else {
prefSpacing = getSpacing();
totalHeight += (numChildren - 1) * getSpacing();
}
// totalMinHeight += (numChildren - 1) * spacing;
// prefMinSumHeight = totalHeight - totalMinHeight;
/*
* The total amount that the children must be shrunk is the sum of the
* preferred Heights of the children minus Max(the available area and
* the sum of the minimum heights of the children).
*
* amntShrinkHeight is the combined amount that the children must shrink
* amntShrinkCurrentHeight is the amount each child will shrink
* respectively
*/
// int amntShrinkHeight = totalHeight - Math.max(availableHeight, totalMinHeight);
//
// if (amntShrinkHeight < 0) {
// amntShrinkHeight = 0;
// }
if (majorAlignment == ALIGN_CENTER) {
y += (clientArea.height - totalHeight) / 2;
} else if (majorAlignment == ALIGN_BOTTOMRIGHT) {
y += clientArea.height - totalHeight;
}
if (isStretchMinorAxis())
totalWidth = Integer.MAX_VALUE;
totalWidth = Math.max(0, Math.min(clientArea.width, totalWidth));
int adjust = clientArea.width - totalWidth;
switch (getMinorAlignment()) {
case ALIGN_TOPLEFT:
adjust = 0;
break;
case ALIGN_CENTER:
adjust /= 2;
break;
case ALIGN_BOTTOMRIGHT:
break;
}
for (int i = 0; i < numChildren; i++) {
// int amntShrinkCurrentHeight = 0;
int prefHeight = prefSizes[i].height;
// int minHeight = minSizes[i].height;
int prefWidth = prefSizes[i].width;
int minWidth = minSizes[i].width;
Rectangle newBounds = new Rectangle(x, y, prefWidth, prefHeight);
child = (IFigure) children.get(i);
// if (prefMinSumHeight != 0)
// amntShrinkCurrentHeight =
// (prefHeight - minHeight) * amntShrinkHeight / (prefMinSumHeight);
int width = Math.min(prefWidth, //totalWidth);
transposer.t(child.getMaximumSize()).width);
if (isStretchMinorAxis())
width = transposer.t(child.getMaximumSize()).width;
width = Math.max(minWidth, Math.min(clientArea.width, width));
newBounds.width = width;
int adjust2 = totalWidth - width;
switch (innerMinorAlignment) {
case ALIGN_BOTTOMRIGHT:
adjust2 = 0;
break;
case ALIGN_CENTER:
adjust2 /= 2;
break;
case ALIGN_TOPLEFT:
break;
}
newBounds.x += adjust + adjust2;
// newBounds.height -= amntShrinkCurrentHeight;
child.setBounds(transposer.t(newBounds));
// amntShrinkHeight -= amntShrinkCurrentHeight;
// prefMinSumHeight -= (prefHeight - minHeight);
y += newBounds.height + prefSpacing;
}
}
}