import java.applet.Applet;  // need to inherit from built-in Applet
import java.awt.*;          // Window I/O classes
import java.awt.event.*;    // Event classes

// Dilip Barman  November 3, 1997
// file hw2Applet.java

// 11/3/97: Frustrated trying to get GridBagLayout to work - UI is
//   basically correct but I have to tweak the constraints
// 11/4/97: Done!  This wasn't particularly easy but everything
//   fell into place today.  I got the hint that I should set the
//   fill to BOTH for colorPanel and by reducing Insets, I got it
//   to format nicely.  Also, I had been having problems with
//   listening on scrollbar actions - I was using in the class
//   definition "implements Adjustable" instead of AdjustmentListener!

// 2nd java homework assignment, to exercise the use of multiple UI
// widgets and their layout, plus event processing.  We are to build
// an application that looks like:
//
// Color Selector Applet
//
//   +--------------------------------------------------+
//   |    +---------+         +---+    < scrollbar >    |
//   |    |         |         +---+                     |
//   |    |         |                                   |
//   |    |         |         +---+    < scrollbar >    |
//   |    |         |         +---+                     |
//   |    |         |                                   |
//   |    |         |         +---+    < scrollbar >    |
//   |    |         |         +---+                     |
//   |    +---------+                                   |
//   +--------------------------------------------------+
//
// The user manipulates the scrollbars to specify R, G, and B values.  
// Dynamically, as the mouse moves, the numeric value is updated
// in the text area to the immediate left of each scrollbar, and
// the big box to the left changes to the color corresponding to the
// specified RGB value.  The background is light bluish-gray in color,
// and the scrollbars and numeric windows are white.  Also, the user
// can specify R, G, and B values by entering them in the text areas
// and hitting enter.


public class hw2Applet 
  extends Applet 
  implements ActionListener, AdjustmentListener
// listen for  window close, text edit; scrolling

