// bergmark - PanicButton - March 1999

// This application uses ITX telephony to ring a telephone 

// To run the application: have resolv.conf in your current directory.
// Have cstub in your path:
//     Unix:  setenv LD_LIBRARY_PATH
//            java PanicButton
//     NT:    [ set %path% to include path to directory containing cstub.dll ]
//            jview PanicButton

import java.awt.*;               // for graphics, buttons, colors
import java.io.*;
import java.awt.event.*;         // for Mouse and Window Listeners

import cnrg.itx.signal.*;         // for DesktopSignaling
import cnrg.itx.ds.*;             // for DirectoryException
import cnrg.itx.datax.*;		  // for Data Exchange

public class PanicButton extends AbstractSignalingObserver {

   DesktopSignaling sig = null;         // Our signaling component
   Panic myButton = null;               // Our GUI

   // Constructor for PanicButton - constructs a GUI and waits for user input
   public PanicButton() {
      super();
      try {
	 sig = new DesktopSignaling ( (SignalingObserver) this, "jx20@cornell.edu", "cnrgjx20" );
      } catch ( DirectoryServiceException e ) {
	System.out.println ( "PanicButton could not get a DesktopSignalng "
	   + "component because there was a DirectoryServiceException" + e );
      }
      System.out.println (" We got a DesktopSignaling: " + sig);
      myButton = new Panic( this );
   }

   // Here is the main entry point
   public static void main (String[] arg) {

      // Instantiate ourselves just so we can pass our handle to
      // the Panic object, so that it can call our panic method.

      PanicButton myself = new PanicButton();
   }

   // Call the telephone extension number "dest"
   public void panic (String dest) {

   // The Connection object represents the data connection which
   // corresponds to a call set up through signaling.  It has no
   // use in this particular application.

      SignalConnection con = null;

      System.out.println("PanicButton's panic method invoked with "
	 + "dest = " + dest);
      if ( sig == null ) {
	 System.out.println ("unfortunately there is no desktopsignaling");
	 myButton.setStatus ("Call cannot be made - no DesktopSignaling");
      } else {
         try { 
	    con = sig.Dial( dest , (Channel) null, (Channel) null ); 
            myButton.setStatus ("Call was made");
            if (con != null) {
               try {
	          Thread.sleep ( 10000 ); // sleep for 10 seconds
               } catch ( InterruptedException e ) {}
               try {
                  sig.Hangup(con); 
                  myButton.setStatus ("Sending hangup to gateway");
               } catch ( ConnectException e ) {}
            }
         } catch (Exception e) {
            myButton.setStatus ("Call was refused");
            System.out.println ("Caught ITX Dialing Exception " + e );
         }

      } // ends else
   } // ends "panic" method

   // private method to clean up when window is sent away
   private void fini() {
      System.out.println ("PanicButton: logging out");
      sig.logout();
      System.exit(0);
   }

// This class, Panic, is just the graphics part of Panic Button.
// When the panic button is pushed, a call is made to PanicButton's
// panic method, which should ring a telephone.

public class Panic extends Frame implements MouseListener {

   // This is the default telephone extension.  
   private String dest = "45541";

   // This is the textfield for the telephone number
   private TextField t1 = new TextField(dest,20);
   private Label l1 = new Label("Phone:");
   private Panel p1north = new Panel( new FlowLayout() ); 

   // This is the textfield for the status message
   private TextField t2 = new TextField("Starting...",40);
   private Label l2 = new Label ("Status:");
   private Panel p2south = new Panel( new FlowLayout() );

   // This is the state of mouse vis a vis the red circle
   private boolean mousePressedInCircle = false;

   // This is a Canvas for the red circle
   private MyCanvas myCircle;

   // If constructed with a calling application, this is it
   private PanicButton myApp = null;

   // This object will listen for window events (closing)
   private MyWindowListener myWindowListener = null;

   // Constructor for Panic GUI
   public Panic ( PanicButton a ) { 
      super();
      myApp = a;
      myWindowListener = new MyWindowListener ( a );
      init();
   }

