package info.limpet.stackedcharts.ui.editor.figures; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import org.eclipse.draw2d.FlowLayout; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.draw2d.geometry.Rectangle; /** * An extension of the standard {@link FlowLayout}. The only difference is that when the layout is * vertical, children need to be arranged bottom-to-top, instead of top-to-bottom. This is achieved * by iterating the children collection in reverse order in the {@link #layout(IFigure)} * method.</br> * Arranging bottom-to-top is desired in order to achieve reading consistency with the Left-To-Right * directional language preference. */ public class DirectionFlowLayout extends FlowLayout { /** * Need to subclass the protected inner class WorkingData, otherwise won't be able to access it. * Reference: http://stackoverflow.com/a/17610709/1649388 */ protected class DirectionalWorkingData extends WorkingData { } /** * Most of the code is copied from the superclass, the only change is iterating the children in * reverse order when layout is vertical. * * @see org.eclipse.draw2d.LayoutManager#layout(IFigure) */ public void layout(IFigure parent) { data = new DirectionalWorkingData(); Rectangle relativeArea = parent.getClientArea(); data.area = transposer.t(relativeArea); // iterate the children in reverse order in case of vertical layout @SuppressWarnings({"unchecked", "rawtypes"}) List<?> childrenCopy = new ArrayList(parent.getChildren()); if (!isHorizontal()) { Collections.reverse(childrenCopy); } Iterator<?> iterator = childrenCopy.iterator(); int dx; // Calculate the hints to be passed to children int wHint = -1; int hHint = -1; if (isHorizontal()) wHint = parent.getClientArea().width; else hHint = parent.getClientArea().height; initVariables(parent); initRow(); while (iterator.hasNext()) { IFigure f = (IFigure) iterator.next(); Dimension pref = transposer.t(getChildSize(f, wHint, hHint)); Rectangle r = new Rectangle(0, 0, pref.width, pref.height); if (data.rowCount > 0) { if (data.rowWidth + pref.width > data.maxWidth) layoutRow(parent); } r.x = data.rowX; r.y = data.rowY; dx = r.width + getMinorSpacing(); data.rowX += dx; data.rowWidth += dx; data.rowHeight = Math.max(data.rowHeight, r.height); data.row[data.rowCount] = f; data.bounds[data.rowCount] = r; data.rowCount++; } if (data.rowCount != 0) layoutRow(parent); data = null; } }