/* scribbler.java   last mod 05 FEB 2012 by Ed James */

import java.awt.*;
import java.awt.event.*;
import java.awt.Graphics;
import javax.swing.JFrame;    // for JFrame, main GUI component
import javax.swing.JToolBar;  // toolbar/buttonbar for these buttons:
import javax.swing.JButton;   // for the GUI buttons.

class scribblerFrame extends JFrame implements ActionListener {
   public static final long serialVersionUID = 375L; // Not currently used.

   BorderLayout myBorderLayout = new BorderLayout();

   JToolBar myToolBar;      // a "Button Bar"
   JButton myClearButton;   // clear the canvas
   JButton myHelpButton;    // displays instructions

   scribblerCanvas myCanvas;

   public scribblerFrame () {
      super ();

      setTitle ("scribbler");
      setSize (400,400);   // first approximation for size

      setVisible (true);
      }

   void buildGUI () {
      myBorderLayout = new BorderLayout ();
      setLayout (myBorderLayout);

      myToolBar = new JToolBar();   // Toolbar - build and install

      myClearButton = new JButton ("Clear Drawing Area");
      myClearButton.addActionListener (this);

      myHelpButton = new JButton ("Help");
      myHelpButton.addActionListener (this);

      myToolBar.add (myClearButton);
      myToolBar.add (myHelpButton);

      add ("North", myToolBar);

      myCanvas = new scribblerCanvas(); // Canvas - build and install
      add ("Center", myCanvas);
      }

   void addWindowListener () {
      try {
         addWindowListener (new WindowAdapter() {
            public void windowClosing (WindowEvent myEvent) {
           // maybe call destroy() here?
               System.exit (0);
               }
            });
         }
      catch (java.security.AccessControlException ACE2) {
         System.out.println("Error 2: " + ACE2.getMessage());
         }
      }

   public void actionPerformed (ActionEvent AE) {
      if (AE.getSource() == myClearButton ) {
         myCanvas.clearScreen();
         myCanvas.resetData ();
         }
      else if (AE.getSource() == myHelpButton) {
         myCanvas.clearScreen ();
         myCanvas.resetData ();
         myCanvas.displayHelp ();
         }
      }

   void addHierarchyBoundsListener () {
// This handles changes to main window location and size
      getContentPane().addHierarchyBoundsListener (new HierarchyBoundsListener () {
         @Override
         public void ancestorMoved (HierarchyEvent HE1) {
			
            }
         @Override
         public void ancestorResized (HierarchyEvent HE2) {
            myCanvas.makeImage ();   // kludge - what about old image?
            }
         });
      }
   }  //===== end of class scribblerFrame


class scribblerCanvas extends Canvas implements MouseListener, MouseMotionListener {
   public static final long serialVersionUID = 449L; // not currently used
   int canvasWidth;
   int canvasHeight;

   Image myImage;
   Graphics myGraphics;

   Point dot[] = new Point[1000]; // for captured mouse droppings
   int box[] = new int[1000];
   int dots = 0;                  // count of mouse droppings
   int minX = 0;                  // "box" that "captures" all mouse droppings
   int minY = 0;
   int maxX = 0;
   int maxY = 0;

   boolean mouseUp = false;

   String myDisplayString = "";

   scribblerCanvas () {
      addMouseListener (this);
      addMouseMotionListener (this);
      }

//===== These overrides are needed to implement MouseListener:
   public void mouseEntered  (MouseEvent ME) { }
   public void mouseExited   (MouseEvent ME) { }
   public void mouseClicked(MouseEvent e) {}

   public void mousePressed (MouseEvent ME) {
      dot[0] = new Point(ME.getX(), ME.getY());
      dots = 1;
      mouseUp = false;
      }

   public void mouseReleased (MouseEvent ME) {
      dot[dots] = new Point(ME.getX(), ME.getY());
      mouseUp = true;
      if (dots < 3)
         return;

      String newLetter = computeLetter();
      myDisplayString += newLetter;
      clearScreen ();
      repaint();
      }

