001: /*
002: * Javu WingS - Lightweight Java Component Set
003: * Copyright (c) 2005-2007 Krzysztof A. Sadlocha
004: * e-mail: ksadlocha@programics.com
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or (at your option) any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
019: */
020:
021: package com.javujavu.javux.wings;
022:
023: import java.awt.Color;
024: import java.awt.Component;
025: import java.awt.Container;
026: import java.awt.Dimension;
027: import java.awt.Font;
028: import java.awt.Graphics;
029: import java.awt.IllegalComponentStateException;
030: import java.awt.Image;
031: import java.awt.Insets;
032: import java.awt.Point;
033: import java.awt.Rectangle;
034: import java.awt.Toolkit;
035: import java.awt.Window;
036: import java.awt.image.ImageObserver;
037:
038: /**
039: * A collection of various utility methods used by WingS components.
040: * This class provides Java version dependent methods
041: * like mouse wheel, text antialiasing and so on.
042: * It checks Java version and initialize appropriate
043: * derived class eg <code>WingToolkit12</code> for Java 1.2
044: *
045: * <br>
046: * <b>This is one of the core WingS classes required by all the components</b><br>
047: * <br>
048: * <b>This class is thread safe.</b>
049: **/
050: public class WingToolkit {
051:
052: private static WingToolkit the;
053:
054: public static WingToolkit the() {
055: if (the == null) {
056: try {
057: String version = System
058: .getProperty("java.version", "0");
059: if (version.compareTo("1.4") >= 0) {
060: the = (WingToolkit) Class.forName(
061: "com.javujavu.javux.wings.WingToolkit14")
062: .newInstance();
063: } else if (version.compareTo("1.2") >= 0) {
064: the = (WingToolkit) Class.forName(
065: "com.javujavu.javux.wings.WingToolkit12")
066: .newInstance();
067: }
068: } catch (SecurityException e) {
069: } catch (ClassNotFoundException e) {
070: } catch (InstantiationException e) {
071: } catch (IllegalAccessException e) {
072: }
073:
074: if (the == null)
075: the = new WingToolkit();
076: }
077: return the;
078: }
079:
080: protected static final int BUFFER_REUSE = 8;
081: private int bufferUsed;
082: private Image buffer;
083:
084: protected Image getBuffer(Component c, int width, int height) {
085: if (buffer != null
086: && ((bufferUsed >= BUFFER_REUSE
087: && buffer.getWidth(null) != width && buffer
088: .getHeight(null) != height)
089: || buffer.getWidth(null) < width || buffer
090: .getHeight(null) < height)) {
091: buffer.flush();
092: buffer = null;
093: }
094: if (buffer == null) {
095: buffer = c.createImage(width, height);
096: bufferUsed = 0;
097: }
098: bufferUsed++;
099: return buffer;
100: }
101:
102: /**
103: * Paints component using double buffering
104: * @param comp component
105: * @param g graphics
106: */
107: public static void paintBuffered(Component comp, Graphics g) {
108: Rectangle clipBounds = g.getClipBounds();
109: Dimension compSize = comp.getSize();
110: Rectangle bufRect = new Rectangle(compSize);
111: if (clipBounds != null)
112: bufRect = bufRect.intersection(clipBounds);
113:
114: if (bufRect.isEmpty())
115: return;
116:
117: the().paintBuffered(comp, g, clipBounds, bufRect);
118: }
119:
120: protected synchronized void paintBuffered(Component comp,
121: Graphics g, Rectangle clipBounds, Rectangle bufRect) {
122: Image buf = null;
123: if (WingComponent.doubleBuffering) {
124: buf = getBuffer(comp, bufRect.width, bufRect.height);
125: }
126: paintBuffered(comp, g, clipBounds, bufRect, buf);
127: }
128:
129: protected void paintBuffered(Component comp, Graphics g,
130: Rectangle clipBounds, Rectangle bufRect, Image buf) {
131: Graphics g2 = null;
132: if (buf != null) {
133: Graphics g3 = buf.getGraphics();
134: if (g3 != null) {
135: g2 = g3.create();
136: g3.dispose();
137: g2.translate(-bufRect.x, -bufRect.y);
138: }
139: }
140: if (g2 == null) {
141: buf = null;
142: g2 = g.create();
143: }
144: g2.setClip(clipBounds);
145:
146: g2.setColor(comp.getForeground());
147: g2.setFont(comp.getFont());
148:
149: if (comp instanceof WingComponent)
150: ((WingComponent) comp).paintComponent(g2);
151: else
152: comp.paint(g2);
153:
154: if (buf != null) {
155: g.drawImage(buf, bufRect.x, bufRect.y, bufRect.x
156: + bufRect.width, bufRect.y + bufRect.height, 0, 0,
157: bufRect.width, bufRect.height, null);
158:
159: }
160: g2.dispose();
161: }
162:
163: /**
164: * Paints container childs
165: * @param parent container
166: * @param g graphics
167: */
168: public static void paintContainer(Container parent, Graphics g) {
169: int count = parent.getComponentCount();
170: if (count == 0)
171: return;
172:
173: Rectangle parentClip = g.getClipBounds(), cBounds, cClip;
174: Graphics gc;
175: Component c;
176: for (int i = count - 1; i >= 0; i--) {
177: c = parent.getComponent(i);
178: cClip = cBounds = c.getBounds();
179: if (c.isVisible()
180: && (parentClip == null || parentClip
181: .intersects(cBounds))) {
182: if (parentClip != null) {
183: cClip = cClip.intersection(parentClip);
184: }
185: gc = g.create();
186: gc.setClip(cClip);
187:
188: gc.translate(cBounds.x, cBounds.y);
189:
190: gc.setColor(c.getForeground());
191: gc.setFont(c.getFont());
192:
193: if (c instanceof WingComponent)
194: ((WingComponent) c).paintComponent(gc);
195: else
196: c.paint(gc);
197:
198: gc.dispose();
199: }
200: }
201: }
202:
203: public boolean drawSmoothImage(Graphics g, WingImage image, int x,
204: int y, int w, int h, ImageObserver o) {
205: return g.drawImage(image.image, x, y, x + w, y + h,
206: image.src.x, image.src.y,
207: image.src.x + image.src.width, image.src.y
208: + image.src.height, o);
209: }
210:
211: protected void addWheelListener(final WingComponent src,
212: final WingComponent target) {
213: }
214:
215: public void addHierarchyListener(final WingComponent c) {
216: }
217:
218: private static int lineWidth(WingFont font, String text) {
219: int w = 0, i, j, len = text.length();
220: for (i = 0; i < len; i = j + 2) {
221: j = text.indexOf(WingConst.UNDERLINE_CHAR, i);
222: if (j == -1) {
223: w += font.stringWidth(text.substring(i));
224: break;
225: }
226: if (j > i)
227: w += font.stringWidth(text.substring(i, j));
228: if (j + 1 < len)
229: w += font.stringWidth(text.substring(j + 1, j + 2));
230: }
231: return w;
232: }
233:
234: public static void drawLabel(Graphics g, int x, int y, int width,
235: int height, WingImage imgIcon, String text, WingFont font,
236: Color color, Color focus, Insets margin, int gap,
237: int alignment, int textPosition, WingComponent c) {
238: Font font2 = font.getFont();
239: x += margin.left;
240: y += margin.top;
241: width -= margin.left + margin.right;
242: height -= margin.top + margin.bottom;
243:
244: // debug code
245: // g.setColor(Color.gray);
246: // g.fillRect(x, y, width, height);
247:
248: int textHeight = 0, labelWidth = 0, lineHeight = 0, ascent = 0;
249: if (text != null && font2 != null) {
250: ascent = font.getAscent();
251: lineHeight = ascent + font.getDescent();
252: int i, j, w, textWidth = 0;
253: for (i = 0; i < text.length(); i = j + 1) {
254: j = text.indexOf('\n', i);
255: if (j == -1)
256: j = text.length();
257: w = lineWidth(font, text.substring(i, j));
258: if (w > textWidth)
259: textWidth = w;
260: textHeight += lineHeight;
261: }
262: labelWidth += textWidth;
263: }
264: if (imgIcon != null) {
265: if (text != null)
266: labelWidth += gap;
267: labelWidth += imgIcon.getWidth();
268: }
269: if (alignment == WingComponent.CENTER)
270: x += (width - labelWidth) / 2;
271: if (alignment == WingComponent.RIGHT)
272: x += (width - labelWidth);
273: width = labelWidth;
274:
275: if (imgIcon != null) {
276: width -= imgIcon.getWidth();
277: int iconY = y + (height - imgIcon.getHeight()) / 2;
278: int iconX = x;
279: if (textPosition == WingComponent.LEFT)
280: iconX += width;
281: else
282: x += imgIcon.getWidth() + gap;
283: if (text != null)
284: width -= gap;
285:
286: // debug code
287: // g.setColor(Color.orange);
288: // g.fillRect(iconX,iconY,imgIcon.getWidth(), imgIcon.getHeight());
289:
290: imgIcon.drawImage(g, iconX, iconY, c);
291: }
292: if (text != null && font2 != null) {
293: y += (height - textHeight) / 2;
294: int lineX, lineY = y + ascent;
295:
296: // debug code
297: // g.setColor(Color.white);
298: // g.fillRect(x, y, width, textHeight);
299:
300: g.setColor(color);
301: g.setFont(font2);
302: for (int i = 0, j; i < text.length(); i = j + 1) {
303: j = text.indexOf('\n', i);
304: if (j == -1)
305: j = text.length();
306: String s = text.substring(i, j);
307: int lineWidth = lineWidth(font, s);
308: lineX = x;
309: if (alignment == WingConst.CENTER)
310: lineX += (width - lineWidth) / 2;
311: if (alignment == WingConst.RIGHT)
312: lineX += (width - lineWidth);
313: {
314: int fx, fi, fj, fw, len = s.length();
315: String fs;
316: fx = lineX;
317: for (fi = 0; fi < len; fi = fj + 2) {
318: fj = s.indexOf(WingConst.UNDERLINE_CHAR, fi);
319: if (fj == -1) {
320: font.drawString(g, s.substring(fi), fx,
321: lineY);
322: break;
323: }
324: if (fj > fi) {
325: fs = s.substring(fi, fj);
326: font.drawString(g, fs, fx, lineY);
327: fx += font.stringWidth(fs);
328: }
329: if (fj + 1 < len) {
330: fs = s.substring(fj + 1, fj + 2);
331: font.drawString(g, fs, fx, lineY);
332: fw = font.stringWidth(fs);
333: // g.setColor(Color.red);
334: g.drawLine(fx, lineY + 1, fx + fw,
335: lineY + 1);
336: // g.setColor(color);
337: fx += fw;
338: }
339: }
340: }
341: lineY += lineHeight;
342: }
343: if (focus != null) {
344: g.setColor(focus);
345: g.drawRoundRect(x - 1, y - 1, width + 1,
346: textHeight + 1, 2, 2);
347: }
348: }
349: }
350:
351: public static Dimension calcLabelSize(WingImage imgIcon,
352: String text, WingFont font, Insets margin, int gap,
353: WingComponent c) {
354: Dimension d = new Dimension();
355: d.width = margin.left + margin.right;
356: d.height = 0;
357: if (text != null && font != null) {
358: int textWidth = 0, lineHeight = font.getAscent()
359: + font.getDescent();
360: for (int i = 0, j; i < text.length(); i = j + 1) {
361: j = text.indexOf('\n', i);
362: if (j == -1)
363: j = text.length();
364: int w = lineWidth(font, text.substring(i, j));
365: if (w > textWidth)
366: textWidth = w;
367: d.height += lineHeight;
368: }
369: d.width += textWidth;
370: }
371: if (imgIcon != null) {
372: if (text != null)
373: d.width += gap;
374: int h = imgIcon.getHeight();
375: int w = imgIcon.getWidth();
376: if (h > d.height)
377: d.height = h;
378: d.width += w;
379: }
380: d.height += margin.top + margin.bottom;
381: return d;
382: }
383:
384: public static void drawBackground(Graphics g, int x, int y,
385: int width, int height, Style style, Component c) {
386: if (style.background != null) {
387: g.setColor(style.background);
388: g.fillRect(x, y, width, height);
389: }
390: if (style.image != null) {
391: style.image.drawImage(g, x, y, width, height, c);
392: }
393: if (style.border != null) {
394: g.setColor(style.border);
395: g.drawRect(x, y, width - 1, height - 1);
396: }
397: }
398:
399: public static void intersection(Rectangle dest, Rectangle with) {
400: int xo = dest.x;
401: int yo = dest.y;
402: int xe = dest.x + dest.width;
403: int ye = dest.y + dest.height;
404: int xo2 = with.x;
405: int yo2 = with.y;
406: int xe2 = with.x + with.width;
407: int ye2 = with.y + with.height;
408: if (xo2 > xo)
409: xo = xo2;
410: if (yo2 > yo)
411: yo = yo2;
412: if (xe2 < xe)
413: xe = xe2;
414: if (ye2 < ye)
415: ye = ye2;
416: dest.setBounds(xo, yo, xe - xo, ye - yo);
417: }
418:
419: /**
420: * @param origin any component
421: * @param pivotX
422: * @param pivotY
423: * @param pivotWidth
424: * @param pivotHeight
425: * @param direction
426: * @param minWidth
427: * @param minHeight
428: * @param content component
429: * @param minLightweightSize
430: * @param enableLightweight
431: * @param enableHeavyweight
432: * @param forceLightweight
433: * @param focusableWindow
434: * @return instance of <code>Window</code> for heavy popup,
435: * instance of <code>WingComponent</code> for light, or <code>null</code>
436: */
437: public static Container showPopup(WingComponent origin, int pivotX,
438: int pivotY, int pivotWidth, int pivotHeight, int direction,
439: int minWidth, int minHeight, WingComponent content,
440: Dimension minLightweightSize, boolean enableLightweight,
441: boolean enableHeavyweight, boolean forceLightweight,
442: boolean focusableWindow) {
443: Container handle = null;
444: Window w = null;
445: int left = 0, right = 0, top = 0, bottom = 0;
446: Dimension screenSize = Toolkit.getDefaultToolkit()
447: .getScreenSize();
448: Dimension size = null;
449:
450: Point originPos;
451: try {
452: originPos = origin.getLocationOnScreen();
453: } catch (IllegalComponentStateException e2) {
454: return null;
455: }
456:
457: int originX = 0, originY = 0;
458: if (enableLightweight) {
459: WingRootPane root = origin.getRootPane();
460: Point rootPos = null;
461: if (root != null) {
462: try {
463: rootPos = root.getLocationOnScreen();
464: } catch (IllegalComponentStateException e2) {
465: root = null;
466: }
467: }
468: if (root != null) {
469: originX = originPos.x + pivotX;
470: originY = originPos.y + pivotY;
471: // forces content.addNotify before getPreferredSize
472: root.addPopup(content);
473: int prefWidth, prefHeight;
474: size = content.getPreferredSize();
475: prefWidth = size.width;
476: prefHeight = size.height;
477: if (minWidth > prefWidth)
478: prefWidth = minWidth;
479: if (minHeight > prefHeight)
480: prefHeight = minHeight;
481: if (minLightweightSize != null) {
482: if (minLightweightSize.width < prefWidth)
483: prefWidth = minLightweightSize.width;
484: if (minLightweightSize.height < prefHeight)
485: prefHeight = minLightweightSize.height;
486: }
487: Dimension rootSize = root.getSize();
488:
489: int scrX0 = rootPos.x, scrY0 = rootPos.y, scrXE = scrX0
490: + rootSize.width, scrYE = scrY0
491: + rootSize.height;
492: if (scrX0 < 0)
493: scrX0 = 0;
494: if (scrY0 < 0)
495: scrY0 = 0;
496: if (scrXE > screenSize.width)
497: scrXE = screenSize.width;
498: if (scrYE > screenSize.height)
499: scrYE = screenSize.height;
500:
501: int rootWidth = scrXE - scrX0, rootHeight = scrYE
502: - scrY0;
503: if (originX < scrX0) {
504: pivotWidth -= scrX0 - originX;
505: if (pivotWidth < 0)
506: pivotWidth = 0;
507: originX = scrX0;
508: }
509: left = originX - scrX0;
510: originX -= rootPos.x;
511:
512: if (originY < scrY0) {
513: pivotHeight -= scrY0 - originY;
514: if (pivotHeight < 0)
515: pivotHeight = 0;
516: originY = scrY0;
517: }
518: top = originY - scrY0;
519: originY -= rootPos.y;
520:
521: right = rootWidth - left - pivotWidth;
522: bottom = rootHeight - top - pivotHeight;
523:
524: if (forceLightweight
525: || (direction == WingConst.HORIZONTAL
526: && rootWidth >= prefWidth && (top >= prefHeight || bottom >= prefHeight))
527: || (direction == WingConst.VERTICAL
528: && rootHeight >= prefHeight && (left >= prefWidth || right >= prefWidth))) {
529: handle = content;
530: } else
531: root.remove(content);
532: }
533: }
534: if (handle == null && enableHeavyweight) {
535: originX = originPos.x + pivotX;
536: originY = originPos.y + pivotY;
537: if (originX < 0) {
538: pivotWidth -= -originX;
539: if (pivotWidth < 0)
540: pivotWidth = 0;
541: originX = 0;
542: }
543: if (originY < 0) {
544: pivotHeight -= -originY;
545: if (pivotHeight < 0)
546: pivotHeight = 0;
547: originY = 0;
548: }
549: if (originX > screenSize.width)
550: originX = screenSize.width;
551: if (originY > screenSize.height)
552: originY = screenSize.height;
553:
554: left = originX;
555: top = originY;
556: right = screenSize.width - left - pivotWidth;
557: bottom = screenSize.height - top - pivotHeight;
558:
559: w = the().createPopup(origin, content, focusableWindow);
560: if (w == null)
561: return null;
562: w.pack();
563: content.setSize(0, 0);
564: size = w.getPreferredSize();
565: handle = w;
566: }
567:
568: if (handle != null) {
569:
570: for (int f = 0; f < 2; f++) {
571: int x = 0, y = 0, width = size.width, height = size.height;
572: if (minWidth > width)
573: width = minWidth;
574: if (minHeight > height)
575: height = minHeight;
576:
577: if (direction == WingConst.HORIZONTAL) {
578: if (bottom < height && bottom < top) {
579: if (height > top)
580: height = top;
581: y = originY - height;
582: } else {
583: if (height > bottom)
584: height = bottom;
585: y = originY + pivotHeight;
586: }
587:
588: if (width > left + pivotWidth + right)
589: width = left + pivotWidth + right;
590:
591: x = originX;
592: if (pivotWidth + right < width)
593: x -= (width - pivotWidth - right);
594: } else {
595: if (right < width && right < left) {
596: if (width > left)
597: width = left;
598: x = originX - width;
599: } else {
600: if (width > right)
601: width = right;
602: x = originX + pivotWidth;
603: }
604:
605: if (height > top + pivotHeight + bottom)
606: height = top + pivotHeight + bottom;
607:
608: y = originY;
609: if (pivotHeight + bottom < height)
610: y -= (height - pivotHeight - bottom);
611: }
612: handle.setBounds(x, y, width, height);
613: handle.validate();
614: Dimension size2 = (w != null) ? w.getPreferredSize()
615: : content.getPreferredSize();
616: if (size2.equals(size))
617: break;
618: size = size2;
619: }
620:
621: handle.setVisible(true);
622: content.revalidateAndRepaint();
623: content.repaint();
624: }
625: return handle;
626: }
627:
628: public static void hidePopup(Container handle) {
629: if (handle instanceof Window) {
630: handle.setVisible(false);
631: ((Window) handle).dispose();
632: } else if (handle != null) {
633: WingRootPane rp = ((WingComponent) handle).getRootPane();
634: if (rp != null)
635: rp.removePopup((WingComponent) handle);
636: }
637: }
638:
639: protected Window createPopup(WingComponent origin,
640: WingComponent content, boolean focusableWindow) {
641: WingWindow w = new WingWindow(origin.getParentFrame());
642: w.getRootPane().setStyleId("popup");
643: w.setContentPane(content);
644: return w;
645: }
646:
647: public Color createColor(int argb) {
648: return new Color(argb & 0x00ffffff);
649: }
650:
651: public void setTextAntialias(Graphics g, boolean antialias) {
652: }
653:
654: protected Object mulComposite(Graphics g, int alpha) {
655: return null;
656: }
657:
658: protected void clrComposite(Graphics g, Object composite) {
659: }
660:
661: public void requestFocusInWindow(Container c) {
662: c.requestFocus();
663: }
664:
665: public int stringWidth(WingFont font, String s) {
666: return font.metrics().stringWidth(s);
667: }
668:
669: public int charsWidth(WingFont font, char[] data, int offset,
670: int length) {
671: return font.metrics().charsWidth(data, offset, length);
672: }
673:
674: }
|