001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.midp.chameleon;
028:
029: import javax.microedition.lcdui.*;
030:
031: /**
032: * Chameleon graphics utility class. This class is a collection of
033: * commonly used graphics routines. These routines can be used by
034: * layer implementations as well as widgets themselves.
035: */
036: public class CGraphicsUtil {
037:
038: /**
039: * Fill width from <code>start</code> to <code>end</code>
040: * with imgTop at <code>y1</code> coordinate and
041: * with imgBottom at <code>y2</code>coordinate.
042: *
043: * @param g The Graphics context to paint to
044: * @param imgTop The top image.
045: * @param imgBottom The bottom image.
046: * @param start start x co-ordinate of ImageItem
047: * @param end end x co-ordinate of ImageItem
048: * @param y1 y co-ordinate of Top ImageItem
049: * @param y2 y co-ordinate of Bottom ImageItem
050: */
051: public static void drawTop_BottomBorder(Graphics g, Image imgTop,
052: Image imgBottom, int start, int end, int y1, int y2) {
053: int imgWidth = imgTop.getWidth();
054: // The assumption is that imgTop and imgBottom will have
055: // the same width
056:
057: // save the clip, before clipping the width;
058: // we need to clip since the last imgTop and imgBottom images
059: // might go over the area that needs to be filled
060: int xClip = g.getClipX();
061: int clipWidth = g.getClipWidth();
062:
063: g.clipRect(start, g.getClipY(), end - start, g.getClipHeight());
064:
065: // IMPL_NOTE add clipping if last img piece is wider than we need
066: for (int x = start; x < end; x += imgWidth) {
067: // draw the top border
068: g.drawImage(imgTop, x, y1, Graphics.TOP | Graphics.LEFT);
069: // draw the bottom border
070: g.drawImage(imgBottom, x, y2, Graphics.TOP | Graphics.LEFT);
071: }
072: g.setClip(xClip, g.getClipY(), clipWidth, g.getClipHeight());
073: }
074:
075: /**
076: * Fill width from <code>start</code> to <code>end</code>
077: * with imgTop at <code>y1</code> coordinate and
078: * with imgBottom at <code>y2</code>coordinate.
079: *
080: * @param g The Graphics context to paint to
081: * @param imgLeft The left image.
082: * @param imgRight The right image.
083: * @param start start y co-ordinate of ImageItem
084: * @param end end y co-ordinate of ImageItem
085: * @param x1 x co-ordinate of Left ImageItem
086: * @param x2 x co-ordinate of Right ImageItem
087: */
088: public static void drawLeft_RightBorder(Graphics g, Image imgLeft,
089: Image imgRight, int start, int end, int x1, int x2) {
090:
091: // the assumption is that imgLeft and imgRight will have the
092: // same height
093: int imgHeight = imgLeft.getHeight();
094:
095: // save the clip, before clipping the height;
096: // we need to clip since the last imgLeft and imgRight images
097: // might go over the area that needs to be filled
098: int yClip = g.getClipY();
099: int clipHeight = g.getClipHeight();
100:
101: g.clipRect(g.getClipX(), start, g.getClipWidth(), end - start);
102:
103: // IMPL_NOTE add clipping if last img piece is taller than we need
104: for (int y = start; y < end; y += imgHeight) {
105: // draw the left border
106: g.drawImage(imgLeft, x1, y, Graphics.TOP | Graphics.LEFT);
107: // draw the right border
108: g.drawImage(imgRight, x2, y, Graphics.TOP | Graphics.LEFT);
109: }
110: g.setClip(g.getClipX(), yClip, g.getClipWidth(), clipHeight);
111: }
112:
113: /**
114: * Draws the button background of the size specified (x, y, w, h).
115: * Different background can be drawn when the ImageItem has and
116: * does not have focus.
117: * IMPL_NOTE: update params
118: * @param g The graphics context to be used for rendering button
119: * @param x The x coordinate of the button's background top left corner
120: * @param y The y coordinate of the button's background top left corner
121: * @param w The width of the button's background
122: * @param h The height of the button's background
123: * @param image Array of background images to render.
124: */
125: public static void draw9pcsBackground(Graphics g, int x, int y,
126: int w, int h, Image[] image) {
127: if (image == null || image.length != 9) {
128: return;
129: }
130: // The assumption is that only middle image can be null the
131: // rest are not null if this method is called
132: g.translate(x, y);
133:
134: // NOTE : If topMiddle is 1 pixel wide, this is fine, but if it is
135: // wider, the clip should be adjusted so that it does not overwrite
136: // the topRight
137:
138: // Top Border
139: int iW = image[1].getWidth();
140: g.drawImage(image[0], 0, 0, Graphics.LEFT | Graphics.TOP);
141: w -= image[2].getWidth();
142: for (int i = image[0].getWidth(); i < w; i += iW) {
143: g.drawImage(image[1], i, 0, Graphics.LEFT | Graphics.TOP);
144: }
145: w += image[2].getWidth();
146: g.drawImage(image[2], w, 0, Graphics.RIGHT | Graphics.TOP);
147:
148: // Tile middle rows
149: if (image[4] != null) {
150: iW = image[4].getWidth();
151: }
152: int iH = image[3].getHeight();
153: h -= image[6].getHeight();
154: w -= image[5].getWidth();
155: for (int i = image[0].getHeight(); i <= h; i += iH) {
156: g.drawImage(image[3], 0, i, Graphics.LEFT | Graphics.TOP);
157: for (int j = image[3].getWidth(); j <= w; j += iW) {
158: g.drawImage(image[4], j, i, Graphics.LEFT
159: | Graphics.TOP);
160: }
161: g.drawImage(image[5], w + image[5].getWidth(), i,
162: Graphics.RIGHT | Graphics.TOP);
163: }
164: w += image[5].getWidth();
165: h += image[6].getHeight();
166:
167: // Bottom border
168: iW = image[7].getWidth();
169: g.drawImage(image[6], 0, h, Graphics.LEFT | Graphics.BOTTOM);
170: w -= image[8].getWidth();
171: for (int i = image[6].getWidth(); i < w; i += iW) {
172: g
173: .drawImage(image[7], i, h, Graphics.LEFT
174: | Graphics.BOTTOM);
175: }
176: w += image[8].getWidth();
177: g.drawImage(image[8], w, h, Graphics.RIGHT | Graphics.BOTTOM);
178:
179: g.translate(-x, -y);
180: }
181:
182: /**
183: * Draws the button background of the size specified (x, y, w).
184: * Different background can be drawn when the ImageItem has and
185: * does not have focus.
186: * IMPL_NOTE: update params
187: * @param g The graphics context to be used for rendering button
188: * @param x The x coordinate of the button's background top left corner
189: * @param y The y coordinate of the button's background top left corner
190: * @param w The width of the button's background
191: * @param image Array of background images to render.
192: */
193:
194: public static void draw3pcsBackground(Graphics g, int x, int y,
195: int w, Image[] image) {
196: if (image == null || image.length != 3) {
197: return;
198: }
199: int iW = image[1].getWidth();
200: g.drawImage(image[0], x, y, Graphics.LEFT | Graphics.TOP);
201: w -= image[2].getWidth();
202: for (int i = image[0].getWidth() + x; i < w; i += iW) {
203: g.drawImage(image[1], i, y, Graphics.LEFT | Graphics.TOP);
204: }
205: w += image[2].getWidth();
206: g.drawImage(image[2], w, y, Graphics.RIGHT | Graphics.TOP);
207: }
208:
209: /**
210: * Draws a border of <code>borderWidth</code> at location
211: * <code>x, y</code> with dimensions <code>width, height</code>.
212: * The border is drawn with one color.
213: * IMPL_NOTE: update params
214: * @param g The graphics context to be used for rendering button
215: * @param x The x coordinate of the button's background top left corner
216: * @param y The y coordinate of the button's background top left corner
217: * @param w The width of the button's background
218: * @param h The height of the button's background
219: * @param borderWidth The width of the border line.
220: * @param borderColor The color for the border line.
221: */
222: public static void draw1ColorBorder(Graphics g, int x, int y,
223: int w, int h, int borderWidth, int borderColor) {
224: g.setColor(borderColor);
225:
226: w--;
227: h--;
228:
229: if (borderWidth == 1) {
230: g.drawRect(x, y, w, h);
231: return;
232: }
233:
234: g.translate(x, y);
235: for (int i = 0; i < borderWidth; i++, w -= 2, h -= 2) {
236: g.drawRect(i, i, w, h);
237: }
238: g.translate(-x, -y);
239: }
240:
241: /**
242: * Draws a border of <code>borderWidth</code> at location
243: * <code>x, y</code> with dimensions <code>width, height</code>.
244: * The border is drawn out of two colors.
245: * IMPL_NOTE: update params
246: * @param g The graphics context to be used for rendering button
247: * @param x The x coordinate of the button's background top left corner
248: * @param y The y coordinate of the button's background top left corner
249: * @param w The width of the button's background
250: * @param h The height of the button's background
251: * @param hasFocus The flag indicating the item has input focus.
252: * @param darkBorder The color of the dark border.
253: * @param lightBorder The color of the light border.
254: * @param borderWidth The wodth of the border line.
255: */
256: public static void draw2ColorBorder(Graphics g, int x, int y,
257: int w, int h, boolean hasFocus, int darkBorder,
258: int lightBorder, int borderWidth) {
259:
260: g.setColor(hasFocus ? darkBorder : lightBorder);
261:
262: g.fillRect(x, y, w, borderWidth);
263: g.fillRect(x, y, borderWidth, h);
264:
265: g.setColor(hasFocus ? lightBorder : darkBorder);
266:
267: g.fillTriangle(x, y + h, x + borderWidth, y + h - borderWidth,
268: x + borderWidth, y + h);
269:
270: g.fillRect(x + borderWidth, y + h - borderWidth, w
271: - borderWidth, borderWidth);
272:
273: g.fillTriangle(x + w, y, x + w - borderWidth, y + borderWidth,
274: x + w, y + borderWidth);
275:
276: g.fillRect(x + w - borderWidth, y + borderWidth, borderWidth, h
277: - borderWidth);
278:
279: }
280:
281: /**
282: * Paints the background according to image or color
283: * requested.
284: * @param g The graphics context to be used for rendering button.
285: * @param bgImage The background image to render or null.
286: * @param tileBG Flag to indicate the background image should be
287: * tiled.
288: * @param bgColor The background color to paint if bgImage is null.
289: * @param width The width of the background.
290: * @param height The height of the background.
291: */
292: public static void paintBackground(Graphics g, Image bgImage,
293: boolean tileBG, int bgColor, int width, int height) {
294: // return if a null graphics context
295: if (g == null) {
296: return;
297: }
298:
299: // We first try for a background image
300: if (bgImage != null) {
301: if (!tileBG) {
302: // Note: this way draws the entire background image and lets
303: // the Graphics object clip what it doesn't need. We use this
304: // method as the drawRegion routine has more overhead and
305: // should be slower.
306: g
307: .drawImage(bgImage, 0, 0, Graphics.TOP
308: | Graphics.LEFT);
309: } else {
310: // We'll re-use our bg* variables while we're in tile mode
311: int bgX = bgImage.getWidth();
312: int bgY = bgImage.getHeight();
313:
314: // Reduce the size of the two loops such that the tiling
315: // only covers the clip region
316: int clipX = g.getClipX();
317: int clipY = g.getClipY();
318: int leftX = (clipX / bgX) * bgX;
319: int leftY = (clipY / bgY) * bgY;
320: int rightX = clipX + g.getClipWidth();
321: int rightY = clipY + g.getClipHeight();
322:
323: for (int i = leftY; i < rightY; i += bgY) {
324: for (int j = leftX; j < rightX; j += bgX) {
325: g.drawImage(bgImage, j, i, Graphics.TOP
326: | Graphics.LEFT);
327: }
328: }
329: }
330: return;
331: }
332:
333: // If the background image is null, we use a fill color.
334: if (bgColor >= 0) {
335: int color = g.getColor();
336: g.setColor(bgColor);
337: // Optimization: Just fill the clip region
338: g.fillRect(g.getClipX(), g.getClipY(), g.getClipWidth(), g
339: .getClipHeight());
340: /*
341: if (borderWidth > 0 && borderColor >= 0) {
342: // IMPL_NOTE : there is a possible optimization whereby the clip is
343: // entirely inside the border and the border does not need to
344: // be painted at all.
345:
346: CGraphicsUtil.draw1ColorBorder(g, 0, 0, bounds[W], bounds[H],
347: borderWidth, borderColor);
348: }
349: */
350: // We reset to the cached color stored in paint()
351: g.setColor(color);
352: }
353:
354: }
355:
356: /**
357: * Draws a drop shadow box with a border of border of
358: * <code>borderColor</code>, a drop shadow of
359: * <code>shadowColor</code>, and a filled area of <code>color</code>
360: * at location <code>x, y</code> with dimensions
361: * <code>width, height</code>.
362: * IMPL_NOTE: update params
363: * @param g The graphics context to be used for rendering button
364: * @param x The x coordinate of the button's background top left corner
365: * @param y The y coordinate of the button's background top left corner
366: * @param w The width of the button's background
367: * @param h The height of the button's background
368: * @param borderColor The border color.
369: * @param shadowColor The shadow color.
370: * @param color The drawing color.
371: */
372: public static void drawDropShadowBox(Graphics g, int x, int y,
373: int w, int h, int borderColor, int shadowColor, int color) {
374: g.setColor(color);
375: w--;
376: h--;
377: g.fillRect(x, y, w, h);
378: g.setColor(shadowColor);
379: g.drawRect(x + 1, y + 1, w - 1, h - 1);
380: g.setColor(borderColor);
381: g.drawRect(x, y, w, h);
382: }
383: }
|