   // sets up the GUI and makes it visible
   public void init() {

      // Build the user interface
      setBackground(Color.blue);
      setTitle ("The ITX Panic Button"); 

      // Define a panel containing a label and textbox
      p1north.setForeground(Color.white);
      p1north.add(l1);
      p1north.add(t1);

      // Define a canvas 
      myCircle = new MyCanvas();
      myCircle.setSize ( new Dimension (500, 300) );

      // Define a panel containing a label and textbox
      p2south.setForeground(Color.white);
      p2south.add(l2);
      p2south.add(t2);

      // Using BorderLayout for GUI 
      setLayout ( new BorderLayout() );
      add ( "North", p1north );
      add ( "Center", myCircle );
      add ( "South", p2south );

      // resize GUI so that it doesn't take up the whole screen
      setSize( new Dimension (500,500) ); 
      setVisible ( true );

      // Set up some listeners
      myCircle.addMouseListener(this);
      addWindowListener ( myWindowListener );

   } // end init

   // track mouse events
   public void mousePressed ( MouseEvent e ) {
      //System.out.println("Mouse pressed at " + e.getX() + "," + e.getY() );
      setStatus("");
      double x = e.getX();
      double y = e.getY();
      mousePressedInCircle = myCircle.inCircle ( x, y );
   }

   public void mouseReleased ( MouseEvent e ) {
      //System.out.println("Mouse released at " + e.getX() + "," + e.getY() );
      double x = e.getX();
      double y = e.getY();
      String dest = t1.getText();
      if ( mousePressedInCircle && myCircle.inCircle ( x, y ) ) {
	 setStatus ("Button was pushed -- calling " + dest );
	 myApp.panic( dest );
      }
   }

   // We are ignoring these mouse events
   public void mouseClicked ( MouseEvent e ) {}
   public void mouseEntered ( MouseEvent e ) {}
   public void mouseExited ( MouseEvent e ) {}

   // this allows the Panic GUI's owner to set the Status bar
   private void setStatus (String s) { 
      t2.setText(s); 
   }

} // ends Panic

// WindowListener interface waits for the "goaway" button to be pushed
public class MyWindowListener extends WindowAdapter {

   private PanicButton myApp = null; // lets us get to PanicButton

   // default constructor
   public MyWindowListener ( PanicButton pb ) { 
      myApp = pb;        
   }

   // Override Window closing event
   public void windowClosing ( WindowEvent e ) {
      System.out.println ("MyWindowListener: got an event, windowClosing");
      myApp.fini();
   }

}

// The Panic Button GUI has two Panels and a Canvas.  It turns out
// you really need to extend class Canvas for it to work out right
// (bad symptom was that the red circle came up and disappeared
// immediately).  Hence, a separate class called "MyCanvas".

   public class MyCanvas extends Canvas {

   // This is the diameter and center of the red circle
   // assuming the circle will be drawn at <100,50> w.r.t. canvas
   private int d = 300;
   private int cx = 100+d/2,cy=50+d/2; 

   public MyCanvas (  ) { super(); }

   // Overide the paint method.  Application is 500 x 500
   public void paint ( Graphics g ) {
      // draw a round circle in middle of the app centered at (cx,cy)
      g.setColor (Color.red);
      // x,y,width,height,arc horiz, arc vertical
      g.fillRoundRect ( 100, 50, d, d, d, d );
      g.setFont (new Font ("Helvetica", Font.BOLD, 30));
      g.setColor(Color.blue);
      g.drawString("PANIC!", 200, 200);
   }

   // return true if mouse is in the red circle centered at (cx,cy)
   public boolean inCircle (double x, double y) {
      // compute distance of point (x,y) from middle of circle
      double a = Math.abs ( x - cx );
      double b = Math.abs ( y - cy );
      // calculate c = sqrt (a^2 + b^2)
      double c = Math.sqrt ( Math.pow(a,2) + Math.pow(b,2) );
      return ( c < d/2 ); // true if distance c < radius of circle
   }

   } // ends MyCanvas

}
