\r
import java.awt.BorderLayout;\r
import java.awt.Color;\r
+import java.awt.FlowLayout;\r
import java.awt.Font;\r
import java.awt.Frame;\r
-import java.awt.GridBagConstraints;\r
-import java.awt.GridBagLayout;\r
import java.awt.Image;\r
import java.awt.Rectangle;\r
import java.awt.datatransfer.Clipboard;\r
import org.simantics.ui.dnd.LocalObjectTransferable;\r
import org.simantics.ui.fonts.Fonts;\r
import org.simantics.utils.ui.dialogs.ShowMessage;\r
+import org.simantics.utils.ui.awt.WrapLayout;\r
import org.simantics.utils.ui.jface.ActiveSelectionProvider;\r
\r
@SuppressWarnings({ "rawtypes", "unchecked" })\r
\r
if (addExpressionField) {\r
\r
- JPanel tools = new JPanel(new GridBagLayout());\r
+ JPanel tools = new JPanel(new WrapLayout(FlowLayout.LEADING, 0, 0));\r
panel.add(tools, BorderLayout.PAGE_START);\r
\r
- GridBagConstraints c = new GridBagConstraints(); \r
+ tools.add(this.font);\r
\r
- c.gridx = 0;\r
- c.anchor = GridBagConstraints.WEST;\r
- tools.add(this.font, c);\r
+ tools.add(foreground);\r
\r
- c.gridx = 1;\r
- tools.add(foreground, c);\r
+ tools.add(background);\r
\r
- c.gridx = 2;\r
- tools.add(background, c);\r
+ tools.add(align_left);\r
+ tools.add(align_hcenter);\r
+ tools.add(align_right);\r
\r
- c.gridx = 3;\r
- tools.add(align_left, c);\r
- c.gridx = 4;\r
- tools.add(align_hcenter, c);\r
- c.gridx = 5;\r
- tools.add(align_right, c);\r
+ tools.add(align_top);\r
+ tools.add(align_vcenter);\r
+ tools.add(align_bottom);\r
\r
- c.gridx = 6;\r
- tools.add(align_top, c);\r
- c.gridx = 7;\r
- tools.add(align_vcenter, c);\r
- c.gridx = 8;\r
- tools.add(align_bottom, c);\r
+ tools.add(borders);\r
\r
- c.gridx = 9;\r
- tools.add(borders, c);\r
+ tools.add(lock);\r
+ tools.add(unlock);\r
\r
- c.gridx = 10;\r
- tools.add(lock, c);\r
- c.gridx = 11;\r
- tools.add(unlock, c);\r
+ tools.add(merge);\r
+ tools.add(unmerge);\r
\r
- c.gridx = 12;\r
- tools.add(merge, c);\r
- c.gridx = 13;\r
- tools.add(unmerge, c);\r
- \r
- c.gridx = 14;\r
- tools.add(inputSource, c);\r
+ tools.add(inputSource);\r
\r
- c.gridx = 15;\r
- tools.add(sheets, c);\r
+ tools.add(sheets);\r
\r
- c.gridx = 16;\r
- tools.add(initialConditions, c);\r
- \r
- c.gridx = 17;\r
- tools.add(saveIc, c);\r
- \r
- c.gridx = 18;\r
- tools.add(context, c);\r
- \r
- c.gridx = 19;\r
- tools.add(operationMode, c);\r
- \r
- c.gridx = 20;\r
- tools.add(iterationEnabled, c);\r
- \r
- c.gridx = 21;\r
- tools.add(iterationLimit, c);\r
-\r
- c.gridx = 0;\r
- c.gridy = 1;\r
- c.gridwidth = 22;\r
- c.gridheight = 1;\r
- c.weighty = 0.0;\r
- c.weightx = 1.0;\r
- c.fill = GridBagConstraints.HORIZONTAL;\r
-\r
- tools.add(expression,c);\r
+ tools.add(initialConditions);\r
+\r
+ tools.add(saveIc);\r
+\r
+ tools.add(context);\r
+\r
+ tools.add(operationMode);\r
+\r
+ tools.add(iterationEnabled);\r
+\r
+ tools.add(iterationLimit);\r
+\r
+ tools.add(expression);\r
\r
}\r
panel.add(scroll, BorderLayout.CENTER);\r
--- /dev/null
+/*******************************************************************************\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
+}
\ No newline at end of file