{

  // ***********  Constants   ***********

  int initialR      = 160;          // set initial RGB values
  int initialG      = 224;
  int initialB      = 255;
  int minRGB        = 0;            // min and max RGB values
  int maxRGB        = 255;

  // ***********  Class Variables   ***********  (none)

  // ***********  Instance Variables   ***********

  MyFrame frame     = new MyFrame ();  // closeable frame def. in MyFrame.java
  Panel colorPanel  = new Panel();  // panel to display color choice

  // TextField rValue  = new TextField (" ", 3);  // define 3-character wide text fields
  TextField rValue  = new TextField (Integer.toString (initialR), 3);
  TextField gValue  = new TextField (Integer.toString (initialG), 3);
  TextField bValue  = new TextField (Integer.toString (initialB), 3);

  Scrollbar rScrollbar = new Scrollbar 
                         (Scrollbar.HORIZONTAL, initialR, 1, minRGB, maxRGB);

  Scrollbar gScrollbar = new Scrollbar 
                         (Scrollbar.HORIZONTAL, initialG, 1, minRGB, maxRGB);

  Scrollbar bScrollbar = new Scrollbar 
                         (Scrollbar.HORIZONTAL, initialB, 1, minRGB, maxRGB);

  GridBagLayout gb = new GridBagLayout();
  GridBagConstraints gbc = new GridBagConstraints();


  // ***********  Standard Applet Methods   ***********

  // Now we define methods.  Applets look for 4 methods - init, start, stop, and destroy
  // init() is called when the applet is loaded, start() when it starts execution (i.e.,
  // right after init() and whenever we revisit this web page), stop() when we leave this
  // web page, and destroy() when we leave the browser.

  public void init()
    {
      createFrame ();  // All the work is here!
    }

  public void start()
    {
    System.out.println ("Starting applet ... \n");
    }

  public void stop()
    {
    System.out.println ("Stopping applet\n");
    }

  public void destroy()
    {
    System.out.println ("Destroying applet execution instance\n");
    }

  // Define an optional paint method.  This method gets called and
  // passed a pointer to the current graphics context whenever an
  // object is exposed.  
  public void paint (Graphics g )  
    {
      // g.setColor (Color.black);
      // g.setFont (new Font ("Helvetica", Font.PLAIN, 14) );
      // g.drawString ("Dilip's Display Message Applet", 0, 0);
      // g.fillRect (50, 50, 100, 100);
    }  // end paint



  // ***********  Other Methods   ***********

  // Method to create and display the frame
  private void createFrame ( ) 
    {
    setDefaultBoundsColors ();
    addComponentsToFrame ();
    listenForEvents ();
    frame.show ();    // Finally, show the frame!
    }  // end createFrame() private class method



  // Method to setup initial sizes, colors, etc. of components
  private void setDefaultBoundsColors ( ) 
    {
      frame.setBounds(50, 200, 400, 200);     // topL x, topL y, width, height
    frame.setTitle ("Dilip's Color Selector");
    frame.setBackground (Color.white);

    colorPanel.setBounds(50, 50, 200, 200);     // topL x, topL y, width, height
    // above sets preferred size, but can change via layout mgr as user resizes
    colorPanel.setBackground ( new Color (initialR, initialG, initialB) );
    }  // end setDefaultBoundsColors()


  // Method to add the components using layout manager
  private void addComponentsToFrame ()
    {
      // Instead of ...
      //  frame.add (colorPanel); frame.add (rScrollbar); frame.add (gScrollbar); ETC ...
      // we'll use the GridBagLayout manager to place a panel, three text
      // fields, and three horizontal scrollbars into a closeable frame.
      // So, we have a 3x3 grid.  Since we want the panel to be bigger, let's
      // work with a 6 column by 3 row grid - the panel has size 3x3 and
      // has upper NW corner (gridx, gridy) of (0,0).  The three text boxes
      // are 1x1 and start at (3,0), (3,1), and (3,2).  The scrollbars are
      // 2x1 and start at (4,0), (4,1), and (4,2).

      frame.setLayout (gb);   // GridBagLayout
      // addComponent (container, component, gridx, gridy, gridwidth, gridheight, fill, anchor)
      // but we'll use our own helper function
      // addGridBoxComponent (container, component, gbl, gbc, col, row, width, height)

      // Set Grid Bag Constraints
      gbc.insets = new Insets (20, 20, 20, 20); // border values around component - t,b,l,r
      gbc.anchor= GridBagConstraints.CENTER;    // compass where component anchored
      gbc.weightx = 10;                         // how much can be resized horiz.
      gbc.weighty = 10;                         // -same but vert.-
      gbc.fill = GridBagConstraints.BOTH;       // whether and in which directions can expand

    addGridBoxComponent ( frame, colorPanel, gb, gbc, 0, 0, 3, 3 );

    gbc.weightx = 0;
    gbc.weighty = 0;
    gbc.insets = new Insets (20, 20, 20, 20);
    gbc.fill = GridBagConstraints.NONE;
    addGridBoxComponent ( frame, rValue, gb, gbc,     3, 0, 1, 1 );
    addGridBoxComponent ( frame, gValue, gb, gbc,     3, 1, 1, 1 );
    addGridBoxComponent ( frame, bValue, gb, gbc,     3, 2, 1, 1 );

    gbc.weightx = 5;
    gbc.weighty = 5;
    gbc.insets = new Insets (20, 20, 10, 10);
    gbc.fill = GridBagConstraints.HORIZONTAL;
    addGridBoxComponent ( frame, rScrollbar, gb, gbc, 4, 0, 2, 1 );
    addGridBoxComponent ( frame, gScrollbar, gb, gbc, 4, 1, 2, 1 );
    addGridBoxComponent ( frame, bScrollbar, gb, gbc, 4, 2, 2, 1 );
  
    }  // end addComponentsToFrame()

  // Helper method to add a component when using grid bag layout
  public void addGridBoxComponent 
         (Container cont, Component comp, GridBagLayout gbl, GridBagConstraints gbc, 
          int col, int row, int wid, int hgt )
    {
    gbc.gridx = col;
    gbc.gridy = row;
    gbc.gridwidth = wid;
    gbc.gridheight = hgt;
    gbl.setConstraints ( comp, gbc );
    cont.add ( comp );
    }  // end addGridBoxComponent


  // Method to register to listen for events we need to react to
  private void listenForEvents ()
    {
      // Listen on events like close (handle in MyFrame class)
    frame.addWindowListener (frame);

    // Listen on scrolling (handle here - interface methods below)
    rScrollbar.addAdjustmentListener ( this );  
    gScrollbar.addAdjustmentListener ( this );  
    bScrollbar.addAdjustmentListener ( this );  

    // Listen on editing text - user types value (handle here)
    rValue.addActionListener(this);
    gValue.addActionListener(this);
    bValue.addActionListener(this);
    }  // end listenForEvents()


  //***********  Interface Methods   ***********


  // Now define IMPLEMENTORS - override ActionListener class's 
  // actionPerformed method to handle when a textField is edited.
  public void actionPerformed ( ActionEvent e )  
    {
    if (e.getSource() instanceof TextField)
      {
        updateScrollbarValues();
        colorPanel.setBackground ( new Color (
                                              (rScrollbar.getValue()),
                                              (gScrollbar.getValue()),
                                              (bScrollbar.getValue()) 
                                             )                         );
      }  
    }  // end actionPerformed


  // Override AdjustmentListener method adjustmentValueChanged to
  // handle when there is a scrollbar manipulation.
  public void adjustmentValueChanged ( AdjustmentEvent e ) 
    {
    colorPanel.setBackground ( new Color (
                                          (rScrollbar.getValue()),
                                          (gScrollbar.getValue()),
                                          (bScrollbar.getValue()) 
                                         )                         );
    updateTextValues();
    }


  // Helper methods to update scroll bar and text boxes on events
  private void updateScrollbarValues ()  // copy text boxes -> scrollbar values
    {
    rScrollbar.setValue ( Integer.parseInt (rValue.getText()) );
    gScrollbar.setValue ( Integer.parseInt (gValue.getText()) );
    bScrollbar.setValue ( Integer.parseInt (bValue.getText()) );
    }

  private void updateTextValues ()  // copy scrollbar values -> text boxes
    {
    rValue.setText ( Integer.toString (rScrollbar.getValue()) );
    gValue.setText ( Integer.toString (gScrollbar.getValue()) );
    bValue.setText ( Integer.toString (bScrollbar.getValue()) );
    }

}  // end class definition

