2D Graphics GUI Java

/*
 * Copyright (c) Ian F. Darwin, http://www.darwinsys.com/, 1996-2002.
 * All rights reserved. Software written by Ian F. Darwin and others.
 * $Id: LICENSE,v 1.8 2004/02/09 03:33:38 ian Exp $
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * 
 * Java, the Duke mascot, and all variants of Sun's Java "steaming coffee
 * cup" logo are trademarks of Sun Microsystems. Sun's, and James Gosling's,
 * pioneering role in inventing and promulgating (and standardizing) the Java 
 * language and environment is gratefully acknowledged.
 * 
 * The pioneering role of Dennis Ritchie and Bjarne Stroustrup, of AT&T, for
 * inventing predecessor languages C and C++ is also gratefully acknowledged.
 */
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.text.DecimalFormat;
import java.util.Calendar;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
/**
 * Display one of those standard Calendar Page icons with Weekday, Day and
 * Month. Can be used as the Icon in a JButton. Can include or exclude an
 * updating Clock at the top (invoke constructor with value of true to include).
 * However, it should be excluded when using as an Icon, and true when using as
 * a Component.
 * 
 * @author Ian Darwin, http://www.darwinsys.com
 * @version $Id: CalIcon.java,v 1.3 2003/05/29 18:06:31 ian Exp $
 */
public class CalIcon extends JComponent implements Icon {
  /** The size shalle be 64x64. */
  protected final int SIZE = 64;
  protected final Dimension d = new Dimension(SIZE, SIZE);
  /** The size of the inner white box */
  protected final int RBW = 40, RBH = 40;
  /** The x location of the inner box */
  protected final int RBX;
  /** The y location of the inner box */
  protected final int RBY;
  /** Our Calendar */
  protected Calendar myCal;
  /** True if user wants the time shown */
  protected boolean showTime = true;
  /** The Clock to show the time, if showTime */
  protected Clock clock;
  /** Font for displaying the time */
  protected Font dayNumbFont;
  /** FontMetrics for displaying the time */
  protected FontMetrics dayNumbFM;
  /** Font for displaying the time */
  protected Font dayNameFont;
  /** FontMetrics for displaying the time */
  protected FontMetrics dayNameFM;
  /** Font for displaying the time */
  protected Font monNameFont;
  /** FontMetrics for displaying the time */
  protected FontMetrics monNameFM;
  /** Construct the object with default arguments */
  public CalIcon(boolean showT) {
    this(Calendar.getInstance(), showT);
  }
  /** Construct the object with a Calendar object */
  public CalIcon(Calendar c, boolean showT) {
    super();
    showTime = showT;
    myCal = c;
    setLayout(null); // we don't need another layout, ...
    if (showTime) {
      // System.err.println("Constructing and adding Clock");
      clock = new Clock();
      add(clock);
      clock.setBounds(0, 2, SIZE, 10);
      // clock.setBackground(Color.black);
      // clock.setForeground(Color.green);
      RBY = d.height - (RBH + (showTime ? 12 : 0) / 2);
    } else {
      RBY = 6;
    }
    RBX = 12; // raised box x offset
    // System.err.println("RBX, RBY = " + RBX + "," + RBY);
    dayNumbFont = new Font("Serif", Font.BOLD, 20);
    dayNumbFM = getFontMetrics(dayNumbFont);
    dayNameFont = new Font("SansSerif", Font.PLAIN, 10);
    dayNameFM = getFontMetrics(dayNameFont);
    monNameFont = new Font("SansSerif", Font.ITALIC, 10);
    monNameFM = getFontMetrics(monNameFont);
  }
  /** Days of the week */
  public String[] days = { "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT" };
  public String[] mons = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL",
      "AUG", "SEP", "OCT", "NOV", "DEC", };
  /**
   * Paint: draw the calendar page in the JComponent. Delegates most work to
   * paintIcon().
   */
  public void paint(Graphics g) {
    paintIcon(this, g, 0, 0);
  }
  /** paintIcon: draw the calendar page. */
  public void paintIcon(Component c, Graphics g, int x, int y) {
    // Allow clock to get painted (voodoo magic)
    if (showTime)
      super.paint(g);
    // Outline it.
    g.setColor(Color.black);
    g.draw3DRect(x, y, d.width - 2, d.height - 2, true);
    // Show the date: First, a white page with a drop shadow.
    g.setColor(Color.gray);
    g.fillRect(x + RBX + 3, y + RBY + 3, RBW, RBH);
    g.setColor(Color.white);
    g.fillRect(x + RBX, y + RBY, RBW, RBH);
    // g.setColor(getForeground());
    g.setColor(Color.black);
    String s = days[myCal.get(Calendar.DAY_OF_WEEK) - 1];
    g.setFont(dayNameFont);
    int w = dayNameFM.stringWidth(s);
    g.drawString(s, x + RBX + ((RBW - w) / 2), y + RBY + 10);
    s = Integer.toString(myCal.get(Calendar.DAY_OF_MONTH));
    g.setFont(dayNumbFont);
    w = dayNumbFM.stringWidth(s);
    g.drawString(s, x + RBX + ((RBW - w) / 2), y + RBY + 25);
    s = mons[myCal.get(Calendar.MONTH)];
    g.setFont(monNameFont);
    w = monNameFM.stringWidth(s);
    g.drawString(s, x + RBX + ((RBW - w) / 2), y + RBY + 35);
  }
  public int getIconWidth() {
    return SIZE;
  }
  public int getIconHeight() {
    return SIZE;
  }
  public Dimension getPreferredSize() {
    return d;
  }
  public Dimension getMinimumSize() {
    return d;
  }
  public static void main(String[] args) {
    JFrame jf = new JFrame("Calendar");
    Container cp = jf.getContentPane();
    cp.setLayout(new GridLayout(0, 1, 5, 5));
    CalIcon c = new CalIcon(true);
    cp.add(c);
    JButton j = new JButton("As Icon", new CalIcon(false));
    cp.add(j);
    jf.pack();
    jf.setVisible(true);
  }
}
class Clock extends javax.swing.JComponent {
  protected DecimalFormat tflz, tf;
  protected boolean done = false;
  public Clock() {
    new Thread(new Runnable() {
      public void run() {
        while (!done) {
          Clock.this.repaint();  // request a redraw
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e){ /* do nothing*/ }
        }
      }
    }).start();
    tf = new DecimalFormat("#0");
    tflz = new DecimalFormat("00");
  }
  public void stop() {
    done = true;
  }
 
  /* paint() - get current time and draw (centered) in Component. */ 
  public void paint(Graphics g) {
    Calendar myCal = Calendar.getInstance();
    StringBuffer sb = new StringBuffer();
    sb.append(tf.format(myCal.get(Calendar.HOUR)));
    sb.append(':');
    sb.append(tflz.format(myCal.get(Calendar.MINUTE)));
    sb.append(':');
    sb.append(tflz.format(myCal.get(Calendar.SECOND)));
    String s = sb.toString();
    FontMetrics fm = getFontMetrics(getFont());
    int x = (getSize().width - fm.stringWidth(s))/2;
    // System.out.println("Size is " + getSize());
    g.drawString(s, x, 10);
  }
  public Dimension getPreferredSize() {
    return new Dimension(100, 30);
  }
  public Dimension getMinimumSize() {
    return new Dimension(50, 10);
  }
}