-/*******************************************************************************\r
- * Copyright (c) 2016 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * Semantum Oy - initial API and implementation, courtesy of Rob Camick\r
- * https://tips4java.wordpress.com/2008/11/06/wrap-layout/\r
- *******************************************************************************/\r
-package org.simantics.utils.ui.awt;\r
-\r
-import java.awt.Component;\r
-import java.awt.Container;\r
-import java.awt.Dimension;\r
-import java.awt.FlowLayout;\r
-import java.awt.Insets;\r
-\r
-import javax.swing.JScrollPane;\r
-import javax.swing.SwingUtilities;\r
-\r
-/**\r
- * FlowLayout subclass that fully supports wrapping of components.\r
- */\r
-public class WrapLayout extends FlowLayout\r
-{\r
- /**\r
- * \r
- */\r
- private static final long serialVersionUID = -4312800883442354753L;\r
-\r
- /**\r
- * Constructs a new <code>WrapLayout</code> with a left\r
- * alignment and a default 5-unit horizontal and vertical gap.\r
- */\r
- public WrapLayout()\r
- {\r
- super();\r
- }\r
-\r
- /**\r
- * Constructs a new <code>FlowLayout</code> with the specified\r
- * alignment and a default 5-unit horizontal and vertical gap.\r
- * The value of the alignment argument must be one of\r
- * <code>WrapLayout</code>, <code>WrapLayout</code>,\r
- * or <code>WrapLayout</code>.\r
- * @param align the alignment value\r
- */\r
- public WrapLayout(int align)\r
- {\r
- super(align);\r
- }\r
-\r
- /**\r
- * Creates a new flow layout manager with the indicated alignment\r
- * and the indicated horizontal and vertical gaps.\r
- * <p>\r
- * The value of the alignment argument must be one of\r
- * <code>WrapLayout</code>, <code>WrapLayout</code>,\r
- * or <code>WrapLayout</code>.\r
- * @param align the alignment value\r
- * @param hgap the horizontal gap between components\r
- * @param vgap the vertical gap between components\r
- */\r
- public WrapLayout(int align, int hgap, int vgap)\r
- {\r
- super(align, hgap, vgap);\r
- }\r
-\r
- /**\r
- * Returns the preferred dimensions for this layout given the\r
- * <i>visible</i> components in the specified target container.\r
- * @param target the component which needs to be laid out\r
- * @return the preferred dimensions to lay out the\r
- * subcomponents of the specified container\r
- */\r
- @Override\r
- public Dimension preferredLayoutSize(Container target)\r
- {\r
- return layoutSize(target, true);\r
- }\r
-\r
- /**\r
- * Returns the minimum dimensions needed to layout the <i>visible</i>\r
- * components contained in the specified target container.\r
- * @param target the component which needs to be laid out\r
- * @return the minimum dimensions to lay out the\r
- * subcomponents of the specified container\r
- */\r
- @Override\r
- public Dimension minimumLayoutSize(Container target)\r
- {\r
- Dimension minimum = layoutSize(target, false);\r
- minimum.width -= (getHgap() + 1);\r
- return minimum;\r
- }\r
-\r
- /**\r
- * Returns the minimum or preferred dimension needed to layout the target\r
- * container.\r
- *\r
- * @param target target to get layout size for\r
- * @param preferred should preferred size be calculated\r
- * @return the dimension to layout the target container\r
- */\r
- private Dimension layoutSize(Container target, boolean preferred)\r
- {\r
- synchronized (target.getTreeLock())\r
- {\r
- // Each row must fit with the width allocated to the containter.\r
- // When the container width = 0, the preferred width of the container\r
- // has not yet been calculated so lets ask for the maximum.\r
-\r
- int targetWidth = target.getSize().width;\r
- Container container = target;\r
-\r
- while (container.getSize().width == 0 && container.getParent() != null)\r
- {\r
- container = container.getParent();\r
- }\r
-\r
- targetWidth = container.getSize().width;\r
-\r
- if (targetWidth == 0)\r
- targetWidth = Integer.MAX_VALUE;\r
-\r
- int hgap = getHgap();\r
- int vgap = getVgap();\r
- Insets insets = target.getInsets();\r
- int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2);\r
- int maxWidth = targetWidth - horizontalInsetsAndGap;\r
-\r
- // Fit components into the allowed width\r
-\r
- Dimension dim = new Dimension(0, 0);\r
- int rowWidth = 0;\r
- int rowHeight = 0;\r
-\r
- int nmembers = target.getComponentCount();\r
-\r
- for (int i = 0; i < nmembers; i++)\r
- {\r
- Component m = target.getComponent(i);\r
-\r
- if (m.isVisible())\r
- {\r
- Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize();\r
-\r
- // Can't add the component to current row. Start a new row.\r
-\r
- if (rowWidth + d.width > maxWidth)\r
- {\r
- addRow(dim, rowWidth, rowHeight);\r
- rowWidth = 0;\r
- rowHeight = 0;\r
- }\r
-\r
- // Add a horizontal gap for all components after the first\r
-\r
- if (rowWidth != 0)\r
- {\r
- rowWidth += hgap;\r
- }\r
-\r
- rowWidth += d.width;\r
- rowHeight = Math.max(rowHeight, d.height);\r
- }\r
- }\r
-\r
- addRow(dim, rowWidth, rowHeight);\r
-\r
- dim.width += horizontalInsetsAndGap;\r
- dim.height += insets.top + insets.bottom + vgap * 2;\r
-\r
- // When using a scroll pane or the DecoratedLookAndFeel we need to\r
- // make sure the preferred size is less than the size of the\r
- // target containter so shrinking the container size works\r
- // correctly. Removing the horizontal gap is an easy way to do this.\r
-\r
- Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target);\r
-\r
- if (scrollPane != null && target.isValid())\r
- {\r
- dim.width -= (hgap + 1);\r
- }\r
-\r
- return dim;\r
- }\r
- }\r
-\r
- /*\r
- * A new row has been completed. Use the dimensions of this row\r
- * to update the preferred size for the container.\r
- *\r
- * @param dim update the width and height when appropriate\r
- * @param rowWidth the width of the row to add\r
- * @param rowHeight the height of the row to add\r
- */\r
- private void addRow(Dimension dim, int rowWidth, int rowHeight)\r
- {\r
- dim.width = Math.max(dim.width, rowWidth);\r
-\r
- if (dim.height > 0)\r
- {\r
- dim.height += getVgap();\r
- }\r
-\r
- dim.height += rowHeight;\r
- }\r
+/*******************************************************************************
+ * Copyright (c) 2016 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:
+ * Semantum Oy - initial API and implementation, courtesy of Rob Camick
+ * https://tips4java.wordpress.com/2008/11/06/wrap-layout/
+ *******************************************************************************/
+package org.simantics.utils.ui.awt;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Insets;
+
+import javax.swing.JScrollPane;
+import javax.swing.SwingUtilities;
+
+/**
+ * FlowLayout subclass that fully supports wrapping of components.
+ */
+public class WrapLayout extends FlowLayout
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = -4312800883442354753L;
+
+ /**
+ * Constructs a new <code>WrapLayout</code> with a left
+ * alignment and a default 5-unit horizontal and vertical gap.
+ */
+ public WrapLayout()
+ {
+ super();
+ }
+
+ /**
+ * Constructs a new <code>FlowLayout</code> with the specified
+ * alignment and a default 5-unit horizontal and vertical gap.
+ * The value of the alignment argument must be one of
+ * <code>WrapLayout</code>, <code>WrapLayout</code>,
+ * or <code>WrapLayout</code>.
+ * @param align the alignment value
+ */
+ public WrapLayout(int align)
+ {
+ super(align);
+ }
+
+ /**
+ * Creates a new flow layout manager with the indicated alignment
+ * and the indicated horizontal and vertical gaps.
+ * <p>
+ * The value of the alignment argument must be one of
+ * <code>WrapLayout</code>, <code>WrapLayout</code>,
+ * or <code>WrapLayout</code>.
+ * @param align the alignment value
+ * @param hgap the horizontal gap between components
+ * @param vgap the vertical gap between components
+ */
+ public WrapLayout(int align, int hgap, int vgap)
+ {
+ super(align, hgap, vgap);
+ }
+
+ /**
+ * Returns the preferred dimensions for this layout given the
+ * <i>visible</i> components in the specified target container.
+ * @param target the component which needs to be laid out
+ * @return the preferred dimensions to lay out the
+ * subcomponents of the specified container
+ */
+ @Override
+ public Dimension preferredLayoutSize(Container target)
+ {
+ return layoutSize(target, true);
+ }
+
+ /**
+ * Returns the minimum dimensions needed to layout the <i>visible</i>
+ * components contained in the specified target container.
+ * @param target the component which needs to be laid out
+ * @return the minimum dimensions to lay out the
+ * subcomponents of the specified container
+ */
+ @Override
+ public Dimension minimumLayoutSize(Container target)
+ {
+ Dimension minimum = layoutSize(target, false);
+ minimum.width -= (getHgap() + 1);
+ return minimum;
+ }
+
+ /**
+ * Returns the minimum or preferred dimension needed to layout the target
+ * container.
+ *
+ * @param target target to get layout size for
+ * @param preferred should preferred size be calculated
+ * @return the dimension to layout the target container
+ */
+ private Dimension layoutSize(Container target, boolean preferred)
+ {
+ synchronized (target.getTreeLock())
+ {
+ // Each row must fit with the width allocated to the containter.
+ // When the container width = 0, the preferred width of the container
+ // has not yet been calculated so lets ask for the maximum.
+
+ int targetWidth = target.getSize().width;
+ Container container = target;
+
+ while (container.getSize().width == 0 && container.getParent() != null)
+ {
+ container = container.getParent();
+ }
+
+ targetWidth = container.getSize().width;
+
+ if (targetWidth == 0)
+ targetWidth = Integer.MAX_VALUE;
+
+ int hgap = getHgap();
+ int vgap = getVgap();
+ Insets insets = target.getInsets();
+ int horizontalInsetsAndGap = insets.left + insets.right + (hgap * 2);
+ int maxWidth = targetWidth - horizontalInsetsAndGap;
+
+ // Fit components into the allowed width
+
+ Dimension dim = new Dimension(0, 0);
+ int rowWidth = 0;
+ int rowHeight = 0;
+
+ int nmembers = target.getComponentCount();
+
+ for (int i = 0; i < nmembers; i++)
+ {
+ Component m = target.getComponent(i);
+
+ if (m.isVisible())
+ {
+ Dimension d = preferred ? m.getPreferredSize() : m.getMinimumSize();
+
+ // Can't add the component to current row. Start a new row.
+
+ if (rowWidth + d.width > maxWidth)
+ {
+ addRow(dim, rowWidth, rowHeight);
+ rowWidth = 0;
+ rowHeight = 0;
+ }
+
+ // Add a horizontal gap for all components after the first
+
+ if (rowWidth != 0)
+ {
+ rowWidth += hgap;
+ }
+
+ rowWidth += d.width;
+ rowHeight = Math.max(rowHeight, d.height);
+ }
+ }
+
+ addRow(dim, rowWidth, rowHeight);
+
+ dim.width += horizontalInsetsAndGap;
+ dim.height += insets.top + insets.bottom + vgap * 2;
+
+ // When using a scroll pane or the DecoratedLookAndFeel we need to
+ // make sure the preferred size is less than the size of the
+ // target containter so shrinking the container size works
+ // correctly. Removing the horizontal gap is an easy way to do this.
+
+ Container scrollPane = SwingUtilities.getAncestorOfClass(JScrollPane.class, target);
+
+ if (scrollPane != null && target.isValid())
+ {
+ dim.width -= (hgap + 1);
+ }
+
+ return dim;
+ }
+ }
+
+ /*
+ * A new row has been completed. Use the dimensions of this row
+ * to update the preferred size for the container.
+ *
+ * @param dim update the width and height when appropriate
+ * @param rowWidth the width of the row to add
+ * @param rowHeight the height of the row to add
+ */
+ private void addRow(Dimension dim, int rowWidth, int rowHeight)
+ {
+ dim.width = Math.max(dim.width, rowWidth);
+
+ if (dim.height > 0)
+ {
+ dim.height += getVgap();
+ }
+
+ dim.height += rowHeight;
+ }