Revision: 8971
Author: j...@google.com
Date: Thu Oct 7 10:04:32 2010
Log: Fix the DevMode Swing UI to avoid clipping buttons when the URL
is too large or the window is resized.
Patch by: jat
Review by: fredsa
Review at http://gwt-code-reviews.appspot.com/952802
http://code.google.com/p/google-web-toolkit/source/detail?r=8971
Added:
/trunk/dev/core/src/com/google/gwt/dev/shell/WrapLayout.java
Modified:
/trunk/dev/core/src/com/google/gwt/dev/ModuleTabPanel.java
/trunk/dev/core/src/com/google/gwt/dev/WebServerPanel.java
/trunk/dev/core/src/com/google/gwt/dev/shell/ShellMainWindow.java
/trunk/dev/core/src/com/google/gwt/dev/shell/log/SwingLoggerPanel.java
=======================================
--- /dev/null
+++ /trunk/dev/core/src/com/google/gwt/dev/shell/WrapLayout.java Thu Oct 7
10:04:32 2010
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may
not
+ * use this file except in compliance with the License. You may obtain a
copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
under
+ * the License.
+ */
+
+/*
+ * Taken from http://tips4java.wordpress.com/2008/11/06/wrap-layout/ and
+ * originally written by Rob Camick. The About link for the web site at
+ * http://tips4java.wordpress.com/about/ says this about IP rights:
+ *
+ * "You are free to use and/or modify any or all code posted on the Java
Tips
+ * Weblog without restriction. A credit in the code comments would be nice,
+ * but not in any way mandatory."
+ */
+package com.google.gwt.dev.shell;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Insets;
+
+/**
+ * FlowLayout subclass that fully supports wrapping of components.
+ */
+public class WrapLayout extends FlowLayout {
+ private Dimension preferredLayoutSize;
+
+ /**
+ * 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);
+ }
+
+ /**
+ * Layout the components in the Container using the layout logic of the
parent
+ * FlowLayout class.
+ *
+ * @param target the Container using this WrapLayout
+ */
+ @Override
+ public void layoutContainer(Container target) {
+ Dimension size = preferredLayoutSize(target);
+
+ // When a frame is minimized or maximized the preferred size of the
+ // Container is assumed not to change. Therefore we need to force a
+ // validate() to make sure that space, if available, is allocated to
+ // the panel using a WrapLayout.
+
+ if (size.equals(preferredLayoutSize)) {
+ super.layoutContainer(target);
+ } else {
+ preferredLayoutSize = size;
+ Container top = target;
+
+ while (top.getParent() != null) {
+ top = top.getParent();
+ }
+
+ top.validate();
+ }
+ }
+
+ /**
+ * 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) {
+ return layoutSize(target, false);
+ }
+
+ /**
+ * 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);
+ }
+
+ /*
+ * 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;
+ }
+
+ /**
+ * 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;
+
+ 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();
+ if (rowWidth + d.width > maxWidth) {
+ // Can't add the component to current row. Start a new row.
+ addRow(dim, rowWidth, rowHeight);
+ rowWidth = 0;
+ rowHeight = 0;
+ }
+ if (rowWidth != 0) {
+ // Add a horizontal gap for all components after the first
+ 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.
+
+ dim.width -= (hgap + 1);
+
+ return dim;
+ }
+ }
+}
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/ModuleTabPanel.java Mon Nov 23
16:21:36 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/ModuleTabPanel.java Thu Oct 7
10:04:32 2010
@@ -17,6 +17,7 @@
import com.google.gwt.core.ext.TreeLogger.Type;
import com.google.gwt.dev.SwingUI.TabPanelCollection;
+import com.google.gwt.dev.shell.WrapLayout;
import com.google.gwt.dev.util.BrowserInfo;
import java.awt.BorderLayout;
@@ -315,7 +316,7 @@
super(new BorderLayout());
this.tabPanelCollection = tabPanelCollection;
topPanel = new JPanel();
- sessionDropdownPanel = new JPanel();
+ sessionDropdownPanel = new JPanel(new WrapLayout());
sessionDropdownPanel.add(new JLabel("Session: "));
sessionDropdown = new JComboBox();
sessionDropdown.addActionListener(new ActionListener() {
@@ -330,7 +331,7 @@
sessionDropdownPanel.setEnabled(false);
sessionDropdownPanel.setVisible(false);
topPanel.add(sessionDropdownPanel);
- moduleDropdownPanel = new JPanel();
+ moduleDropdownPanel = new JPanel(new WrapLayout());
moduleDropdownPanel.add(new JLabel("Module: "));
moduleDropdown = new JComboBox();
moduleDropdown.addActionListener(new ActionListener() {
@@ -349,9 +350,8 @@
moduleDropdownPanel.setVisible(false);
topPanel.add(moduleDropdownPanel);
add(topPanel, BorderLayout.NORTH);
- deckPanel = new JPanel();
cardLayout = new CardLayout();
- deckPanel.setLayout(cardLayout);
+ deckPanel = new JPanel(cardLayout);
add(deckPanel);
// Construct the tab title and tooltip
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/WebServerPanel.java Tue Jun 22
06:26:45 2010
+++ /trunk/dev/core/src/com/google/gwt/dev/WebServerPanel.java Thu Oct 7
10:04:32 2010
@@ -16,6 +16,7 @@
package com.google.gwt.dev;
import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.dev.shell.WrapLayout;
import com.google.gwt.dev.shell.log.SwingLoggerPanel;
import java.awt.BorderLayout;
@@ -52,7 +53,7 @@
super(new BorderLayout());
logWindow = new SwingLoggerPanel(maxLevel, logFile);
if (restartServerAction != null) {
- JPanel panel = new JPanel();
+ JPanel panel = new JPanel(new WrapLayout());
JButton restartButton = new JButton("Restart Server");
restartButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/shell/ShellMainWindow.java Tue
Nov 24 17:17:57 2009
+++ /trunk/dev/core/src/com/google/gwt/dev/shell/ShellMainWindow.java Thu
Oct 7 10:04:32 2010
@@ -163,6 +163,7 @@
private JButton defaultBrowserButton;
private JButton copyToClipboardButton;
private JLabel loadingMessage;
+ private JPanel launchPanel;
/**
* Create the main window with the top-level logger and launch controls.
@@ -174,7 +175,7 @@
*/
public ShellMainWindow(TreeLogger.Type maxLevel, File logFile) {
super(new BorderLayout());
- JPanel launchPanel = new JPanel();
+ launchPanel = new JPanel(new WrapLayout());
launchPanel.setBorder(BorderFactory.createTitledBorder(
"Launch GWT Module"));
launchPanel.add(new JLabel("Startup URL:"));
@@ -241,6 +242,8 @@
defaultBrowserButton.setEnabled(true);
copyToClipboardButton.setVisible(true);
copyToClipboardButton.setEnabled(true);
+ launchPanel.revalidate();
+ launchPanel.repaint();
}
/**
=======================================
--- /trunk/dev/core/src/com/google/gwt/dev/shell/log/SwingLoggerPanel.java
Wed Jan 13 14:01:33 2010
+++ /trunk/dev/core/src/com/google/gwt/dev/shell/log/SwingLoggerPanel.java
Thu Oct 7 10:04:32 2010
@@ -20,6 +20,7 @@
import com.google.gwt.dev.BootStrapPlatform;
import com.google.gwt.dev.shell.CloseButton;
import com.google.gwt.dev.shell.CloseButton.Callback;
+import com.google.gwt.dev.shell.WrapLayout;
import com.google.gwt.dev.shell.log.SwingTreeLogger.LogEvent;
import com.google.gwt.dev.util.BrowserLauncher;
import com.google.gwt.dev.util.log.AbstractTreeLogger;
@@ -298,9 +299,8 @@
levelFilter = maxLevel;
// TODO(jat): how to make the topPanel properly layout items
// when the window is resized
- topPanel = new JPanel();
- topPanel.setLayout(new BorderLayout());
- JPanel logButtons = new JPanel();
+ topPanel = new JPanel(new BorderLayout());
+ JPanel logButtons = new JPanel(new WrapLayout());
JButton expandButton = new JButton("Expand All");
expandButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
--
http://groups.google.com/group/Google-Web-Toolkit-Contributors