001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2007 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.visualweb.css2;
042:
043: import org.netbeans.modules.visualweb.api.designer.cssengine.CssProvider;
044: import org.netbeans.modules.visualweb.designer.CssUtilities;
045: import java.awt.Color;
046: import java.awt.Font;
047: import java.awt.FontMetrics;
048: import java.awt.Graphics;
049: import java.awt.Insets;
050: import java.awt.Rectangle;
051:
052: import javax.swing.UIManager;
053:
054: import org.w3c.dom.Element;
055:
056: import org.netbeans.modules.visualweb.designer.DesignerUtils;
057: import org.netbeans.modules.visualweb.designer.WebForm;
058: import org.netbeans.modules.visualweb.api.designer.cssengine.XhtmlCss;
059:
060: /**
061: * <p>
062: * CustomButtonBox represents the painting of a button that is not using
063: * the native platform look and feel for buttons. You typically get these
064: * buttons if your button specifies the button appearance for example using
065: * background-image.
066: * </p>
067: * @todo Figure out why the button width does not seem to obey my width settings.
068: * Am I adding in the padding etc.
069: * @todo Make sure that buttons which DON'T set a border but do set a
070: * background-image behave the same way as in the browser
071: * @todo Paint watermark?
072: * @todo I should make sure the text is clipped inside the borders!
073: * @todo Try to make rounded borders!
074: * @todo The button border on the ACME theme is cut off
075: *
076: * @author Tor Norbye
077: */
078: public class CustomButtonBox extends CssBox {
079: private String string;
080: private Color fg;
081: private char[] stringChars;
082: private FontMetrics fm;
083: private int textWidth;
084: private int prefWidth;
085: private int prefHeight;
086:
087: // private int baseline;
088:
089: /**
090: * Create a StringBox for the given string
091: *
092: * @param webform The <code>WebForm</code>
093: * @param element The element this string box is associated with
094: * @param boxType Type of box.
095: * @param string The string to manage
096: * @param width The width to use for the box
097: * @param height The height to use for the box
098: */
099: public CustomButtonBox(WebForm webform, Element element,
100: BoxType boxType, String string, CssBorder border) {
101: this (webform, element, boxType, string, border, true);
102: }
103:
104: /**
105: * Create a StringBox for the given string
106: *
107: * @param webform The <code>WebForm</code>
108: * @param element The element this string box is associated with
109: * @param boxType Type of box.
110: * @param string The string to manage
111: * @param width The width to use for the box
112: * @param height The height to use for the box
113: */
114: public CustomButtonBox(WebForm webform, Element element,
115: BoxType boxType, String string, CssBorder border,
116: boolean inline) {
117: super (webform, element, boxType, inline, true);
118: this .string = string;
119: this .stringChars = string.toCharArray();
120: this .border = border;
121:
122: // See if we have SPECIFIC font or color settings to apply, otherwise
123: // stick with the defaults....
124: // XhtmlCssEngine engine = CssLookup.getCssEngine(element);
125: Font font;
126:
127: // TODO check font-family, font-variant etc. too
128: // if (engine.isInheritedValue((RaveElement)element, XhtmlCss.FONT_SIZE_INDEX)) {
129: if (CssProvider.getEngineService()
130: .isInheritedStyleValueForElement(element,
131: XhtmlCss.FONT_SIZE_INDEX)) {
132: font = UIManager.getFont("Button.font"); // NOI18N
133: } else {
134: // font = CssLookup.getFont(element, DesignerSettings.getInstance().getDefaultFontSize());
135: // font = CssProvider.getValueService().getFontForElement(element, DesignerSettings.getInstance().getDefaultFontSize(), Font.PLAIN);
136: font = CssUtilities.getDesignerFontForElement(element,
137: string, webform.getDefaultFontSize());
138: }
139:
140: // fm = Toolkit.getDefaultToolkit().getFontMetrics(font);
141: fm = DesignerUtils.getFontMetrics(font);
142:
143: textWidth = DesignerUtils.getNonTabbedTextWidth(stringChars, 0,
144: stringChars.length, fm);
145: prefWidth = textWidth;
146: prefHeight = fm.getHeight();
147: this .width = prefWidth;
148: this .height = prefHeight;
149: this .contentWidth = this .width;
150: this .contentHeight = this .height;
151:
152: // if (engine.isInheritedValue((RaveElement)element, XhtmlCss.COLOR_INDEX)) {
153: if (CssProvider.getEngineService()
154: .isInheritedStyleValueForElement(element,
155: XhtmlCss.COLOR_INDEX)) {
156: // XXX Should we default to something else?
157: fg = Color.black;
158: } else {
159: // fg = CssLookup.getColor(element, XhtmlCss.COLOR_INDEX);
160: fg = CssProvider.getValueService().getColorForElement(
161: element, XhtmlCss.COLOR_INDEX);
162:
163: if (fg == null) {
164: if (fg == null) {
165: fg = Color.black;
166: }
167: }
168: }
169: }
170:
171: protected void initializeBorder() {
172: if (border == null) {
173: super .initializeBorder();
174: }
175:
176: if (border == null) {
177: border = CssBorder.getDesignerBorder();
178: }
179:
180: leftBorderWidth = border.getLeftBorderWidth();
181: topBorderWidth = border.getTopBorderWidth();
182: bottomBorderWidth = border.getBottomBorderWidth();
183: rightBorderWidth = border.getRightBorderWidth();
184:
185: // baseline = fm.getHeight() - fm.getDescent() + topBorderWidth + topPadding;
186:
187: //baseline += (height-baseline)/2;
188: }
189:
190: public int getIntrinsicWidth() {
191: return prefWidth;
192: }
193:
194: public int getIntrinsicHeight() {
195: return prefHeight;
196: }
197:
198: // Unlike normal replaced boxes, we don't want the buttons to
199: // scale if only one dimension is set.
200: protected void updateAutoContentSize() {
201: if (contentWidth == AUTO) {
202: contentWidth = getIntrinsicWidth();
203: }
204:
205: if (contentHeight == AUTO) {
206: contentHeight = getIntrinsicHeight();
207: }
208: }
209:
210: public int getBaseline() {
211: // return baseline;
212: // #109564 It corresponds to the height.
213: return height;
214: }
215:
216: // public String toString() {
217: // return "CustomButtonBox[" + paramString() + "]";
218: // }
219:
220: protected String paramString() {
221: return super .paramString() + ", " + string;
222: }
223:
224: protected void paintBackground(Graphics g, int px, int py) {
225: // Do nothing. We paint by calling super directly. This
226: // is because paintBackground() on inline boxes is called by
227: // the paragraph formatter - it paints the backgrounds, then
228: // the text selection highlight, then the foregrounds. However,
229: // for these buttons we don't want the selection highlight to
230: // show up between the background and foreground like we do
231: // for text, so make this call do nothing.
232: }
233:
234: public void paint(Graphics g, int px, int py) {
235: if (hidden) {
236: return;
237: }
238:
239: px += getX();
240: py += getY();
241:
242: px += leftMargin;
243: py += effectiveTopMargin;
244:
245: super .paintBackground(g, px, py);
246:
247: // XXX decoration
248: paintDecoration(g, px + getWidth(), py);
249:
250: int x = (width - textWidth) / 2;
251: int y = (height - fm.getHeight()) / 2;
252:
253: if (x < 0) {
254: x = 0;
255: }
256:
257: if (y < 0) {
258: y = 0;
259: }
260:
261: x += px;
262: y += py;
263:
264: g.setColor(fg);
265: g.setFont(fm.getFont());
266:
267: // determine the y coordinate to render the glyphs
268: int yadj = (y + fm.getHeight()) - fm.getDescent();
269:
270: // Clip contents in case text is too large
271: Rectangle sharedClipRect = ContainerBox.sharedClipRect;
272: g.getClipBounds(sharedClipRect);
273:
274: int cx = sharedClipRect.x;
275: int cy = sharedClipRect.y;
276: int cw = sharedClipRect.width;
277: int ch = sharedClipRect.height;
278: g.clipRect(px, py, width, height);
279:
280: // Draw text!
281: g.drawChars(stringChars, 0, stringChars.length, x, yadj);
282:
283: // if (width > WATERMARK_SIZE && height > WATERMARK_SIZE) { // don't draw watermarks for tiny images
284: // paintFacesWatermark(g, px, py);
285: // }
286: // Restore clip
287: g.setClip(cx, cy, cw, ch);
288: }
289:
290: public boolean isBorderSizeIncluded() {
291: return true;
292: }
293:
294: public Insets getCssSizeInsets() {
295: return new Insets(0, 0, 0, 0);
296: }
297: }
|