• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /*
4  *******************************************************************************
5  * Copyright (C) 1997-2010, International Business Machines Corporation and    *
6  * others. All Rights Reserved.                                                *
7  *******************************************************************************
8  */
9 package com.ibm.icu.dev.demo.holiday;
10 
11 import java.awt.Color;
12 import java.awt.Dimension;
13 import java.awt.Font;
14 import java.awt.FontMetrics;
15 import java.awt.Graphics;
16 import java.awt.Insets;
17 import java.awt.Panel;
18 
19 /**
20  * Various graphical borders. The border itself is a Panel so that it can
21  * contain other Components (i.e. it borders something). You use the
22  * HolidayBorderPanel like any other Panel: you set the layout that you prefer and
23  * add Components to it. Beware that a null layout does not obey the insets
24  * of the panel so if you use null layouts, adjust your measurements to
25  * handle the border by calling insets().
26  *
27  * @author  Andy Clark, Taligent Inc.
28  * @version 1.0
29  */
30 public class HolidayBorderPanel extends Panel {
31     /**
32      * For serialization
33      */
34     private static final long serialVersionUID = 4669213306492461159L;
35     // Constants
36 
37     /** Solid border. */
38     public final static int SOLID = 0;
39     /** A raised border. */
40     public final static int RAISED = 1;
41     /** A lowered border. */
42     public final static int LOWERED = 2;
43     /** An etched in border. */
44     public final static int IN = 3;
45     /** An etched out border. */
46     public final static int OUT = 4;
47 
48     /** Left alignment. */
49     public final static int LEFT = 0;
50     /** Center alignment. */
51     public final static int CENTER = 1;
52     /** Right alignment. */
53     public final static int RIGHT = 2;
54 
55     /** Default style (IN). */
56     public final static int DEFAULT_STYLE = IN;
57     /** Default thickness (10). */
58     public final static int DEFAULT_THICKNESS = 10;
59     /** Default thickness for solid borders (4). */
60     public final static int DEFAULT_SOLID_THICKNESS = 4;
61     /** Default thickness for raised borders (2). */
62     public final static int DEFAULT_RAISED_THICKNESS = 2;
63     /** Default thickness for lowered borders (2). */
64     public final static int DEFAULT_LOWERED_THICKNESS = 2;
65     /** Default thickness for etched-in borders (10). */
66     public final static int DEFAULT_IN_THICKNESS = 10;
67     /** Default thickness for etched-out borders (10). */
68     public final static int DEFAULT_OUT_THICKNESS = 10;
69     /** Default gap between border and contained component (5). */
70     public final static int DEFAULT_GAP = 5;
71     /** Default color (black). Applies to SOLID and etched borders. */
72     public final static Color DEFAULT_COLOR = Color.black;
73 
74     /** Default font (TimesRoman,PLAIN,14). Only applies to etched borders. */
75     public final static Font DEFAULT_FONT = new Font("TimesRoman", Font.PLAIN, 14);
76     /** Default alignment (LEFT). Only applies to etched borders. */
77     public final static int DEFAULT_ALIGNMENT = LEFT;
78 
79     // Data
80     private int style;
81     private int thickness;
82     private int gap;
83     private Color color;
84 
85     private Font font;
86     private String text;
87     private int alignment;
88 
89     /**
90      * Constructor. Makes default border.
91      */
HolidayBorderPanel()92     public HolidayBorderPanel() {
93 
94         // initialize data
95         style       = DEFAULT_STYLE;
96         thickness   = DEFAULT_THICKNESS;
97         gap         = DEFAULT_GAP;
98         color       = DEFAULT_COLOR;
99 
100         text        = null;
101         font        = DEFAULT_FONT;
102         alignment   = DEFAULT_ALIGNMENT;
103 
104         }
105 
106     /**
107      * Constructor. Makes an etched IN border with given text caption.
108      *
109      * @param text  Text caption
110      */
HolidayBorderPanel(String text)111     public HolidayBorderPanel(String text) {
112         this();
113 
114         style = IN;
115         this.text = text;
116         }
117 
118     /**
119      * Constructor. Makes SOLID border with color and thickness given.
120      *
121      * @param color     The color for the border.
122      * @param thickness The thickness of the border.
123      */
HolidayBorderPanel(Color color, int thickness)124     public HolidayBorderPanel(Color color, int thickness) {
125         this();
126 
127         style = SOLID;
128         this.color = color;
129         this.thickness = thickness;
130         }
131 
132     /**
133      * Constructor. Makes a border of the given style with the default
134      * thickness for that style.
135      *
136      * @param style The style for this border.
137      */
HolidayBorderPanel(int style)138     public HolidayBorderPanel(int style) {
139         this();
140 
141         // set thickness appropriate to this style
142         switch (style) {
143             case SOLID: thickness = DEFAULT_SOLID_THICKNESS; break;
144             case RAISED: thickness = DEFAULT_RAISED_THICKNESS; break;
145             case LOWERED: thickness = DEFAULT_LOWERED_THICKNESS; break;
146             case IN: thickness = DEFAULT_IN_THICKNESS; break;
147             case OUT: thickness = DEFAULT_OUT_THICKNESS; break;
148             default:
149                 thickness = DEFAULT_THICKNESS;
150             }
151 
152         this.style = style;
153         }
154 
155     /**
156      * Constructor. Makes border with given style and thickness.
157      *
158      * @param style     The style for this border.
159      * @param thickness The thickness for this border.
160      */
HolidayBorderPanel(int style, int thickness)161     public HolidayBorderPanel(int style, int thickness) {
162         this();
163 
164         this.style = style;
165         this.thickness = thickness;
166         }
167 
168     /**
169      * Returns the insets of this panel..
170      */
getInsets()171     public Insets getInsets() {
172         int adjustment = 0;
173 
174         // adjust for text string
175         if (style == IN || style == OUT) {
176             if (text != null && text.length() > 0) {
177                 try {
178                     // set font and get info
179                     int height = getGraphics().getFontMetrics(font).getHeight();
180                     if (height > thickness)
181                         adjustment = height - thickness;
182                     }
183                 catch (Exception e) {
184                     // nothing: just in case there is no graphics context
185                     //   at the beginning.
186                     System.out.print("");
187                     }
188                 }
189             }
190 
191         // return appropriate insets
192         int dist = thickness + gap;
193         return new Insets(dist + adjustment, dist, dist, dist);
194         }
195 
196     /**
197      * Sets the style of the border
198      *
199      * @param style The new style.
200      */
setStyle(int style)201     public HolidayBorderPanel setStyle(int style) {
202 
203         // set the style and re-layout the panel
204         this.style = style;
205         doLayout();
206         repaint();
207 
208         return this;
209         }
210 
211     /**
212      * Gets the style of the border
213      */
getStyle()214     public int getStyle() {
215 
216         return style;
217         }
218 
219     /**
220      * Sets the thickness of the border.
221      *
222      * @param thickness The new thickness
223      */
setThickness(int thickness)224     public HolidayBorderPanel setThickness(int thickness) {
225 
226         if (thickness > 0) {
227             this.thickness = thickness;
228             doLayout();
229             repaint();
230             }
231 
232         return this;
233         }
234 
235     /**
236      * Gets the thickness of the border.
237      */
getThickness()238     public int getThickness() {
239 
240         return thickness;
241         }
242 
243     /**
244      * Sets the gap between the border and the contained Component.
245      *
246      * @param gap The new gap, in pixels.
247      */
setGap(int gap)248     public HolidayBorderPanel setGap(int gap) {
249 
250         if (gap > -1) {
251             this.gap = gap;
252             doLayout();
253             repaint();
254             }
255 
256         return this;
257         }
258 
259     /**
260      * Gets the gap between the border and the contained Component.
261      */
getGap()262     public int getGap() {
263 
264         return gap;
265         }
266 
267     /**
268      * Sets the current color for SOLID borders and the caption text
269      * color for etched borders.
270      *
271      * @param color The new color.
272      */
setColor(Color color)273     public HolidayBorderPanel setColor(Color color) {
274 
275         this.color = color;
276         if (style == SOLID || style == IN || style == OUT)
277             repaint();
278 
279         return this;
280         }
281 
282     /**
283      * Gets the current color for SOLID borders and the caption
284      * text color for etched borders.
285      */
getColor()286     public Color getColor() {
287 
288         return color;
289         }
290 
291     /**
292      * Sets the font. Only applies to etched borders.
293      */
setTextFont(Font font)294     public HolidayBorderPanel setTextFont(Font font) {
295 
296         // set font
297         if (font != null) {
298             this.font = font;
299             if (style == IN || style == OUT) {
300                 doLayout();
301                 repaint();
302                 }
303             }
304 
305         return this;
306         }
307 
308     /**
309      * Gets the font of the text. Only applies to etched borders.
310      */
getTextFont()311     public Font getTextFont() {
312 
313         return font;
314         }
315 
316     /**
317      * Sets the text. Only applies to etched borders.
318      *
319      * @param text  The new text.
320      */
setText(String text)321     public HolidayBorderPanel setText(String text) {
322 
323         this.text = text;
324         if (style == IN || style == OUT) {
325             doLayout();
326             repaint();
327             }
328 
329         return this;
330         }
331 
332     /**
333      * Gets the text. Only applies to etched borders.
334      */
getText()335     public String getText() {
336 
337         return text;
338         }
339 
340     /**
341      * Sets the text alignment. Only applies to etched borders.
342      *
343      * @param alignment The new alignment.
344      */
setAlignment(int alignment)345     public HolidayBorderPanel setAlignment(int alignment) {
346 
347         this.alignment = alignment;
348         if (style == IN || style == OUT) {
349             doLayout();
350             repaint();
351             }
352 
353         return this;
354         }
355 
356     /**
357      * Gets the text alignment.
358      */
getAlignment()359     public int getAlignment() {
360 
361         return alignment;
362         }
363 
364     /**
365      * Repaints the border.
366      *
367      * @param g The graphics context.
368      */
paint(Graphics g)369     public void paint(Graphics g) {
370 
371         // get current dimensions
372         Dimension size = getSize();
373         int width = size.width;
374         int height = size.height;
375 
376         // set colors
377         Color light = getBackground().brighter().brighter().brighter();
378         Color dark = getBackground().darker().darker().darker();
379 
380         // Draw border
381         switch (style) {
382             case RAISED:    // 3D Border (in or out)
383             case LOWERED:
384                 Color topleft = null;
385                 Color bottomright = null;
386 
387                 // set colors
388                 if (style == RAISED) {
389                     topleft = light;
390                     bottomright = dark;
391                     }
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 - i - 1);
406                     g.drawLine(width - i - 1, i, width - i - 1, height - i - 2);
407                     }
408                 break;
409 
410             case IN:    // Etched Border (in or out)
411             case OUT:
412                 int adjust1 = 0;
413                 int adjust2 = 0;
414 
415                 // set font and get info
416                 Font oldfont = g.getFont();
417                 g.setFont(font);
418                 FontMetrics fm = g.getFontMetrics();
419                 int ascent = fm.getAscent();
420 
421                 // set adjustment
422                 if (style == IN)
423                     adjust1 = 1;
424                 else
425                     adjust2 = 1;
426 
427                 // Calculate adjustment for text
428                 int adjustment = 0;
429                 if (text != null && text.length() > 0) {
430                     if (ascent > thickness)
431                         adjustment = (ascent - thickness) / 2;
432                     }
433 
434                 // The adjustment is there so that we always draw the
435                 // light rectangle first. Otherwise, your eye picks up
436                 // the discrepancy where the light rect. passes over
437                 // the darker rect.
438                 int x = thickness / 2;
439                 int y = thickness / 2 + adjustment;
440                 int w = width - thickness - 1;
441                 int h = height - thickness - 1 - adjustment;
442 
443                 // draw rectangles
444                 g.setColor(light);
445                 g.drawRect(x + adjust1, y + adjust1, w, h);
446                 g.setColor(dark);
447                 g.drawRect(x + adjust2, y + adjust2, w, h);
448 
449                 // draw text, if applicable
450                 if (text != null && text.length() > 0) {
451                     // calculate drawing area
452                     int fontheight = fm.getHeight();
453                     int strwidth = fm.stringWidth(text);
454 
455                     int textwidth = width - 2 * (thickness + 5);
456                     if (strwidth > textwidth)
457                         strwidth = textwidth;
458 
459                     // calculate offset for alignment
460                     int offset;
461                     switch (alignment) {
462                         case CENTER:
463                             offset = (width - strwidth) / 2;
464                             break;
465                         case RIGHT:
466                             offset = width - strwidth - thickness - 5;
467                             break;
468                         case LEFT:
469                         default: // assume left alignment if invalid
470                             offset = thickness + 5;
471                             break;
472                         }
473 
474                     // clear drawing area and set clipping region
475                     g.clearRect(offset - 5, 0, strwidth  + 10, fontheight);
476                     g.clipRect(offset, 0, strwidth, fontheight);
477 
478                     // draw text
479                     g.setColor(color);
480                     g.drawString(text, offset, ascent);
481 
482                     // restore old clipping area
483                     g.clipRect(0, 0, width, height);
484                     }
485 
486                 g.setFont(oldfont);
487                 break;
488 
489             case SOLID:
490             default: // assume SOLID
491                 g.setColor(color);
492                 for (int i = 0; i < thickness; i++)
493                     g.drawRect(i, i, width - 2 * i - 1, height - 2 * i - 1);
494             }
495 
496         }
497 
498     /**
499      * Returns the settings of this HolidayBorderPanel instance as a string.
500      */
toString()501     public String toString() {
502         StringBuffer str = new StringBuffer("HolidayBorderPanel[");
503 
504         // style
505         str.append("style=");
506         switch (style) {
507             case SOLID: str.append("SOLID"); break;
508             case RAISED: str.append("RAISED"); break;
509             case LOWERED: str.append("LOWERED"); break;
510             case IN: str.append("IN"); break;
511             case OUT: str.append("OUT"); break;
512             default: str.append("unknown");
513             }
514         str.append(",");
515 
516         // thickness
517         str.append("thickness=");
518         str.append(thickness);
519         str.append(",");
520 
521         // gap
522         str.append("gap=");
523         str.append(gap);
524         str.append(",");
525 
526         // color
527         str.append(color);
528         str.append(",");
529 
530         // font
531         str.append(font);
532         str.append(",");
533 
534         // text
535         str.append("text=");
536         str.append(text);
537         str.append(",");
538 
539         // alignment
540         str.append("alignment=");
541         switch (alignment) {
542             case LEFT: str.append("LEFT"); break;
543             case CENTER: str.append("CENTER"); break;
544             case RIGHT: str.append("RIGHT"); break;
545             default: str.append("unknown");
546             }
547 
548         str.append("]");
549 
550         return str.toString();
551         }
552 
553     }
554 
555