package org.xmind.cathy.internal.renderer; import java.util.ArrayList; import java.util.List; import org.eclipse.e4.ui.model.application.ui.MGenericTile; import org.eclipse.e4.ui.model.application.ui.MUIElement; import org.eclipse.swt.graphics.Point; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Layout; import org.eclipse.swt.widgets.Shell; public class XSashLayout extends Layout { int suggestedSizeForViewStack = 310; int suggestedDownDistanceForViewStack = 22; int marginLeft = 0; int marginRight = 0; int marginTop = 0; int marginBottom = 0; int sashWidth = 0; MUIElement root; class SashRect { Rectangle rect; MGenericTile<?> container; MUIElement left; MUIElement right; public SashRect(Rectangle rect, MGenericTile<?> container, MUIElement left, MUIElement right) { this.container = container; this.rect = rect; this.left = left; this.right = right; } } public XSashLayout(MUIElement root) { this.root = root; } @Override protected void layout(Composite composite, boolean flushCache) { if (root == null) return; Rectangle bounds = composite.getBounds(); if (composite instanceof Shell) bounds = ((Shell) composite).getClientArea(); else { bounds.x = 0; bounds.y = 0; } bounds.width -= (marginLeft + marginRight); bounds.height -= (marginTop + marginBottom); bounds.x += marginLeft; bounds.y += marginTop; tileSubNodes(bounds, root); } @Override protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) { return new Point(600, 400); } private int totalScalableSectionWeight(MGenericTile<?> node) { int total = 0; for (MUIElement subNode : node.getChildren()) { if (subNode.isToBeRendered() && subNode.isVisible()) { Object renderer = subNode.getRenderer(); if (renderer != null && renderer.getClass() != XRightStackRenderer.class) { total += getWeight(subNode); } } } return total; } private void tileSubNodes(Rectangle bounds, MUIElement node) { if (node != root) setRectangle(node, bounds); if (!(node instanceof MGenericTile<?>)) return; MGenericTile<?> sashContainer = (MGenericTile<?>) node; List<MUIElement> visibleChildren = getVisibleChildren(sashContainer); int childCount = visibleChildren.size(); // How many pixels do we have? int availableWidth = sashContainer.isHorizontal() ? bounds.width : bounds.height; // Subtract off the room for the sashes availableWidth -= ((childCount - 1) * sashWidth); int availableScalableSectionWidth = availableWidth; // Get the total of the weights double totalScalableSectionWeight = totalScalableSectionWeight( sashContainer); for (MUIElement subNode : visibleChildren) { Object renderer = subNode.getRenderer(); if (renderer != null && renderer.getClass() == XRightStackRenderer.class) { availableScalableSectionWidth -= suggestedSizeForViewStack; } } int tilePos = sashContainer.isHorizontal() ? bounds.x : bounds.y; MUIElement prev = null; for (MUIElement subNode : visibleChildren) { // Add a 'sash' between this node and the 'prev' if (prev != null) { tilePos += sashWidth; } // Calc the new size as a %'age of the total int weight = getWeight(subNode); double ratio = weight / totalScalableSectionWeight; int newSize = (int) ((availableScalableSectionWidth * ratio) + 0.5); Object renderer = subNode.getRenderer(); int y = bounds.y; int height = bounds.height; if (renderer != null && renderer.getClass() == XRightStackRenderer.class) { newSize = suggestedSizeForViewStack; y = y + suggestedDownDistanceForViewStack; height = height - suggestedDownDistanceForViewStack - 1; } Rectangle subBounds = sashContainer.isHorizontal() ? new Rectangle(tilePos, y, newSize, height) : new Rectangle(bounds.x, tilePos, bounds.width, newSize); tilePos += newSize; tileSubNodes(subBounds, subNode); prev = subNode; } } /** * @param node * @param bounds */ private void setRectangle(MUIElement node, Rectangle bounds) { if (node.getWidget() instanceof Control) { Control ctrl = (Control) node.getWidget(); ctrl.setBounds(bounds); } else if (node.getWidget() instanceof Rectangle) { Rectangle theRect = (Rectangle) node.getWidget(); theRect.x = bounds.x; theRect.y = bounds.y; theRect.width = bounds.width; theRect.height = bounds.height; } } private List<MUIElement> getVisibleChildren(MGenericTile<?> sashContainer) { List<MUIElement> visKids = new ArrayList<MUIElement>(); for (MUIElement child : sashContainer.getChildren()) { if (child.isToBeRendered() && child.isVisible()) visKids.add(child); } return visKids; } private static int getWeight(MUIElement element) { String info = element.getContainerData(); if (info == null || info.length() == 0) { return 0; } try { int value = Integer.parseInt(info); return value; } catch (NumberFormatException e) { return 0; } } }