001: /*
002: *******************************************************************************
003: * Copyright (C) 1997-2004, International Business Machines Corporation and *
004: * others. All Rights Reserved. *
005: *******************************************************************************
006: */
007: package com.ibm.icu.dev.demo.holiday;
008:
009: import java.awt.*;
010:
011: /**
012: * Various graphical borders. The border itself is a Panel so that it can
013: * contain other Components (i.e. it borders something). You use the
014: * HolidayBorderPanel like any other Panel: you set the layout that you prefer and
015: * add Components to it. Beware that a null layout does not obey the insets
016: * of the panel so if you use null layouts, adjust your measurements to
017: * handle the border by calling insets().
018: *
019: * @author Andy Clark, Taligent Inc.
020: * @version 1.0
021: */
022: public class HolidayBorderPanel extends Panel {
023: // Constants
024:
025: /** Solid border. */
026: public final static int SOLID = 0;
027: /** A raised border. */
028: public final static int RAISED = 1;
029: /** A lowered border. */
030: public final static int LOWERED = 2;
031: /** An etched in border. */
032: public final static int IN = 3;
033: /** An etched out border. */
034: public final static int OUT = 4;
035:
036: /** Left alignment. */
037: public final static int LEFT = 0;
038: /** Center alignment. */
039: public final static int CENTER = 1;
040: /** Right alignment. */
041: public final static int RIGHT = 2;
042:
043: /** Default style (IN). */
044: public final static int DEFAULT_STYLE = IN;
045: /** Default thickness (10). */
046: public final static int DEFAULT_THICKNESS = 10;
047: /** Default thickness for solid borders (4). */
048: public final static int DEFAULT_SOLID_THICKNESS = 4;
049: /** Default thickness for raised borders (2). */
050: public final static int DEFAULT_RAISED_THICKNESS = 2;
051: /** Default thickness for lowered borders (2). */
052: public final static int DEFAULT_LOWERED_THICKNESS = 2;
053: /** Default thickness for etched-in borders (10). */
054: public final static int DEFAULT_IN_THICKNESS = 10;
055: /** Default thickness for etched-out borders (10). */
056: public final static int DEFAULT_OUT_THICKNESS = 10;
057: /** Default gap between border and contained component (5). */
058: public final static int DEFAULT_GAP = 5;
059: /** Default color (black). Applies to SOLID and etched borders. */
060: public final static Color DEFAULT_COLOR = Color.black;
061:
062: /** Default font (TimesRoman,PLAIN,14). Only applies to etched borders. */
063: public final static Font DEFAULT_FONT = new Font("TimesRoman",
064: Font.PLAIN, 14);
065: /** Default alignment (LEFT). Only applies to etched borders. */
066: public final static int DEFAULT_ALIGNMENT = LEFT;
067:
068: // Data
069: private int style;
070: private int thickness;
071: private int gap;
072: private Color color;
073:
074: private Font font;
075: private String text;
076: private int alignment;
077:
078: /**
079: * Constructor. Makes default border.
080: */
081: public HolidayBorderPanel() {
082:
083: // initialize data
084: style = DEFAULT_STYLE;
085: thickness = DEFAULT_THICKNESS;
086: gap = DEFAULT_GAP;
087: color = DEFAULT_COLOR;
088:
089: text = null;
090: font = DEFAULT_FONT;
091: alignment = DEFAULT_ALIGNMENT;
092:
093: }
094:
095: /**
096: * Constructor. Makes an etched IN border with given text caption.
097: *
098: * @param text Text caption
099: */
100: public HolidayBorderPanel(String text) {
101: this ();
102:
103: style = IN;
104: this .text = text;
105: }
106:
107: /**
108: * Constructor. Makes SOLID border with color and thickness given.
109: *
110: * @param color The color for the border.
111: * @param thickness The thickness of the border.
112: */
113: public HolidayBorderPanel(Color color, int thickness) {
114: this ();
115:
116: style = SOLID;
117: this .color = color;
118: this .thickness = thickness;
119: }
120:
121: /**
122: * Constructor. Makes a border of the given style with the default
123: * thickness for that style.
124: *
125: * @param style The style for this border.
126: */
127: public HolidayBorderPanel(int style) {
128: this ();
129:
130: // set thickness appropriate to this style
131: int thickness;
132: switch (style) {
133: case SOLID:
134: thickness = DEFAULT_SOLID_THICKNESS;
135: break;
136: case RAISED:
137: thickness = DEFAULT_RAISED_THICKNESS;
138: break;
139: case LOWERED:
140: thickness = DEFAULT_LOWERED_THICKNESS;
141: break;
142: case IN:
143: thickness = DEFAULT_IN_THICKNESS;
144: break;
145: case OUT:
146: thickness = DEFAULT_OUT_THICKNESS;
147: break;
148: default:
149: thickness = DEFAULT_THICKNESS;
150: }
151:
152: this .style = style;
153: this .thickness = thickness;
154: }
155:
156: /**
157: * Constructor. Makes border with given style and thickness.
158: *
159: * @param style The style for this border.
160: * @param thickness The thickness for this border.
161: */
162: public HolidayBorderPanel(int style, int thickness) {
163: this ();
164:
165: this .style = style;
166: this .thickness = thickness;
167: }
168:
169: /**
170: * Returns the insets of this panel..
171: */
172: public Insets getInsets() {
173: int adjustment = 0;
174:
175: // adjust for text string
176: if (style == IN || style == OUT) {
177: if (text != null && text.length() > 0) {
178: try {
179: // set font and get info
180: int height = getGraphics().getFontMetrics(font)
181: .getHeight();
182: if (height > thickness)
183: adjustment = height - thickness;
184: } catch (Exception e) {
185: // nothing: just in case there is no graphics context
186: // at the beginning.
187: System.out.print("");
188: }
189: }
190: }
191:
192: // return appropriate insets
193: int dist = thickness + gap;
194: return new Insets(dist + adjustment, dist, dist, dist);
195: }
196:
197: /**
198: * Sets the style of the border
199: *
200: * @param style The new style.
201: */
202: public HolidayBorderPanel setStyle(int style) {
203:
204: // set the style and re-layout the panel
205: this .style = style;
206: doLayout();
207: repaint();
208:
209: return this ;
210: }
211:
212: /**
213: * Gets the style of the border
214: */
215: public int getStyle() {
216:
217: return style;
218: }
219:
220: /**
221: * Sets the thickness of the border.
222: *
223: * @param thickness The new thickness
224: */
225: public HolidayBorderPanel setThickness(int thickness) {
226:
227: if (thickness > 0) {
228: this .thickness = thickness;
229: doLayout();
230: repaint();
231: }
232:
233: return this ;
234: }
235:
236: /**
237: * Gets the thickness of the border.
238: */
239: public int getThickness() {
240:
241: return thickness;
242: }
243:
244: /**
245: * Sets the gap between the border and the contained Component.
246: *
247: * @param gap The new gap, in pixels.
248: */
249: public HolidayBorderPanel setGap(int gap) {
250:
251: if (gap > -1) {
252: this .gap = gap;
253: doLayout();
254: repaint();
255: }
256:
257: return this ;
258: }
259:
260: /**
261: * Gets the gap between the border and the contained Component.
262: */
263: public int getGap() {
264:
265: return gap;
266: }
267:
268: /**
269: * Sets the current color for SOLID borders and the caption text
270: * color for etched borders.
271: *
272: * @param color The new color.
273: */
274: public HolidayBorderPanel setColor(Color color) {
275:
276: this .color = color;
277: if (style == SOLID || style == IN || style == OUT)
278: repaint();
279:
280: return this ;
281: }
282:
283: /**
284: * Gets the current color for SOLID borders and the caption
285: * text color for etched borders.
286: */
287: public Color getColor() {
288:
289: return color;
290: }
291:
292: /**
293: * Sets the font. Only applies to etched borders.
294: */
295: public HolidayBorderPanel setTextFont(Font font) {
296:
297: // set font
298: if (font != null) {
299: this .font = font;
300: if (style == IN || style == OUT) {
301: doLayout();
302: repaint();
303: }
304: }
305:
306: return this ;
307: }
308:
309: /**
310: * Gets the font of the text. Only applies to etched borders.
311: */
312: public Font getTextFont() {
313:
314: return font;
315: }
316:
317: /**
318: * Sets the text. Only applies to etched borders.
319: *
320: * @param text The new text.
321: */
322: public HolidayBorderPanel setText(String text) {
323:
324: this .text = text;
325: if (style == IN || style == OUT) {
326: doLayout();
327: repaint();
328: }
329:
330: return this ;
331: }
332:
333: /**
334: * Gets the text. Only applies to etched borders.
335: */
336: public String getText() {
337:
338: return text;
339: }
340:
341: /**
342: * Sets the text alignment. Only applies to etched borders.
343: *
344: * @param alignment The new alignment.
345: */
346: public HolidayBorderPanel setAlignment(int alignment) {
347:
348: this .alignment = alignment;
349: if (style == IN || style == OUT) {
350: doLayout();
351: repaint();
352: }
353:
354: return this ;
355: }
356:
357: /**
358: * Gets the text alignment.
359: */
360: public int getAlignment() {
361:
362: return alignment;
363: }
364:
365: /**
366: * Repaints the border.
367: *
368: * @param g The graphics context.
369: */
370: public void paint(Graphics g) {
371:
372: // get current dimensions
373: Dimension size = getSize();
374: int width = size.width;
375: int height = size.height;
376:
377: // set colors
378: Color light = getBackground().brighter().brighter().brighter();
379: Color dark = getBackground().darker().darker().darker();
380:
381: // Draw border
382: switch (style) {
383: case RAISED: // 3D Border (in or out)
384: case LOWERED:
385: Color topleft = null;
386: Color bottomright = null;
387:
388: // set colors
389: if (style == RAISED) {
390: topleft = light;
391: bottomright = dark;
392: } else {
393: topleft = dark;
394: bottomright = light;
395: }
396:
397: // draw border
398: g.setColor(topleft);
399: for (int i = 0; i < thickness; i++) {
400: g.drawLine(i, i, width - i - 2, i);
401: g.drawLine(i, i + 1, i, height - i - 1);
402: }
403: g.setColor(bottomright);
404: for (int i = 0; i < thickness; i++) {
405: g.drawLine(i + 1, height - i - 1, width - i - 1, height
406: - i - 1);
407: g.drawLine(width - i - 1, i, width - i - 1, height - i
408: - 2);
409: }
410: break;
411:
412: case IN: // Etched Border (in or out)
413: case OUT:
414: int adjust1 = 0;
415: int adjust2 = 0;
416:
417: // set font and get info
418: Font oldfont = g.getFont();
419: g.setFont(font);
420: FontMetrics fm = g.getFontMetrics();
421: int ascent = fm.getAscent();
422:
423: // set adjustment
424: if (style == IN)
425: adjust1 = 1;
426: else
427: adjust2 = 1;
428:
429: // Calculate adjustment for text
430: int adjustment = 0;
431: if (text != null && text.length() > 0) {
432: if (ascent > thickness)
433: adjustment = (ascent - thickness) / 2;
434: }
435:
436: // The adjustment is there so that we always draw the
437: // light rectangle first. Otherwise, your eye picks up
438: // the discrepancy where the light rect. passes over
439: // the darker rect.
440: int x = thickness / 2;
441: int y = thickness / 2 + adjustment;
442: int w = width - thickness - 1;
443: int h = height - thickness - 1 - adjustment;
444:
445: // draw rectangles
446: g.setColor(light);
447: g.drawRect(x + adjust1, y + adjust1, w, h);
448: g.setColor(dark);
449: g.drawRect(x + adjust2, y + adjust2, w, h);
450:
451: // draw text, if applicable
452: if (text != null && text.length() > 0) {
453: // calculate drawing area
454: int fontheight = fm.getHeight();
455: int strwidth = fm.stringWidth(text);
456:
457: int textwidth = width - 2 * (thickness + 5);
458: if (strwidth > textwidth)
459: strwidth = textwidth;
460:
461: // calculate offset for alignment
462: int offset;
463: switch (alignment) {
464: case CENTER:
465: offset = (width - strwidth) / 2;
466: break;
467: case RIGHT:
468: offset = width - strwidth - thickness - 5;
469: break;
470: case LEFT:
471: default: // assume left alignment if invalid
472: offset = thickness + 5;
473: break;
474: }
475:
476: // clear drawing area and set clipping region
477: g.clearRect(offset - 5, 0, strwidth + 10, fontheight);
478: g.clipRect(offset, 0, strwidth, fontheight);
479:
480: // draw text
481: g.setColor(color);
482: g.drawString(text, offset, ascent);
483:
484: // restore old clipping area
485: g.clipRect(0, 0, width, height);
486: }
487:
488: g.setFont(oldfont);
489: break;
490:
491: case SOLID:
492: default: // assume SOLID
493: g.setColor(color);
494: for (int i = 0; i < thickness; i++)
495: g.drawRect(i, i, width - 2 * i - 1, height - 2 * i - 1);
496: }
497:
498: }
499:
500: /**
501: * Returns the settings of this HolidayBorderPanel instance as a string.
502: */
503: public String toString() {
504: StringBuffer str = new StringBuffer("HolidayBorderPanel[");
505:
506: // style
507: str.append("style=");
508: switch (style) {
509: case SOLID:
510: str.append("SOLID");
511: break;
512: case RAISED:
513: str.append("RAISED");
514: break;
515: case LOWERED:
516: str.append("LOWERED");
517: break;
518: case IN:
519: str.append("IN");
520: break;
521: case OUT:
522: str.append("OUT");
523: break;
524: default:
525: str.append("unknown");
526: }
527: str.append(",");
528:
529: // thickness
530: str.append("thickness=");
531: str.append(thickness);
532: str.append(",");
533:
534: // gap
535: str.append("gap=");
536: str.append(gap);
537: str.append(",");
538:
539: // color
540: str.append(color);
541: str.append(",");
542:
543: // font
544: str.append(font);
545: str.append(",");
546:
547: // text
548: str.append("text=");
549: str.append(text);
550: str.append(",");
551:
552: // alignment
553: str.append("alignment=");
554: switch (alignment) {
555: case LEFT:
556: str.append("LEFT");
557: break;
558: case CENTER:
559: str.append("CENTER");
560: break;
561: case RIGHT:
562: str.append("RIGHT");
563: break;
564: default:
565: str.append("unknown");
566: }
567:
568: str.append("]");
569:
570: return str.toString();
571: }
572:
573: }
|