/* ******************************************************************************* * Copyright (C) 1997-2010, International Business Machines Corporation and * * others. All Rights Reserved. * ******************************************************************************* */ package com.ibm.icu.dev.demo.holiday; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Insets; import java.awt.Panel; /** * Various graphical borders. The border itself is a Panel so that it can * contain other Components (i.e. it borders something). You use the * HolidayBorderPanel like any other Panel: you set the layout that you prefer and * add Components to it. Beware that a null layout does not obey the insets * of the panel so if you use null layouts, adjust your measurements to * handle the border by calling insets(). * * @author Andy Clark, Taligent Inc. * @version 1.0 */ public class HolidayBorderPanel extends Panel { /** * For serialization */ private static final long serialVersionUID = 4669213306492461159L; // Constants /** Solid border. */ public final static int SOLID = 0; /** A raised border. */ public final static int RAISED = 1; /** A lowered border. */ public final static int LOWERED = 2; /** An etched in border. */ public final static int IN = 3; /** An etched out border. */ public final static int OUT = 4; /** Left alignment. */ public final static int LEFT = 0; /** Center alignment. */ public final static int CENTER = 1; /** Right alignment. */ public final static int RIGHT = 2; /** Default style (IN). */ public final static int DEFAULT_STYLE = IN; /** Default thickness (10). */ public final static int DEFAULT_THICKNESS = 10; /** Default thickness for solid borders (4). */ public final static int DEFAULT_SOLID_THICKNESS = 4; /** Default thickness for raised borders (2). */ public final static int DEFAULT_RAISED_THICKNESS = 2; /** Default thickness for lowered borders (2). */ public final static int DEFAULT_LOWERED_THICKNESS = 2; /** Default thickness for etched-in borders (10). */ public final static int DEFAULT_IN_THICKNESS = 10; /** Default thickness for etched-out borders (10). */ public final static int DEFAULT_OUT_THICKNESS = 10; /** Default gap between border and contained component (5). */ public final static int DEFAULT_GAP = 5; /** Default color (black). Applies to SOLID and etched borders. */ public final static Color DEFAULT_COLOR = Color.black; /** Default font (TimesRoman,PLAIN,14). Only applies to etched borders. */ public final static Font DEFAULT_FONT = new Font("TimesRoman", Font.PLAIN, 14); /** Default alignment (LEFT). Only applies to etched borders. */ public final static int DEFAULT_ALIGNMENT = LEFT; // Data private int style; private int thickness; private int gap; private Color color; private Font font; private String text; private int alignment; /** * Constructor. Makes default border. */ public HolidayBorderPanel() { // initialize data style = DEFAULT_STYLE; thickness = DEFAULT_THICKNESS; gap = DEFAULT_GAP; color = DEFAULT_COLOR; text = null; font = DEFAULT_FONT; alignment = DEFAULT_ALIGNMENT; } /** * Constructor. Makes an etched IN border with given text caption. * * @param text Text caption */ public HolidayBorderPanel(String text) { this(); style = IN; this.text = text; } /** * Constructor. Makes SOLID border with color and thickness given. * * @param color The color for the border. * @param thickness The thickness of the border. */ public HolidayBorderPanel(Color color, int thickness) { this(); style = SOLID; this.color = color; this.thickness = thickness; } /** * Constructor. Makes a border of the given style with the default * thickness for that style. * * @param style The style for this border. */ public HolidayBorderPanel(int style) { this(); // set thickness appropriate to this style switch (style) { case SOLID: thickness = DEFAULT_SOLID_THICKNESS; break; case RAISED: thickness = DEFAULT_RAISED_THICKNESS; break; case LOWERED: thickness = DEFAULT_LOWERED_THICKNESS; break; case IN: thickness = DEFAULT_IN_THICKNESS; break; case OUT: thickness = DEFAULT_OUT_THICKNESS; break; default: thickness = DEFAULT_THICKNESS; } this.style = style; } /** * Constructor. Makes border with given style and thickness. * * @param style The style for this border. * @param thickness The thickness for this border. */ public HolidayBorderPanel(int style, int thickness) { this(); this.style = style; this.thickness = thickness; } /** * Returns the insets of this panel.. */ public Insets getInsets() { int adjustment = 0; // adjust for text string if (style == IN || style == OUT) { if (text != null && text.length() > 0) { try { // set font and get info int height = getGraphics().getFontMetrics(font).getHeight(); if (height > thickness) adjustment = height - thickness; } catch (Exception e) { // nothing: just in case there is no graphics context // at the beginning. System.out.print(""); } } } // return appropriate insets int dist = thickness + gap; return new Insets(dist + adjustment, dist, dist, dist); } /** * Sets the style of the border * * @param style The new style. */ public HolidayBorderPanel setStyle(int style) { // set the style and re-layout the panel this.style = style; doLayout(); repaint(); return this; } /** * Gets the style of the border */ public int getStyle() { return style; } /** * Sets the thickness of the border. * * @param thickness The new thickness */ public HolidayBorderPanel setThickness(int thickness) { if (thickness > 0) { this.thickness = thickness; doLayout(); repaint(); } return this; } /** * Gets the thickness of the border. */ public int getThickness() { return thickness; } /** * Sets the gap between the border and the contained Component. * * @param gap The new gap, in pixels. */ public HolidayBorderPanel setGap(int gap) { if (gap > -1) { this.gap = gap; doLayout(); repaint(); } return this; } /** * Gets the gap between the border and the contained Component. */ public int getGap() { return gap; } /** * Sets the current color for SOLID borders and the caption text * color for etched borders. * * @param color The new color. */ public HolidayBorderPanel setColor(Color color) { this.color = color; if (style == SOLID || style == IN || style == OUT) repaint(); return this; } /** * Gets the current color for SOLID borders and the caption * text color for etched borders. */ public Color getColor() { return color; } /** * Sets the font. Only applies to etched borders. */ public HolidayBorderPanel setTextFont(Font font) { // set font if (font != null) { this.font = font; if (style == IN || style == OUT) { doLayout(); repaint(); } } return this; } /** * Gets the font of the text. Only applies to etched borders. */ public Font getTextFont() { return font; } /** * Sets the text. Only applies to etched borders. * * @param text The new text. */ public HolidayBorderPanel setText(String text) { this.text = text; if (style == IN || style == OUT) { doLayout(); repaint(); } return this; } /** * Gets the text. Only applies to etched borders. */ public String getText() { return text; } /** * Sets the text alignment. Only applies to etched borders. * * @param alignment The new alignment. */ public HolidayBorderPanel setAlignment(int alignment) { this.alignment = alignment; if (style == IN || style == OUT) { doLayout(); repaint(); } return this; } /** * Gets the text alignment. */ public int getAlignment() { return alignment; } /** * Repaints the border. * * @param g The graphics context. */ public void paint(Graphics g) { // get current dimensions Dimension size = getSize(); int width = size.width; int height = size.height; // set colors Color light = getBackground().brighter().brighter().brighter(); Color dark = getBackground().darker().darker().darker(); // Draw border switch (style) { case RAISED: // 3D Border (in or out) case LOWERED: Color topleft = null; Color bottomright = null; // set colors if (style == RAISED) { topleft = light; bottomright = dark; } else { topleft = dark; bottomright = light; } // draw border g.setColor(topleft); for (int i = 0; i < thickness; i++) { g.drawLine(i, i, width - i - 2, i); g.drawLine(i, i + 1, i, height - i - 1); } g.setColor(bottomright); for (int i = 0; i < thickness; i++) { g.drawLine(i + 1, height - i - 1, width - i - 1, height - i - 1); g.drawLine(width - i - 1, i, width - i - 1, height - i - 2); } break; case IN: // Etched Border (in or out) case OUT: int adjust1 = 0; int adjust2 = 0; // set font and get info Font oldfont = g.getFont(); g.setFont(font); FontMetrics fm = g.getFontMetrics(); int ascent = fm.getAscent(); // set adjustment if (style == IN) adjust1 = 1; else adjust2 = 1; // Calculate adjustment for text int adjustment = 0; if (text != null && text.length() > 0) { if (ascent > thickness) adjustment = (ascent - thickness) / 2; } // The adjustment is there so that we always draw the // light rectangle first. Otherwise, your eye picks up // the discrepancy where the light rect. passes over // the darker rect. int x = thickness / 2; int y = thickness / 2 + adjustment; int w = width - thickness - 1; int h = height - thickness - 1 - adjustment; // draw rectangles g.setColor(light); g.drawRect(x + adjust1, y + adjust1, w, h); g.setColor(dark); g.drawRect(x + adjust2, y + adjust2, w, h); // draw text, if applicable if (text != null && text.length() > 0) { // calculate drawing area int fontheight = fm.getHeight(); int strwidth = fm.stringWidth(text); int textwidth = width - 2 * (thickness + 5); if (strwidth > textwidth) strwidth = textwidth; // calculate offset for alignment int offset; switch (alignment) { case CENTER: offset = (width - strwidth) / 2; break; case RIGHT: offset = width - strwidth - thickness - 5; break; case LEFT: default: // assume left alignment if invalid offset = thickness + 5; break; } // clear drawing area and set clipping region g.clearRect(offset - 5, 0, strwidth + 10, fontheight); g.clipRect(offset, 0, strwidth, fontheight); // draw text g.setColor(color); g.drawString(text, offset, ascent); // restore old clipping area g.clipRect(0, 0, width, height); } g.setFont(oldfont); break; case SOLID: default: // assume SOLID g.setColor(color); for (int i = 0; i < thickness; i++) g.drawRect(i, i, width - 2 * i - 1, height - 2 * i - 1); } } /** * Returns the settings of this HolidayBorderPanel instance as a string. */ public String toString() { StringBuffer str = new StringBuffer("HolidayBorderPanel["); // style str.append("style="); switch (style) { case SOLID: str.append("SOLID"); break; case RAISED: str.append("RAISED"); break; case LOWERED: str.append("LOWERED"); break; case IN: str.append("IN"); break; case OUT: str.append("OUT"); break; default: str.append("unknown"); } str.append(","); // thickness str.append("thickness="); str.append(thickness); str.append(","); // gap str.append("gap="); str.append(gap); str.append(","); // color str.append(color); str.append(","); // font str.append(font); str.append(","); // text str.append("text="); str.append(text); str.append(","); // alignment str.append("alignment="); switch (alignment) { case LEFT: str.append("LEFT"); break; case CENTER: str.append("CENTER"); break; case RIGHT: str.append("RIGHT"); break; default: str.append("unknown"); } str.append("]"); return str.toString(); } }