/* * 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.i18n.client.LocaleInfo; 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> * This widget will <em>only</em> work in quirks mode in most cases. * Specifically, setting the height or width of the DecoratorPanel will result * in rendering issues. * </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>Setting the Size:</h3> * <p> * If you set the width or height of the {@link DecoratorPanel}, you need to * set the height and width of the middleCenter cell to 100% so that the * middleCenter cell takes up all of the available space. If you do not set the * width and height of the {@link DecoratorPanel}, it will wrap its contents * tightly. * </p> * * <pre> * .gwt-DecoratorPanel .middleCenter { * height: 100%; * width: 100%; * } * </pre> * * <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); if (LocaleInfo.getCurrentLocale().isRTL()) { DOM.appendChild(trElem, createTD(styleName + "Right")); DOM.appendChild(trElem, createTD(styleName + "Center")); DOM.appendChild(trElem, createTD(styleName + "Left")); } else { 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); } /** * 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 */ protected Element getCellElement(int row, int cell) { Element tr = DOM.getChild(tbody, row); Element td = DOM.getChild(tr, cell); return DOM.getFirstChild(td); } @Override protected Element getContainerElement() { return containerElem; } }