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