// ==========================================================================
// $Id: TimerClockPanel.java,v 1.7 2002/09/15 15:02:32 hitoshi Exp $
// Timer Clock panel
// ==========================================================================
// Copyright (C) 2002 Yamauchi, Hitoshi
//
//   Max-Planck-Institut fuer Informatik AG4
//   Stuhlsatzenhausweg 85, 66123 Saarbruecken
//   http://www.mpi-sb.mpg.de/
// 
// This software can be redistributed only under GNU copyleft.
//
// @author Yamauchi Hitoshi 山内 斉
// ==========================================================================
// $Revision: 1.7 $
// $Date: 2002/09/15 15:02:32 $
// $Author: hitoshi $
// ==========================================================================
package de.mpg.mpisb.timerclock;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;

public class TimerClockPanel extends JPanel 
{
  // 数字右余白空間 (means 
  // `the extra space size of the right side of digits'.
  // Sometimes I'm surprized that Chinese charactor is very good at
  // expressing this kind stuffs.)
  private final static double YOHAKU_FACTOR = 0.1;

  /**
   * constructor
   */
  public TimerClockPanel(int width, int height, Timer aTimer)
  {
    this.mPanelDim 	  = new Dimension();
    this.mPanelDim.width  = width;
    this.mPanelDim.height = height;
    this.mTimer 	  = aTimer;
    this.mTimeFormatter	  = new TimeFormatter();
    this.setSize(width, height);
    this.resetColor();
    this.updatePresentTime();    
  }

  /*
   * init font
   */
  private void updateFontInfo(String str, Dimension d)
  {
    this.mNumFont = new Font(this.mFontName, this.mFontStyle, this.mFontSize);
    Graphics g = this.getGraphics();
    FontMetrics fm = g.getFontMetrics(this.mNumFont);
    final int width  = fm.charsWidth(str.toCharArray(), 0, str.length());
    final int height = fm.getHeight();
    
    double mag_w = (double)(d.width)  / (double)width;
    double mag_h = (double)(d.height) / (double)height;
    double mag = (mag_w < mag_h) ? mag_w : mag_h; // 小さい方を選択する
    double newFontSize = 
      (double)(this.mFontSize) * mag * (1.0 - (2.0 * YOHAKU_FACTOR));

    // updates
    if((int)newFontSize <= 0)
    {
      // 一度 0 になると戻らなくなってしまう
      newFontSize = 1.0;
    }
    if(this.mFontSize  != (int)newFontSize)
    {
      this.mFontSize = (int)newFontSize;
      this.mNumFont = new Font(this.mFontName, this.mFontStyle, this.mFontSize);      
      g.setFont(this.mNumFont);
      Message.verboseOut("DEBUG: Font will be changed to " + this.mFontSize + "\n");

      FontMetrics newfm = g.getFontMetrics(this.mNumFont);
      final int newwidth  = newfm.charsWidth(str.toCharArray(), 0, str.length());
      final int newheight = newfm.getHeight();

      this.mNumX = (d.width  - newwidth)  / 2;
      this.mNumY = d.height - ((d.height - newheight) / 2);
    }
    else
    {
      Message.verboseOut("DEBUG: Font is not changed.\n");
    }     
    this.mIsShouldUpdateFontInfo = false;
  }

  /**
   * set font info
   */
  public void setFontInfo(String fontname, int fontstyle)
  {
    this.mFontName  = fontname;
    this.mFontStyle = fontstyle;
  }
  /**
   * get font name
   */
  public String getFontName()
  {
    return(this.mFontName);
  }
  /**
   * get font style
   */
  public int getFontStyle()
  {
    return(this.mFontStyle);
  }

  /*
   * call back draw
   */
  public void draw(Graphics g)
  {
    Dimension d = new Dimension();
    d.width 	= this.mPanelDim.width;
    d.height 	= this.mPanelDim.height;

    if(this.mIsShouldUpdateFontInfo)
    {
      this.updateFontInfo(this.mDataStr, d);
    }

    // if double buffer
    //     this.mGr.setColor(this.mBGColor);
    //     this.mGr.fillRect(0, 0, this.mPanelDim.width, this.mPanelDim.height);
    //     this.mGr.setColor(this.mFGColor);
    //     Dimension aread = this.getSize();
    //     this.mGr.setFont(new Font("TimesRoman", Font.BOLD, this.mFontSize));
    //     this.mGr.drawString(this.mDataStr, 0, this.mPanelDim.width / 5);
    // else
    g.setColor(this.mBGColor);
    g.fillRect(0, 0, this.mPanelDim.width, this.mPanelDim.height);
    g.setColor(this.mFGColor);
    // Dimension aread = this.getSize();
    g.setFont(this.mNumFont);
    g.drawString(this.mDataStr, this.mNumX, this.mNumY);
    // endif
  }
  /*
   * call back draw
   */
  public void paint(Graphics g)
  {
    try{
      draw(g);
      // if double buffer      
      // g.drawImage(this.mDoubleBuffer, 0, 0, this);
      // endif
    }
    catch(java.lang.NullPointerException e)
    {
      System.out.println(e);
    }
  }
  /*
   * call back update
   */
  public void update(Graphics g)
  {
    paint(g);
  }
  /*
   * call back focusGained
   */
  public void focusGained(FocusEvent e)
  {
    repaint();
  }
  /**
   * call back when the screen is resized.
   */
  public void doLayout()
  {
    // if double buffer
    //  Image img = this.mDoubleBuffer;
    //  this.mDoubleBuffer = createImage(this.mPanelDim.width, this.mPanelDim.height);
    //  if(this.mDoubleBuffer != null)
    //  {
    //    // this.mGr = this.mDoubleBuffer.getGraphics();
        //  }
    //  if(img != null)
    //  {
    //    this.mGr.drawImage(img, 0, 0, null);
    //  }
    // else
    this.mGr = this.getGraphics();
    //endif
    
    Dimension d           = this.getSize();
    this.updateFontInfo(this.mDataStr, d);
    this.mPanelDim.width  = d.width;
    this.mPanelDim.height = d.height;
    this.setSize(this.mPanelDim.width, this.mPanelDim.height);
  }

