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

Reply via email to