Java tutorial
/* * 2010, seriouslynonamesleft@gmail.com * * This work is derivative of org.cobogw.gwt.user.client.ui.RoundedPanel, which * can be found at http://code.google.com/p/cobogw/. Modifications are marked. * * 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 org.orwell.widgets; // Modification: Changed namespace import com.google.gwt.dom.client.DivElement; import com.google.gwt.dom.client.Document; import com.google.gwt.dom.client.Element; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Widget; /** * The <code>RoundedPanel</code> class adds similar rounded corners, as seen * in other Google applications, to a widget. This is done by adding several * <code>div</code> Elements around a Widget. The HTML code roughly for a * corner height 2 looks as follows: * * <pre> * <div> * <div style="margin:0 2px"></div> * <div style="margin:0 1px"></div> * <div>your widget</div> * <div style="margin:0 1px"></div> * <div style="margin:0 2px"></div> * </div> * </pre> * * To add the rounded corners to a widget start simply wrap your own widget * in the <code>RoundedPanel</code> class, for example with all corners * rounded: * * <pre> * // all 4 corners are rounded. * RoundedPanel rp = new RoundedPanel(yourWidget); * // use rp where you would use 'yourWidget' otherwise * </pre> * * Or with custom set corners, like only on the left: * * <pre> * // custom set corners * RoundedPanel rp = new RoundedPanel(yourWidget, RoundedPanel.LEFT); * // use rp where you would use 'yourWidget' otherwise * </pre> * * By default the height of the corners is 2px. It is possible to set * a different height at construction time. The height can be a value * between and including 1 and 9. This value doesn't correspond exactly * with the height, e.g. 9 is 12px height. * * <pre> * // all 4 corners are rounded and height index 5 * RoundedPanel rp = new RoundedPanel(yourWidget, ALL, 5); * // use rp where you would use 'yourWidget' otherwise * </pre> * * There are 2 ways to set the color on the border programmatically. First via * {@link #setCornerColor(String)} and second via * {@link #setBorderColor(String)}. The second method will also add a solid * border style in the given color on the left and/or right of the widget. The * first method doesn't set a border style. Use the first method when you don't * want to have a border or when the background color of your widget is the same * as the background color of the rounded corners or if you wan to have the * flexibility to set the border via CSS. * * Example to set the color of the corners with {@link #setCornerColor(String)}: * * <pre> * // all 4 corners are rounded. * RoundedPanel rp = new RoundedPanel(yourWidget); * rp.setCornerColor("red"); * </pre> * * To add also a solid border style to the left and/or right of the widget use * {@link #setBorderColor(String)}: * * <pre> * // all 4 corners are rounded and solid border style left and right of widget * RoundedPanel rp = new RoundedPanel(yourWidget); * rp.setBorderColor("red"); * </pre> * * Default the CSS style name of the rounded corner divs is * <code>cbg-RP</code>. Use it to set the colors of the corner. For example: * * <pre> * .cbg-RP { background-color:#c3d9ff; } * </pre> * * A custom style might be needed when the corners are visible only when a panel * is selected (see the KitchenSink example modification below). Use the * <code>setCornerStyleName</code> method to set the custom style name. For * example set a custom style <code>my-RP</code> and add something like the * following to the style sheet: * * <pre> * .selected .my-RP { background-color:#c3d9ff; } * </pre> * * <h3>Adding rounded corners to DialogBox widgets</h3> * Adding rounded corners to a <code>DialogBox</code> is somewhat more * complicated. The problem with <code>DialogBox</code> is that it uses a * private panel and the <code>RoundedPanel</code> should be applied to this * private <code>Panel</code>. To add the rounded corners to a * <code>DialogBox</code> you have to rewrite the implementation of the * <code>DialogBox</code>. For the <code>DialogBox</code> widget this can * be done as follows. First create a new class like * <code>RoundedDialogBox</code> and copy the code from the original * <code>DialogBox</code> (Please take the copyright of this class into * account). Next make the following changes to the code: * * <pre> * // Private variable for RoundedPanel * private RoundedPanel rp; * </pre> * * In the constructor change: * * <pre> * super.add(panel); * </pre> * * into: * * <pre> * rp = new RoundedPanel(panel); * super.add(rp); * </pre> * * Next change the style, otherwise the style of the dialog box is applied to * the rounded lines too. Do this by changing the following line: * * <pre> * setStyleName("gwt-DialogBox"); * </pre> * * into: * * <pre> * panel.setStyleName("gwt-DialogBox"); * </pre> * * In your css add the color of the border, something like: * * <pre> * .cbg-RP { background-color:#AAAAAA; } * </pre> * * Now by extending your own dialog class on this <code>RoundedDialogBox</code> * instead of the original <code>DialogBox</code> you will have rounded * corners around your dialog. */ public class RoundedPanel extends SimplePanel { /** * <code>TOPLEFT</code> top left rounded corner */ public final static int TOPLEFT = 1; /** * <code>TOPRIGHT</code> top right rounded corner */ public final static int TOPRIGHT = 2; /** * <code>BOTTOMLEFT</code> bottom left rounded corner */ public final static int BOTTOMLEFT = 4; /** * <code>BOTTOMRIGHT</code> bottom right rounded corner */ public final static int BOTTOMRIGHT = 8; /** * <code>BOTTOM</code> rounded corners at the top */ public final static int TOP = TOPLEFT | TOPRIGHT; /** * <code>TOP</code> rounded corners at the bottom */ public final static int BOTTOM = BOTTOMLEFT | BOTTOMRIGHT; /** * <code>LEFT</code> rounded corners on the left side */ public final static int LEFT = TOPLEFT | BOTTOMLEFT; /** * <code>RIGHT</code> rounded corners on the right side */ public final static int RIGHT = TOPRIGHT | BOTTOMRIGHT; /** * <code>ALL</code> rounded corners on all sides */ public final static int ALL = TOP | BOTTOM; /** * Default border style */ public final static String RPSTYLE = "cbg-RP"; // Modification: Made member public /** * Lookup table for corner border width */ private final static int[][] CORNERBORDER = { { 1 }, { 1, 1 }, { 1, 1, 1 }, { 1, 1, 1, 1 }, { 1, 1, 1, 2, 1 }, { 1, 1, 1, 1, 2, 1 }, { 1, 1, 1, 1, 1, 2, 1 }, { 1, 1, 1, 1, 1, 2, 2, 1 }, { 1, 1, 1, 1, 1, 1, 2, 3, 1 } }; /** * Lookup table for corner height */ private final static int[][] CORNERHEIGHT = { { 1 }, { 1, 1 }, { 1, 1, 1 }, { 1, 1, 1, 1 }, { 2, 1, 1, 1, 1 }, { 2, 1, 1, 1, 1, 1 }, { 2, 1, 1, 1, 1, 1, 1 }, { 2, 1, 1, 1, 1, 1, 1, 1 }, { 3, 2, 1, 1, 1, 1, 1, 1, 1 } }; /** * Lookup table for corner margin */ private final static int[][] CORNERMARGIN = { { 1 }, { 1, 2 }, { 1, 2, 3 }, { 1, 2, 3, 4 }, { 1, 2, 3, 4, 6 }, { 1, 2, 3, 4, 5, 7 }, { 1, 2, 3, 4, 5, 6, 8 }, { 1, 2, 3, 4, 5, 6, 8, 10 }, { 1, 2, 3, 4, 5, 6, 7, 9, 12 }, }; /** * Element array containing all div elements of the top corner div's. */ protected final DivElement[] divt; /** * Element array containing all div elements of the bottom corner div's. */ protected final DivElement[] divb; /** * Index of the corner height. */ protected final int cornerHeight; /** * Index of which corners are set. */ protected final int corners; private final DivElement body; // body of widget private DivElement divElement; // div element containing widget /** * Creates a new <code>RoundedPanel</code> with all corners rounded and * height of corners 2px. Use <code>setWidget</code> to add the widget. */ public RoundedPanel() { this(ALL, 2); } /** * Creates a new <code>RoundedPanel</code> with custom rounding and height * of corners 2px but with no widget set. Use <code>setWidget</code> to add * widget. * * Every combination of corners can be set via <code>corners</code>. * Use the static constants to set the corners. For example, to create a * panel with only rounded corners at the left, use: * * <code>new RoundedPanel(RoundedPanel.LEFT);</code> * * @param corners set custom rounded corners */ public RoundedPanel(int corners) { this(corners, 2); } /** * Creates a new <code>RoundedPanel</code> with custom rounding and custom * height of the corners but with no widget set. Height can be value from * 1 to 9. The height for a value 5 or higher is actually larger, e.g. for * 5 the height is 6px. * Use {@link #setWidget(Widget)} to add widget. * * @param corners set custom rounded corners * @param cornerHeight height index between and including 1 and 9 * @throws IndexOutOfBoundsException when cornerHeight below 1 or above 9 */ public RoundedPanel(int corners, int cornerHeight) { super(); body = getElement().cast(); if (cornerHeight < 1 || cornerHeight > 9) { throw new IndexOutOfBoundsException("RoundedPanel height range is between and including 1 and 9"); } this.cornerHeight = cornerHeight; divt = new DivElement[cornerHeight]; divb = new DivElement[cornerHeight]; this.corners = corners; if (inMask(corners, TOP)) { final int ct = corners & TOP; for (int i = 0; i < cornerHeight; ++i) { divt[i] = addLine(ct, cornerHeight - (i + 1)); } } divElement = Document.get().createDivElement(); body.appendChild(divElement); if (inMask(corners, BOTTOM)) { final int cb = corners & BOTTOM; for (int i = cornerHeight - 1; i >= 0; --i) { divb[i] = addLine(cb, cornerHeight - (i + 1)); } } setCornerStyleName(RPSTYLE); } /** * Creates a new <code>RoundedPanel</code> with all corners rounded and * height 2px on the widget <code>w</code>. * * @param w widget to add corners to */ public RoundedPanel(Widget w) { this(w, ALL); } /** * Creates a new <code>RoundedPanel</code> with custom rounded corners * and height 2px on the widget <code>w</code>. * * @param w widget to add corners to * @param corners set custom rounded corners */ public RoundedPanel(Widget w, int corners) { this(w, corners, 2); } /** * Creates a new <code>RoundedPanel</code> with custom rounded corners * and custom height on widget <code>w</code>. * * @param w widget to add corners to * @param corners set custom rounded corners * @param cornerHeight height index between and including 1 and 9 * @throws IndexOutOfBoundsException when cornerHeight below 1 or above 9 */ public RoundedPanel(Widget w, int corners, int cornerHeight) { this(corners, cornerHeight); setWidget(w); } /** * Set the colors on the rounded borders and adds a border style on the * element wrapped around the widget. The width of the border (left and/or * right) is the same as the height of the rounding. * * <p>If NO border style (e.g. lines on the left and/or right side) for the * wrapped widget is desired use {@link #setCornerColor(String)}. * * @param borderColor color of the border */ public void setBorderColor(String borderColor) { setCornerColor(borderColor); setBorderContainer(borderColor, CORNERMARGIN[cornerHeight - 1][cornerHeight - 1]); } /** * Set the color on the rounded corners. When a different background color for * the widget is used, this will display as a block with rounded corners at * the top or bottom (depending on the rounding) in the given borderColor. * * <p>If border style (e.g. lines on the left and/or right side) for the * wrapped widget IS desired use {@link #setBorderColor(String)}. * * @param borderColor border color */ public void setCornerColor(String borderColor) { if (null != divt[0]) { for (int i = 0; i < cornerHeight; ++i) { divt[i].getStyle().setProperty("backgroundColor", borderColor); } } if (null != divb[0]) { for (int i = 0; i < cornerHeight; ++i) { divb[i].getStyle().setProperty("backgroundColor", borderColor); } } } /** * Set the CSS style name of the rounded corners div's. Default the CSS style * name is <code>cbg-RP</code>. Use it to set the colors of the corner. For * example: <code>.cbg-RP { background-color:#c3d9ff; }</code>. * * A custom style might be needed when the corners are visible only when a * panel is selected. Use this method to set the custom style name and add * something like the following to the style sheet: * * <code>.selected .cbg-RP { background-color:#c3d9ff; }</code> * Setting the color is also possible via the method * {@link #setCornerColor(String)}. * * @param style CSS style name */ public void setCornerStyleName(String style) { if (null != divt[0]) { for (int i = 0; i < cornerHeight; ++i) { divt[i].setClassName(style); } } if (null != divb[0]) { for (int i = 0; i < cornerHeight; ++i) { divb[i].setClassName(style); } } } //Modification: Overidden methods addStyleName and removeStyleName @Override public void addStyleName(String style) { Widget w = getWidget(); if (w != null) { w.addStyleName(style); setCornerStyleName(w.getStyleName()); } else { setCornerStyleName(style); } } @Override public void removeStyleName(String style) { Widget w = getWidget(); if (w != null) { w.removeStyleName(style); setCornerStyleName(w.getStyleName()); } else { setCornerStyleName(RPSTYLE); } } /** * Overwrite of parent getContainerElement() */ @Override protected com.google.gwt.user.client.Element getContainerElement() { return divElement.cast(); } /** * Convenience method to check if given <code>input</code> is with * the <code>mask</code>. * * @param input input to check * @param mask mask to check against * @return true if input within mask */ protected boolean inMask(int input, int mask) { return (input & mask) > 0; } /** * Set the left and/or right border on the container element. * * @param borderColor color of the border * @param borderWidth width of the border */ protected void setBorderContainer(String borderColor, int borderWidth) { setBorder(getContainerElement(), corners, borderColor); getContainerElement().getStyle().setProperty("borderWidth", "0 " + borderWidth + "px"); } /** * Set the border left and or right style and color attributes on the element. * * @param elem element to set the style attributes * @param corners corners to set the style attributes * @param borderColor color of the border */ protected void setBorder(Element elem, int corners, String borderColor) { if (inMask(corners, LEFT)) { elem.getStyle().setProperty("borderLeftStyle", "solid"); elem.getStyle().setProperty("borderLeftColor", borderColor); } if (inMask(corners, RIGHT)) { elem.getStyle().setProperty("borderRightStyle", "solid"); elem.getStyle().setProperty("borderRightColor", borderColor); } } /** * Creates div element representing part of the rounded corner. * * @param corner corner mask to set rounded corner * @param heightIndex margin width for line */ private DivElement addLine(int corner, int heightIndex) { // margin 4 fields : top right bottom left => "0 <width>px 0 <width>px" final String mw = CORNERMARGIN[cornerHeight - 1][heightIndex] + "px "; final String margin = "0 " + (inMask(corner, RIGHT) ? mw : "0 ") + "0 " + (inMask(corner, LEFT) ? mw : "0"); final DivElement div = Document.get().createDivElement(); div.getStyle().setPropertyPx("height", CORNERHEIGHT[cornerHeight - 1][heightIndex]); div.getStyle().setProperty("borderWidth", "0 " + CORNERBORDER[cornerHeight - 1][heightIndex] + "px"); div.getStyle().setProperty("margin", margin); //Font size set to work around IE's default minimal element height. div.getStyle().setPropertyPx("fontSize", 0); div.getStyle().setProperty("overflow", "hidden"); body.appendChild(div); return div; } }