X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.g2d%2Fsrc%2Forg%2Fsimantics%2Fg2d%2Fdiagram%2Fhandler%2Flayout%2FFlowLayout.java;h=4753e080d929d4dbfde55bcd6192d46aefbb113b;hb=b4f82d1df29a6f3322fcc7940ec30050eef8fbf3;hp=8d84864ccf0e7f0857143ea5bdc372882b905525;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/handler/layout/FlowLayout.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/handler/layout/FlowLayout.java index 8d84864cc..4753e080d 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/handler/layout/FlowLayout.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/handler/layout/FlowLayout.java @@ -1,171 +1,171 @@ -/******************************************************************************* - * Copyright (c) 2007, 2010 Association for Decentralized Information Management - * in Industry THTH ry. - * 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: - * VTT Technical Research Centre of Finland - initial API and implementation - *******************************************************************************/ -package org.simantics.g2d.diagram.handler.layout; - -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; - -import org.simantics.g2d.diagram.IDiagram; -import org.simantics.g2d.diagram.handler.LayoutManager; -import org.simantics.g2d.element.ElementUtils; -import org.simantics.g2d.element.IElement; -import org.simantics.utils.datastructures.hints.IHintContext.Key; -import org.simantics.utils.datastructures.hints.IHintContext.KeyOf; - -public class FlowLayout implements LayoutManager { - - /** Diagram hint, Row justification */ - public static enum Align {Left, Center, Right, Fill} - - /** - * The align specifies the alignment of elements - * in a row. - */ - public static final Key ALIGN = new KeyOf(Align.class, "FlowLayout.ALIGN"); - - /** - * The horizontal gap specifies the space between - * elements and between an element and borders. - */ - public static final Key HGAP = new KeyOf(Double.class, "FlowLayout.HGAP"); - - /** - * The vertical gap specifies the space between - * elements and between an element and borders. - */ - public static final Key VGAP = new KeyOf(Double.class, "FlowLayout.VGAP"); - - @Override - public void layout(IDiagram diagram, Rectangle2D bounds) { - Align align = diagram.getHint(ALIGN); - Double hgap = diagram.getHint(HGAP); - Double vgap = diagram.getHint(VGAP); - if (align==null) align = Align.Left; - if (hgap==null) hgap = 0.; - if (vgap==null) vgap = 0.; - - Map pos = computePositions(diagram, bounds, align, hgap, vgap); - for (Entry e : pos.entrySet()) { - ElementUtils.setPos(e.getKey(), e.getValue().getMinX(), e.getValue().getMinY()); - } - } - - @Override - public Rectangle2D computeSize(IDiagram diagram, Double wHint, Double hHint) - { - Rectangle2D bounds = new Rectangle2D.Double(); - Align align = diagram.getHint(ALIGN); - Double hgap = diagram.getHint(HGAP); - Double vgap = diagram.getHint(VGAP); - if (align==null) align = Align.Left; - if (hgap==null) hgap = 0.; - if (vgap==null) vgap = 0.; - - if (wHint==null) wHint = Double.MAX_VALUE; - if (hHint==null) hHint = Double.MAX_VALUE; - - bounds.setFrame(0, 0, wHint, hHint); - - Map pos = computePositions(diagram, bounds, align, hgap, vgap); - double minX = Double.MAX_VALUE, minY = Double.MAX_VALUE, maxX = -Double.MAX_VALUE, maxY = -Double.MAX_VALUE; - for (IElement e : pos.keySet()) { - Rectangle2D b = pos.get(e); - if (b.getMinX() < minX) minX = b.getMinX(); - if (b.getMinY() < minY) minY = b.getMinY(); - if (b.getMaxX() > maxX) maxX = b.getMaxX(); - if (b.getMaxY() > maxY) maxY = b.getMaxY(); - } - - return new Rectangle2D.Double(minX, minY, maxX-minX, maxY-minY); - } - - private Map computePositions(IDiagram diagram, Rectangle2D bounds, Align align, double hgap, double vgap) - { - double width = bounds.getWidth(); - - // Must use diagram.getSnapshot since we are not guaranteed to be in the - // diagram's canvas context thread. - Collection elements = diagram.getSnapshot(); - Map rects = ElementUtils.getElementBoundsOnDiagram(elements, null); - - // Rows - List> rows = new ArrayList>(); - - // Divide elements to rows - List row = new ArrayList(); - rows.add(row); - double rowWidth = 0.0; - for (IElement e : elements) - { - Rectangle2D elementBounds = rects.get(e); - - if (row.isEmpty()) { - row.add(e); - rowWidth += elementBounds.getWidth(); - continue; - } - - // Add element if it fits to the row - if (rowWidth + elementBounds.getWidth() + hgap*(row.size()) < width) - { - rowWidth += elementBounds.getWidth(); - row.add(e); - continue; - } - - // Create a new row - rows.add( row = new ArrayList() ); - row.add(e); - rowWidth = elementBounds.getWidth(); - } - - // Flush rows - double y = bounds.getMinY(); - double hmargin = hgap; - for (List row_ : rows) { - double rowHeight = 0; - - // Calc row width - double rowContentWidth = (row.size()-1) * hgap; - for (IElement e : row) - rowContentWidth += rects.get(e).getWidth(); - - double x = hgap + bounds.getMinX(); - double _hgap = hgap; - if (align == Align.Center) x = (width - hmargin - hmargin - rowContentWidth) / 2; - if (align == Align.Left) x = hmargin; - if (align == Align.Right) x = width-rowContentWidth-hmargin; - if (align == Align.Fill) { - x = hmargin; - _hgap = (width - hmargin - hmargin - rowContentWidth) / (row.size()+1); - //_hgap = 2; - } - for (IElement e : row_) { - Rectangle2D rect = rects.get(e); - rect.setFrame(x, y, rect.getWidth(), rect.getHeight()); - x += rect.getWidth() + _hgap; - rowHeight = Math.max(rowHeight, rect.getHeight()); - } - - x = bounds.getMinX(); - y += rowHeight + vgap; - } - - return rects; - } - - -} +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * 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: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.g2d.diagram.handler.layout; + +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.diagram.handler.LayoutManager; +import org.simantics.g2d.element.ElementUtils; +import org.simantics.g2d.element.IElement; +import org.simantics.utils.datastructures.hints.IHintContext.Key; +import org.simantics.utils.datastructures.hints.IHintContext.KeyOf; + +public class FlowLayout implements LayoutManager { + + /** Diagram hint, Row justification */ + public static enum Align {Left, Center, Right, Fill} + + /** + * The align specifies the alignment of elements + * in a row. + */ + public static final Key ALIGN = new KeyOf(Align.class, "FlowLayout.ALIGN"); + + /** + * The horizontal gap specifies the space between + * elements and between an element and borders. + */ + public static final Key HGAP = new KeyOf(Double.class, "FlowLayout.HGAP"); + + /** + * The vertical gap specifies the space between + * elements and between an element and borders. + */ + public static final Key VGAP = new KeyOf(Double.class, "FlowLayout.VGAP"); + + @Override + public void layout(IDiagram diagram, Rectangle2D bounds) { + Align align = diagram.getHint(ALIGN); + Double hgap = diagram.getHint(HGAP); + Double vgap = diagram.getHint(VGAP); + if (align==null) align = Align.Left; + if (hgap==null) hgap = 0.; + if (vgap==null) vgap = 0.; + + Map pos = computePositions(diagram, bounds, align, hgap, vgap); + for (Entry e : pos.entrySet()) { + ElementUtils.setPos(e.getKey(), e.getValue().getMinX(), e.getValue().getMinY()); + } + } + + @Override + public Rectangle2D computeSize(IDiagram diagram, Double wHint, Double hHint) + { + Rectangle2D bounds = new Rectangle2D.Double(); + Align align = diagram.getHint(ALIGN); + Double hgap = diagram.getHint(HGAP); + Double vgap = diagram.getHint(VGAP); + if (align==null) align = Align.Left; + if (hgap==null) hgap = 0.; + if (vgap==null) vgap = 0.; + + if (wHint==null) wHint = Double.MAX_VALUE; + if (hHint==null) hHint = Double.MAX_VALUE; + + bounds.setFrame(0, 0, wHint, hHint); + + Map pos = computePositions(diagram, bounds, align, hgap, vgap); + double minX = Double.MAX_VALUE, minY = Double.MAX_VALUE, maxX = -Double.MAX_VALUE, maxY = -Double.MAX_VALUE; + for (IElement e : pos.keySet()) { + Rectangle2D b = pos.get(e); + if (b.getMinX() < minX) minX = b.getMinX(); + if (b.getMinY() < minY) minY = b.getMinY(); + if (b.getMaxX() > maxX) maxX = b.getMaxX(); + if (b.getMaxY() > maxY) maxY = b.getMaxY(); + } + + return new Rectangle2D.Double(minX, minY, maxX-minX, maxY-minY); + } + + private Map computePositions(IDiagram diagram, Rectangle2D bounds, Align align, double hgap, double vgap) + { + double width = bounds.getWidth(); + + // Must use diagram.getSnapshot since we are not guaranteed to be in the + // diagram's canvas context thread. + Collection elements = diagram.getSnapshot(); + Map rects = ElementUtils.getElementBoundsOnDiagram(elements, null); + + // Rows + List> rows = new ArrayList>(); + + // Divide elements to rows + List row = new ArrayList(); + rows.add(row); + double rowWidth = 0.0; + for (IElement e : elements) + { + Rectangle2D elementBounds = rects.get(e); + + if (row.isEmpty()) { + row.add(e); + rowWidth += elementBounds.getWidth(); + continue; + } + + // Add element if it fits to the row + if (rowWidth + elementBounds.getWidth() + hgap*(row.size()) < width) + { + rowWidth += elementBounds.getWidth(); + row.add(e); + continue; + } + + // Create a new row + rows.add( row = new ArrayList() ); + row.add(e); + rowWidth = elementBounds.getWidth(); + } + + // Flush rows + double y = bounds.getMinY(); + double hmargin = hgap; + for (List row_ : rows) { + double rowHeight = 0; + + // Calc row width + double rowContentWidth = (row.size()-1) * hgap; + for (IElement e : row) + rowContentWidth += rects.get(e).getWidth(); + + double x = hgap + bounds.getMinX(); + double _hgap = hgap; + if (align == Align.Center) x = (width - hmargin - hmargin - rowContentWidth) / 2; + if (align == Align.Left) x = hmargin; + if (align == Align.Right) x = width-rowContentWidth-hmargin; + if (align == Align.Fill) { + x = hmargin; + _hgap = (width - hmargin - hmargin - rowContentWidth) / (row.size()+1); + //_hgap = 2; + } + for (IElement e : row_) { + Rectangle2D rect = rects.get(e); + rect.setFrame(x, y, rect.getWidth(), rect.getHeight()); + x += rect.getWidth() + _hgap; + rowHeight = Math.max(rowHeight, rect.getHeight()); + } + + x = bounds.getMinX(); + y += rowHeight + vgap; + } + + return rects; + } + + +}