  /*============================================================
   * Setting 
   *===========================================================*/
  /**
   * set default foreground color 
   */
  public void setDefaultFGColor(Color fg)
  {
    this.mDefaultFGColor = new Color(fg.getRed(), fg.getGreen(), fg.getBlue());
    this.changeFGColor(this.mDefaultFGColor);
    this.repaint();
  }
  /**
   * change foreground color (temporary change)
   */
  public void changeFGColor(Color fg)
  {
    this.mFGColor = new Color(fg.getRed(), fg.getGreen(), fg.getBlue());
    this.repaint();
  }
  /**
   * set default background color 
   */
  public void setDefaultBGColor(Color bg)
  {
    this.mDefaultBGColor = new Color(bg.getRed(), bg.getGreen(), bg.getBlue());    
    this.changeBGColor(this.mDefaultBGColor);    
    this.repaint();
  }
  /**
   * change background color (temporary change)
   */
  public void changeBGColor(Color bg)
  {
    this.mBGColor = new Color(bg.getRed(), bg.getGreen(), bg.getBlue());    
    this.repaint();
  }
  /**
   * reset color 
   */
  public void resetColor()
  {
    this.changeFGColor(this.mDefaultFGColor);
    this.changeBGColor(this.mDefaultBGColor);
  }

  /**
   * acess to time formatter
   */
  public TimeFormatter peekTimeFormatter()
  {
    return(this.mTimeFormatter);
  }

  /*============================================================
   * timer control
   *===========================================================*/
  /**
   * update present time and strings
   * @return elapsed time (millisecond)
   */
  public long updatePresentTime()
  {
    int curstrlen = this.mDataStr.length();
    this.mDataStr = 
      this.mTimeFormatter.getFormattedString(this.mTimer.getCurrentDisplayTime());
    if(curstrlen != this.mDataStr.length())
    {
      this.mIsShouldUpdateFontInfo = true;
    }
    return(this.mTimer.getCurrentElapsedTime());
  }

  /**
   * start timer 
   */
  public void start()
  {
    this.mTimer.start();
  }
  /**
   * stop timer 
   */
  public void stop()
  {
    this.mTimer.stop();    
  }
  /**
   * reset timer 
   */
  public void reset()
  {
    this.mTimer.reset();        
    this.updatePresentTime();            
    this.repaint();            
  }

  /**
   * set timer period 
   */
  public void setPeriodTime(long periodmillisec)
  {
    this.mTimer.setPeriod(periodmillisec);            
  }
  /**
   * get timer period
   */
  public long getPeriodTime()
  {
    return(this.mTimer.getPeriod());            
  }

  // private variables
  private String 	mDataStr 	= "00";  
  private Timer 	mTimer		= null;
  private TimeFormatter	mTimeFormatter	= null;
  private int 		mFontSize 	= 36;
  private Image 	mDoubleBuffer 	= null;
  private Dimension 	mPanelDim	= null;
  private Color		mFGColor	= null;
  private Color		mBGColor	= null;
  private Font 	        mNumFont	= null;
  private Color         mDefaultFGColor = Color.black;
  private Color         mDefaultBGColor = Color.white;
  private Graphics 	mGr		= null;
  private int           mNumX        	= 10;
  private int           mNumY        	= 100;
  private boolean       mIsShouldUpdateFontInfo = true;
  private String        mFontName       = "TimesRoman";
  private int           mFontStyle      = Font.BOLD;

  /*
   * main for test
   */
  public static void main(String args[])
  {
    TimerClockPanel cdtp = new TimerClockPanel(500, 500, new TimerDowncount(12000));
    DisplayTime dt = new DisplayTime(cdtp);
    
    JFrame frame = new JFrame("Timer Clock Test");
    frame.addWindowListener(new WindowAdapter() {
	public void windowClosing(WindowEvent e) {System.exit(0);}
      });
    frame.getContentPane().add(cdtp, BorderLayout.CENTER);
    frame.setSize(500, 500);
    frame.pack();
    frame.setVisible(true);
    dt.start();
  }
}