   String computeLetter () {
      String myLetter = "?";
      if (dots < 0)
      return "?";

      minX = dot[0].x;
      minY = dot[0].y;
      maxX = minX;
      maxY = minY;

      for (int i = 1 ; i < dots-1 ; i++) {
         if (dot[i].x < minX) minX = dot[i].x;
         if (dot[i].y < minY) minY = dot[i].y;
         if (dot[i].x > maxX) maxX = dot[i].x;
         if (dot[i].y > maxY) maxY = dot[i].y;
         }

      int width  = maxX - minX;
      int height = maxY - minY;
      if (height > 5*width) {  // let's assume the letter "I"
         return "I";
         }

      int aveX = minX + width/2;
      int aveY = minY + height/2;
      if (width > height) {
         height = width;
         minY = aveY - height/2;
         maxY = aveY + height/2;
         }
      else {
         width = height;
         minX = aveX - width/2;
         maxX = aveX + width/2;
         }

      int prevBox = -1;
      int currBox;
      String myString = "";

      int boxSize = width/3;   
      int ix, iy;
      int ibox;
      int prevBoxCount = 0;
      for (int i = 1 ; i < dots-1 ; i++) {
         ix = (dot[i].x - minX) / boxSize;
         if (ix > 2)
            ix = 2;
         iy = (dot[i].y - minY) / boxSize;
         if (iy > 2)
            iy = 2;
         currBox = 3*iy + ix;
         box[i] = currBox;
         if (currBox != prevBox) {
            if (prevBoxCount > 0)
               System.out.println(prevBox + " - " + prevBoxCount);
            myString = myString + currBox;
            prevBox = currBox;
            prevBoxCount = 0;
            }
         else
            prevBoxCount++;
         }
      System.out.println(myString);
      if      (myString.equals("345"))           myLetter = " ";
      else if (myString.equals("6341458543"))    myLetter = "A";
      else if (myString.equals("6341258543"))    myLetter = "A";
      else if (myString.equals("6301458543"))    myLetter = "A";
      else if (myString.equals("634125854"))     myLetter = "A";
      else if (myString.equals("6301258543"))    myLetter = "A";
      else if (myString.equals("6301458743"))    myLetter = "A";
      else if (myString.equals("63415854"))      myLetter = "A";
      else if (myString.equals("6341478543"))    myLetter = "A"; // 1 hit, box 5
      else if (myString.equals("64125854"))      myLetter = "A";
      else if (myString.equals("6301254345876")) myLetter = "B";
      else if (myString.equals("2103678"))       myLetter = "C";
      else if (myString.equals("630125876"))     myLetter = "D";
      else if (myString.equals("210343678"))     myLetter = "E";
      else if (myString.equals("21034543678"))   myLetter = "E";
      else if (myString.equals("2103634"))       myLetter = "F";
      else if (myString.equals("21036345"))      myLetter = "F";
      else if (myString.equals("210367854"))     myLetter = "G";
      else if (myString.equals("03678"))         myLetter = "L";
      else if (myString.equals("63045852"))      myLetter = "N";
      else if (myString.equals("630345852"))     myLetter = "N";
      else if (myString.equals("630147852"))     myLetter = "N";
      else if (myString.equals("630145852"))     myLetter = "N";
      else if (myString.equals("63014852"))      myLetter = "N";
      else if (myString.equals("103678521"))     myLetter = "O";
      else if (myString.equals("63012543478"))   myLetter = "R";
      else if (myString.equals("210345876"))     myLetter = "S";
      else if (myString.equals("012147"))        myLetter = "T";
      else if (myString.equals("210147"))        myLetter = "T";
      else if (myString.equals("012543678"))     myLetter = "Z";
      
      return myLetter;
      }
//===== End of overrides needed to implement MouseListener:


//===== These overrides are needed to implement MouseMotionListener:
   public void mouseMoved   (MouseEvent ME) { }

   public void mouseDragged (MouseEvent e) {
      if (dots >= 1000)   // avoid array overflow
         return;

      dot[dots] = new Point(e.getX(), e.getY());
      dots++;
      repaint();  // calls update
      }
//===== End of overrides needed to implement MouseMotionListener

   void makeImage () {
   // This is called when the program starts, and when the main Frame size changes
      canvasWidth  = getSize().width;
      canvasHeight = getSize().height;
      myImage    = createImage (canvasWidth, canvasHeight);
      myGraphics = myImage.getGraphics ();
      setBackground (Color.white);
      }

   public void update (Graphics g) {
   // called by repaint();
      paint (g);
      }

   public void paint (Graphics g) {
      if (myImage == null)
         makeImage ();
      myGraphics.setColor (Color.black);

      for (int i = 0 ; i < dots-1 ; i++) {  // scribble path
         myGraphics.drawLine (dot[i].x, dot[i].y, dot[i+1].x, dot[i+1].y);
         }

      myGraphics.drawString (myDisplayString, 20, 20);
      g.drawImage (myImage, 0, 0, this);
      }

   public void resetData () {
      myDisplayString = "";
      dots = 0;
      }

   public void clearScreen () {
      dots = 0;
      myGraphics.setColor (Color.white);
      myGraphics.fillRect (0, 0, canvasWidth, canvasHeight);
      myGraphics.setColor (Color.black);
      repaint();
      }

   public void displayHelp () {
    //kludge for now
    //need to get font metrics to determine line spacing, etc
      myGraphics.drawString ("Move cursor to start point on drawing area.", 20, 20);
      myGraphics.drawString ("Press left mouse button and draw letter on screen.", 20, 40);
      myGraphics.drawString ("Release left mouse button.", 20, 60);
      myGraphics.drawString ("If system groks scribble, letter will be displayed.", 20, 80);
      myGraphics.drawString ("If systems fails to grok, a '?' will display instead.", 20, 100);
      myGraphics.drawString ("NOTE: This is a demo.  Not all letters are understandable.", 20, 120);
      }
   } //===== end of class scribblerCanvas

public class scribbler extends java.applet.Applet {
   public static final long serialVersionUID = 445L; // not currently used
   public static scribblerFrame myFrame;

   public void init () {
// NOTE: This is the starting point when this is run as an Applet
      myFrame = new scribblerFrame ();
      myFrame.addWindowListener ();
      myFrame.buildGUI ();
      myFrame.addHierarchyBoundsListener ();
      }

   public static void main (String[] args) {
// NOTE: This is the starting point when this is run as an Application
      myFrame = new scribblerFrame ();
      myFrame.addWindowListener ();
      myFrame.buildGUI ();
      myFrame.addHierarchyBoundsListener ();
      }
   }