Added the DecoratorPanel, which is a Widget that wraps another Widget in a 9-box that can be used to create rounded corners.
Issue: 883
Patch by: jlabanca, ecc
Review by: ecc
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1875 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/ui/DecoratorPanel.java b/user/src/com/google/gwt/user/client/ui/DecoratorPanel.java
new file mode 100644
index 0000000..5ed9464
--- /dev/null
+++ b/user/src/com/google/gwt/user/client/ui/DecoratorPanel.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2008 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.
+ */
+package com.google.gwt.user.client.ui;
+
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+
+/**
+ * <p>
+ * A {@link SimplePanel} that wraps its contents in stylized boxes, which can be
+ * used to add rounded corners to a {@link Widget}.
+ * </p>
+ * <p>
+ * Wrapping a {@link Widget} in a "9-box" allows users to specify images in each
+ * of the corners and along the four borders. This method allows the content
+ * within the {@link DecoratorPanel} to resize without disrupting the look of
+ * the border. In addition, rounded corners can generally be combined into a
+ * single image file, which reduces the number of downloaded files at startup.
+ * This class also simplifies the process of using AlphaImageLoaders to support
+ * 8-bit transparencies (anti-aliasing and shadows) in ie6, which does not
+ * support them normally.
+ * </p>
+ *
+ * <h3>CSS Style Rules</h3>
+ * <ul class='css'>
+ * <li>.gwt-DecoratorPanel { the panel }</li>
+ * <li>.gwt-DecoratorPanel .top { the top row }</li>
+ * <li>.gwt-DecoratorPanel .topLeft { the top left cell }</li>
+ * <li>.gwt-DecoratorPanel .topLeftInner { the inner element of the cell }</li>
+ * <li>.gwt-DecoratorPanel .topCenter { the top center cell }</li>
+ * <li>.gwt-DecoratorPanel .topCenterInner { the inner element of the cell }</li>
+ * <li>.gwt-DecoratorPanel .topRight { the top right cell }</li>
+ * <li>.gwt-DecoratorPanel .topRightInner { the inner element of the cell }</li>
+ * <li>.gwt-DecoratorPanel .middle { the middle row }</li>
+ * <li>.gwt-DecoratorPanel .middleLeft { the middle left cell }</li>
+ * <li>.gwt-DecoratorPanel .middleLeftInner { the inner element of the cell }</li>
+ * <li>.gwt-DecoratorPanel .middleCenter { the middle center cell }</li>
+ * <li>.gwt-DecoratorPanel .middleCenterInner { the inner element of the cell }</li>
+ * <li>.gwt-DecoratorPanel .middleRight { the middle right cell }</li>
+ * <li>.gwt-DecoratorPanel .middleRightInner { the inner element of the cell }</li>
+ * <li>.gwt-DecoratorPanel .bottom { the bottom row }</li>
+ * <li>.gwt-DecoratorPanel .bottomLeft { the bottom left cell }</li>
+ * <li>.gwt-DecoratorPanel .bottomLeftInner { the inner element of the cell }</li>
+ * <li>.gwt-DecoratorPanel .bottomCenter { the bottom center cell }</li>
+ * <li>.gwt-DecoratorPanel .bottomCenterInner { the inner element of the cell }</li>
+ * <li>.gwt-DecoratorPanel .bottomRight { the bottom right cell }</li>
+ * <li>.gwt-DecoratorPanel .bottomRightInner { the inner element of the cell }</li>
+ * </ul>
+ */
+public class DecoratorPanel extends SimplePanel {
+ /**
+ * The default style name.
+ */
+ private static final String DEFAULT_STYLENAME = "gwt-DecoratorPanel";
+
+ /**
+ * The default styles applied to each row.
+ */
+ private static final String[] DEFAULT_ROW_STYLENAMES = {
+ "top", "middle", "bottom"};
+
+ /**
+ * Create a new row with a specific style name. The row will contain three
+ * cells (Left, Center, and Right), each prefixed with the specified style
+ * name.
+ *
+ * This method allows Widgets to reuse the code on a DOM level, without
+ * creating a DecoratorPanel Widget.
+ *
+ * @param styleName the style name
+ * @return the new row {@link Element}
+ */
+ static Element createTR(String styleName) {
+ Element trElem = DOM.createTR();
+ setStyleName(trElem, styleName);
+ DOM.appendChild(trElem, createTD(styleName + "Left"));
+ DOM.appendChild(trElem, createTD(styleName + "Center"));
+ DOM.appendChild(trElem, createTD(styleName + "Right"));
+ return trElem;
+ }
+
+ /**
+ * Create a new table cell with a specific style name.
+ *
+ * @param styleName the style name
+ * @return the new cell {@link Element}
+ */
+ private static Element createTD(String styleName) {
+ Element tdElem = DOM.createTD();
+ Element inner = DOM.createDiv();
+ DOM.appendChild(tdElem, inner);
+ setStyleName(tdElem, styleName);
+ setStyleName(inner, styleName + "Inner");
+ return tdElem;
+ }
+
+ /**
+ * The container element at the center of the panel.
+ */
+ private Element containerElem;
+
+ /**
+ * The table body element.
+ */
+ private Element tbody;
+
+ /**
+ * Create a new {@link DecoratorPanel}.
+ */
+ public DecoratorPanel() {
+ this(DEFAULT_ROW_STYLENAMES, 1);
+ }
+
+ /**
+ * Creates a new panel using the specified style names to apply to each row.
+ * Each row will contain three cells (Left, Center, and Right). The Center
+ * cell in the containerIndex row will contain the {@link Widget}.
+ *
+ * @param rowStyles an array of style names to apply to each row
+ * @param containerIndex the index of the container row
+ */
+ DecoratorPanel(String[] rowStyles, int containerIndex) {
+ super(DOM.createTable());
+
+ // Add a tbody
+ Element table = getElement();
+ tbody = DOM.createTBody();
+ DOM.appendChild(table, tbody);
+ DOM.setElementPropertyInt(table, "cellSpacing", 0);
+ DOM.setElementPropertyInt(table, "cellPadding", 0);
+
+ // Add each row
+ for (int i = 0; i < rowStyles.length; i++) {
+ Element row = createTR(rowStyles[i]);
+ DOM.appendChild(tbody, row);
+ if (i == containerIndex) {
+ containerElem = DOM.getFirstChild(DOM.getChild(row, 1));
+ }
+ }
+
+ // Set the overall style name
+ setStyleName(DEFAULT_STYLENAME);
+ }
+
+ @Override
+ protected Element getContainerElement() {
+ return containerElem;
+ }
+
+ /**
+ * Get a specific Element from the panel.
+ *
+ * @param row the row index
+ * @param cell the cell index
+ * @return the Element at the given row and cell
+ */
+ Element getCellElement(int row, int cell) {
+ Element tr = DOM.getChild(tbody, row);
+ return DOM.getChild(tr, cell);
+ }
+}
diff --git a/user/test/com/google/gwt/user/UISuite.java b/user/test/com/google/gwt/user/UISuite.java
index a26f39c..16b09ab 100644
--- a/user/test/com/google/gwt/user/UISuite.java
+++ b/user/test/com/google/gwt/user/UISuite.java
@@ -19,6 +19,7 @@
import com.google.gwt.user.client.ui.CheckBoxTest;
import com.google.gwt.user.client.ui.CustomButtonTest;
import com.google.gwt.user.client.ui.DOMTest;
+import com.google.gwt.user.client.ui.DecoratorPanelTest;
import com.google.gwt.user.client.ui.DelegatingKeyboardListenerCollectionTest;
import com.google.gwt.user.client.ui.DialogBoxTest;
import com.google.gwt.user.client.ui.DisclosurePanelTest;
@@ -68,6 +69,7 @@
suite.addTestSuite(AbsolutePanelTest.class);
suite.addTestSuite(CheckBoxTest.class);
suite.addTestSuite(CustomButtonTest.class);
+ suite.addTestSuite(DecoratorPanelTest.class);
suite.addTestSuite(DelegatingKeyboardListenerCollectionTest.class);
suite.addTestSuite(DialogBoxTest.class);
suite.addTestSuite(DisclosurePanelTest.class);
diff --git a/user/test/com/google/gwt/user/client/ui/DecoratorPanelTest.java b/user/test/com/google/gwt/user/client/ui/DecoratorPanelTest.java
new file mode 100644
index 0000000..630106d
--- /dev/null
+++ b/user/test/com/google/gwt/user/client/ui/DecoratorPanelTest.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2008 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.
+ */
+
+package com.google.gwt.user.client.ui;
+
+import com.google.gwt.junit.client.GWTTestCase;
+import com.google.gwt.user.client.DOM;
+import com.google.gwt.user.client.Element;
+
+/**
+ * Test for {@link DecoratorPanel}.
+ */
+public class DecoratorPanelTest extends GWTTestCase {
+ /**
+ * Assert that an element has the specified class name.
+ *
+ * @param elem the DOM {@link Element}
+ * @param styleName the style name the element should have
+ */
+ private static void assertStyleName(Element elem, String styleName) {
+ assertEquals(styleName, DOM.getElementProperty(elem, "className"));
+ }
+
+ @Override
+ public String getModuleName() {
+ return "com.google.gwt.user.User";
+ }
+
+ /**
+ * Test addition and removal of widgets.
+ */
+ public void testAddRemoveWidget() {
+ DecoratorPanel panel = new DecoratorPanel();
+ Label contents = new Label("test");
+ panel.setWidget(contents);
+ assertEquals(contents, panel.getWidget());
+ }
+
+ /**
+ * Test the ability to define custom rows.
+ */
+ public void testCustomRows() {
+ String[] rowStyles = {"rowA", "rowB", "rowC", "rowD"};
+ DecoratorPanel panel = new DecoratorPanel(rowStyles, 2);
+
+ // Check the styles of each row
+ for (int i = 0; i < rowStyles.length; i++) {
+ String rowStyle = rowStyles[i];
+ assertStyleName(DOM.getParent(panel.getCellElement(i, 0)), rowStyle);
+ assertStyleName(panel.getCellElement(i, 0), rowStyle + "Left");
+ assertStyleName(panel.getCellElement(i, 1), rowStyle + "Center");
+ assertStyleName(panel.getCellElement(i, 2), rowStyle + "Right");
+ }
+
+ // Check the container element
+ assertEquals(DOM.getFirstChild(panel.getCellElement(2, 1)),
+ panel.getContainerElement());
+ }
+
+ /**
+ * Test the default styles.
+ */
+ public void testDefaultStyles() {
+ String[] rowStyles = {"top", "middle", "bottom"};
+ DecoratorPanel panel = new DecoratorPanel();
+
+ // Check the styles of each row
+ for (int i = 0; i < rowStyles.length; i++) {
+ String rowStyle = rowStyles[i];
+ assertStyleName(DOM.getParent(panel.getCellElement(i, 0)), rowStyle);
+ assertStyleName(panel.getCellElement(i, 0), rowStyle + "Left");
+ assertStyleName(panel.getCellElement(i, 1), rowStyle + "Center");
+ assertStyleName(panel.getCellElement(i, 2), rowStyle + "Right");
+ }
+
+ // Check the container element
+ assertEquals(DOM.getFirstChild(panel.getCellElement(1, 1)),
+ panel.getContainerElement());
+ }
+}