blob: cd81ef1fa74e9b7ba0e2a610803f3a172845f24b [file] [log] [blame]
/*
*******************************************************************************
* 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();
}
}