/*  
This applet will plot a quadratic curve
*/ 


import java.applet.Applet;
import java.awt.*;
import java.util.Date;
import java.util.Random;

// These classes are for Url's.
import java.net.*;
// import an extra class for the ActionListener
import java.awt.event.*;


public class emission1 extends Applet implements ActionListener {
// Specify variables that will be needed everywhere, anytime here 
	private Image buffer;
	private Graphics bufG;

       	Font bigFont; 
       	Font verybigFont; 
	Font smallFont;
	Font verysmallFont;
	Color whiteColor; 
	Color blackColor; 
	Color greyColor; 
	Color redColor; 
	Color greenColor; 
	Color blueColor; 
	Color orangeColor; 
	Color bgColor; 
	Button resetButton;
	URL base;
	MediaTracker mt;
	myFloat3Slider aSlider;
	myFloatSlider bSlider;
        mySlider cSlider;
	Image my_start;
	Image my_run;
	Image my_hit;
	boolean firsttime;	
	boolean reset;	

	public void init()  
	{ 
		// Resize, in case the HTML author forgot to
		resize(520, 420);

                // Prepare double-buffer
                buffer = createImage(520, 420);
                bufG = buffer.getGraphics();

		// Tell the applet not to use a layout manager.
                setLayout(null);

		// initialize the MediaTracker
                mt = new MediaTracker(this);

		// The try-catch is necessary when the URL isn't valid
                // Of course this one is valid, since it is generated by
                // Java itself.
		try {
                      // getDocumentbase gets the applet path.
                      base = getDocumentBase();
              	}

		catch (Exception e) {}

		// Get the images
		my_start = getImage(base,"carex.gif");
		my_run = getImage(base,"carex2.gif");
		my_hit = getImage(base,"carex3.gif");
	
        	// Will use Arial as type, 16 as size and bold as style 
	        smallFont = new Font("Arial",Font.BOLD,12); 
	        bigFont = new Font("Arial",Font.BOLD,16); 
	        verybigFont = new Font("Arial",Font.BOLD,24); 
	        verysmallFont = new Font("Arial",Font.BOLD,8); 
	        whiteColor = Color.white; 
	        blackColor = Color.black; 
	        greyColor = Color.gray; 
	        redColor = Color.red; 
	        greenColor = Color.green; 
	        blueColor = Color.blue; 
	        orangeColor = Color.orange; 
	        bgColor = new Color(255, 237, 169);

		resetButton = new Button("Reset");
		resetButton.setBounds(20,385,100,30);

		aSlider = new myFloat3Slider( -2000, 2000, 0, 1);
		aSlider.setParent(this);
		FontMetrics fm = bufG.getFontMetrics(smallFont);
		int w1 = fm.stringWidth("a: ");
                aSlider.setBounds(20+w1,10,200,30);

		bSlider = new myFloatSlider( -900, 900, 0, 1);
		bSlider.setParent(this);
		int w2 = fm.stringWidth("b: ");
                bSlider.setBounds(280+w2,10,200,30);

		cSlider = new mySlider( -500, 500, 0, 1);
		cSlider.setParent(this);
		int w3 = fm.stringWidth("c: ");
                cSlider.setBounds(20+w3,45,200,30);

		 // Attach actions to the components
                resetButton.addActionListener(this);

		// Sliders are attached separately, using 'doAction' function
		add(resetButton);
		add(aSlider);
		add(bSlider);
		add(cSlider);

		// Set first time flag
		firsttime = true;
        } 

	// When the button is clicked this method will get automatically called
        public void actionPerformed(ActionEvent evt)
        {
                // Here we will ask what component called this method
                if (evt.getSource() == resetButton) { 
			firsttime = false;
			reset = true;

			aSlider.setValue(0);
			bSlider.setValue(0);
			cSlider.setValue(0);

                	repaint();
		}
	}

	// When the sliders are adjusted this method will get called
        public void doAction() 
	{
		firsttime = false;
		reset = false;

		// Read current values and repaint
               	repaint();
	}

        public void stop() 
        { 
        } 


	// Update method gets rid of flickering
        public void update(Graphics g)  
        { 
		paint(g);
	}

        // Now lets draw things on screen 
        public void paint(Graphics g)  
        { 
		int ix, iy;
		String s;

		// Draw background
	        bufG.setColor(bgColor); 
		bufG.fillRect(0, 0, 520, 420);

		// Don't do much if first time
		if (!firsttime) {
			// Print run images -- image depends on slider readings
			int c = cSlider.getValue();
			int ia = aSlider.getValue();
			int ib = bSlider.getValue();
		
			if (c != 393 || ia != 45 || ib != -675)
				bufG.drawImage(my_run,0+68,135,this);
			else
				bufG.drawImage(my_hit,0+68,135,this);
			

		}	// All this if not firsttime
		else {
			// Reset the screen:
			// Print start images
			bufG.drawImage(my_start,0+68,135,this);
		}

		// Write labels
                bufG.setColor(blackColor);
                bufG.setFont(smallFont);
                bufG.drawString("a: ", 20,30);
                bufG.drawString("b: ", 280,30);
                bufG.drawString("c: ", 20,65);

		// Draw a coordinate system
                bufG.drawLine(40,350,490,350);
                bufG.drawLine(40,120,490,120);
                bufG.drawLine(40,350,40,120);
                bufG.drawLine(490,350,490,120);
	
                bufG.setFont(verysmallFont);
		for (ix=0;ix<=120;ix+=10)
		{
			bufG.drawLine( findX(ix), 350, findX(ix),340 );
			bufG.drawLine( findX(ix), 120, findX(ix),130 );
			s = "" + ix;
			FontMetrics fm = bufG.getFontMetrics(verysmallFont);
			int w1 = fm.stringWidth(s);
			bufG.drawString( s, findX(ix)-w1/2, 370);
		}
		for (iy=-100;iy<=500;iy+=100)
		{
			bufG.drawLine( 40, findY(iy), 50, findY(iy) );
			bufG.drawLine( 490, findY(iy), 480, findY(iy) );
			s = "" + iy;
			FontMetrics fm = bufG.getFontMetrics(verysmallFont);
			int w1 = fm.stringWidth(s);
			bufG.drawString( s, 40-w1-5, findY(iy) + 3 );
		}

                bufG.setFont(smallFont);
		s = "Car Speed (km/h)";
		bufG.drawString( s, 200, 390);

		s = "CO2 emission (g/km)";
		bufG.drawString( s, 5, 100);

		// Print the equation of the lines
		bufG.setColor(redColor); 
	        bufG.setFont(bigFont); 
		s = "y =  " + aSlider.getText() + "x^2 + " + bSlider.getText() + "x + " + cSlider.getText();
	        bufG.drawString(s, 150, 240 ); 
		bufG.setColor(greenColor); 
		s = "y = 0.045 x^2 - 6.75 x + 393";
	        bufG.drawString(s, 150, 170 ); 

		// Print the line and should-be line
		for (ix=0;ix<120;ix+=2) 
		{
			bufG.setColor(redColor); 
			s = aSlider.getText();
			double a = Double.valueOf(s).doubleValue();
			s = bSlider.getText();
			double b = Double.valueOf(s).doubleValue();
			s = cSlider.getText();
			double c = Double.valueOf(s).doubleValue();
			iy = (int)(a*(double)(ix*ix) + b*(double)ix + c);
			if (iy > -5000 && iy < 5000) {
	                	bufG.fillOval(findX(ix)-2, findY(iy)-2, 5, 5);
				
				if (ix>0) {	
					int ixold = ix-2;	
					int iyold = (int)(a*(double)(ixold*ixold) + b*(double)ixold + c);
					bufG.drawLine(findX(ix),findY(iy),findX(ixold),findY(iyold));
				}
			}

			bufG.setColor(greenColor); 
			iy = (int)(0.045*(double)(ix*ix) + -6.75*(double)ix + 393.0);
			if (iy > -5000 && iy < 5000) {
	                	bufG.fillOval(findX(ix)-2, findY(iy)-2, 5, 5);
			}

		}

		 // Copy buffer on screen
                g.drawImage(buffer, 0, 0, this);
        } 

	private int findX( int worldX )
	{
		return (int)(40 + (double)(worldX-0)/120.0*(double)(490-40));
	}

	private int findY( int worldY )
	{
		return (int)(350 - (double)((worldY-(-100))/600.0)*(double)(350-120));
	}
} 


// Here comes the integer slider
public class mySlider extends Panel implements ActionListener,
                                             AdjustmentListener {
  private Scrollbar scrollbar;
  private TextField textfield;
  private ScrollbarPanel scrollbarPanel;
  private int preferredWidth = 250;

  private emission1 el;

  /** Construct a slider with the specified min, max and initial
   *  values. The "bubble" (thumb) size is set to 1/10th the
   *  scrollbar range.
   */

  public mySlider(int minValue, int maxValue, int initialValue) {
    this(minValue, maxValue, initialValue,
         (maxValue - minValue)/10);
  }

  /** Construct a slider with the specified min, max,and initial
   *  values, plus the specified "bubble" (thumb) value. This
   *  bubbleSize should be specified in the units that min and
   *  max use, not in pixels. Thus, if min is 20 and max is 320,
   *  then a bubbleSize of 30 is 10% of the visible range.
   */

  public mySlider(int minValue, int maxValue, int initialValue,
                int bubbleSize) {
    setLayout(new BorderLayout());
    maxValue = maxValue + bubbleSize;
    scrollbar = new Scrollbar(Scrollbar.HORIZONTAL,
                              initialValue, bubbleSize,
                              minValue, maxValue);
    scrollbar.addAdjustmentListener(this);
    scrollbarPanel = new ScrollbarPanel(6);
    scrollbarPanel.add(scrollbar, BorderLayout.CENTER);
    add(scrollbarPanel, BorderLayout.CENTER);
    textfield = new TextField(numDigits(maxValue) + 1);
    textfield.addActionListener(this);
    setFontSize(12);
    textfield.setEditable(false);
    setTextFieldValue();
    add(textfield, BorderLayout.EAST);
  }

  /** Set parent address */
  public void setParent(emission1 thisEl)
  {
	el = thisEl;
  }

  /** A place holder to override for action to be taken when
   *  scrollbar changes.
   */

  public void doAction(int value) {
        el.doAction();
  }

  /** When textfield changes, sets the scrollbar */

  public void actionPerformed(ActionEvent event) {
    String value = textfield.getText();
    int oldValue = getValue();
    try {
      setValue(Integer.parseInt(value.trim()));
    } catch(NumberFormatException nfe) {
      setValue(oldValue);
    }
  }

  /** When scrollbar changes, sets the textfield */

  public void adjustmentValueChanged(AdjustmentEvent event) {
    setTextFieldValue();
    doAction(scrollbar.getValue());
  }

  /** This returns the current scrollbar value */

  public int getValue() {
    return(scrollbar.getValue());
  }

  /** This assigns the scrollbar value. If it is below the
   *  minimum value or above the maximum, the value is set to
   *  the min and max value, respectively.
   */

  public void setValue(int value) {
    scrollbar.setValue(value);
    setTextFieldValue();
  }

  /** Returns the current textfield string. In most cases this
   *  is just the same as a String version of getValue, except
   *  that there may be padded blank spaces at the left.
   */

  public String getText() {
    return(textfield.getText());
  }

  /** Rather than setting the whole font, you can just set the
   *  size (Monospaced bold will be used for the family/face).
   */

  public void setFontSize(int size) {
    setFont(new Font("Monospaced", Font.BOLD, size));
  }

  /** Determines if the textfield is editable. If it is, you can
   *  enter a number to change the scrollbar value. In such a
   *  case, entering a value outside the legal range results in
   *  the min or max legal value. A non-integer is ignored.
   */

  public boolean isEditable() {
    return(textfield.isEditable());
  }

  /** Determines if you can enter values directly into the
   *  textfield to change the scrollbar.
   */

  public void setEditable(boolean editable) {
    textfield.setEditable(editable);
  }

  // Sets a right-aligned textfield number.

  private void setTextFieldValue() {
    int value = scrollbar.getValue();
    int digits = numDigits(scrollbar.getMaximum());

    if (value > 4990) 
	    value = 5000;

    String valueString = padString(value, digits);
    textfield.setText(valueString);
  }

  // Repeated String concatenation is expensive, but this is
  // only used to add a small amount of padding, so converting
  // to a StringBuffer would not pay off.

  private String padString(int value, int digits) {
    String result = String.valueOf(value);
    for(int i=result.length(); i<digits; i++) {
      result = " " + result;
    }
    return(result + " ");
  }

  // Determines the number of digits in a decimal number.

  private static final double LN10 = Math.log(10.0);

  private static int numDigits(int num) {
    return(1 + (int)Math.floor(Math.log((double)num)/LN10));
  }
}


// Here comes the float slider
/** This is a special version that shows the slider value as 
    decimal number (divided by factor 100) */
public class myFloatSlider extends Panel implements ActionListener,
                                             AdjustmentListener {
  private Scrollbar scrollbar;
  private TextField textfield;
  private ScrollbarPanel scrollbarPanel;
  private int preferredWidth = 250;

  private emission1 el;

  /** Construct a slider with the specified min, max and initial
   *  values. The "bubble" (thumb) size is set to 1/10th the
   *  scrollbar range.
   */

  public myFloatSlider(int minValue, int maxValue, int initialValue) {
    this(minValue, maxValue, initialValue,
         (maxValue - minValue)/10);
  }

  /** Construct a slider with the specified min, max,and initial
   *  values, plus the specified "bubble" (thumb) value. This
   *  bubbleSize should be specified in the units that min and
   *  max use, not in pixels. Thus, if min is 20 and max is 320,
   *  then a bubbleSize of 30 is 10% of the visible range.
   */

  public myFloatSlider(int minValue, int maxValue, int initialValue,
                int bubbleSize) {
    setLayout(new BorderLayout());
    maxValue = maxValue + bubbleSize;
    scrollbar = new Scrollbar(Scrollbar.HORIZONTAL,
                              initialValue, bubbleSize,
                              minValue, maxValue);
    scrollbar.addAdjustmentListener(this);
    scrollbarPanel = new ScrollbarPanel(6);
    scrollbarPanel.add(scrollbar, BorderLayout.CENTER);
    add(scrollbarPanel, BorderLayout.CENTER);
    textfield = new TextField(numDigits(maxValue) + 2);
    textfield.addActionListener(this);
    setFontSize(12);
    textfield.setEditable(false);
    setTextFieldValue();
    add(textfield, BorderLayout.EAST);
  }

  /** Set parent address */
  public void setParent(emission1 thisEl)
  {
	el = thisEl;
  }

  /** A place holder to override for action to be taken when
   *  scrollbar changes.
   */

  public void doAction(int value) {
        el.doAction();
  }

  /** When textfield changes, sets the scrollbar */

  public void actionPerformed(ActionEvent event) {
    String value = textfield.getText();
    int oldValue = getValue();
    try {
      setValue(Integer.parseInt(value.trim()));
    } catch(NumberFormatException nfe) {
      setValue(oldValue);
    }
  }

  /** When scrollbar changes, sets the textfield */

  public void adjustmentValueChanged(AdjustmentEvent event) {
    setTextFieldValue();
    doAction(scrollbar.getValue());
  }

  /** This returns the current scrollbar value */

  public int getValue() {
    return(scrollbar.getValue());
  }

  /** This assigns the scrollbar value. If it is below the
   *  minimum value or above the maximum, the value is set to
   *  the min and max value, respectively.
   */

  public void setValue(int value) {
    scrollbar.setValue(value);
    setTextFieldValue();
  }

  /** Returns the current textfield string. In most cases this
   *  is just the same as a String version of getValue, except
   *  that there may be padded blank spaces at the left.
   */

  public String getText() {
    return(textfield.getText());
  }

  /** Rather than setting the whole font, you can just set the
   *  size (Monospaced bold will be used for the family/face).
   */

  public void setFontSize(int size) {
    setFont(new Font("Monospaced", Font.BOLD, size));
  }

  /** Determines if you can enter values directly into the
   *  textfield to change the scrollbar.
   */

  public void setEditable(boolean editable) {
    textfield.setEditable(editable);
  }

  // Sets a right-aligned textfield number.

  private void setTextFieldValue() {
    int value = scrollbar.getValue();
    int myvalue = Math.abs(scrollbar.getValue());
    int myvalue2 = Math.abs(scrollbar.getValue()-100);
    int myvalue3 = Math.abs(scrollbar.getValue()-200);
    int myvalue4 = Math.abs(scrollbar.getValue()-300);
    int myvalue5 = Math.abs(scrollbar.getValue()-400);
    int myvalue6 = Math.abs(scrollbar.getValue()-500);
    int myvalue7 = Math.abs(scrollbar.getValue()-600);
    int myvalue8 = Math.abs(scrollbar.getValue()-700);
    int myvalue9 = Math.abs(scrollbar.getValue()-800);
    int myvalue10 = Math.abs(scrollbar.getValue()-900);
    int myvalue11 = Math.abs(scrollbar.getValue()+100);
    int myvalue12 = Math.abs(scrollbar.getValue()+200);
    int myvalue13 = Math.abs(scrollbar.getValue()+300);
    int myvalue14 = Math.abs(scrollbar.getValue()+400);
    int myvalue15 = Math.abs(scrollbar.getValue()+500);
    int myvalue16 = Math.abs(scrollbar.getValue()+600);
    int myvalue17 = Math.abs(scrollbar.getValue()+700);
    int myvalue18 = Math.abs(scrollbar.getValue()+800);
    int myvalue19 = Math.abs(scrollbar.getValue()+900);
    int digits = numDigits(scrollbar.getMaximum());
//    String valueString = padString(myvalue, digits);
    String valueString = padString(myvalue, 0);
    String valueString2 = padString(myvalue2, 0);
    String valueString3 = padString(myvalue3, 0);
    String valueString4 = padString(myvalue4, 0);
    String valueString5 = padString(myvalue5, 0);
    String valueString6 = padString(myvalue6, 0);
    String valueString7 = padString(myvalue7, 0);
    String valueString8 = padString(myvalue8, 0);
    String valueString9 = padString(myvalue9, 0);
    String valueString10 = padString(myvalue10, 0);
    String valueString11 = padString(myvalue11, 0);
    String valueString12 = padString(myvalue12, 0);
    String valueString13 = padString(myvalue13, 0);
    String valueString14 = padString(myvalue14, 0);
    String valueString15 = padString(myvalue15, 0);
    String valueString16 = padString(myvalue16, 0);
    String valueString17 = padString(myvalue17, 0);
    String valueString18 = padString(myvalue18, 0);
    String valueString19 = padString(myvalue19, 0);
    if (value >= 0 && value < 10) 
	    textfield.setText("0.0" + valueString);
    else if (value >= 0 && value >= 10 && value < 100) 
	    textfield.setText("0." + valueString);
    else if (value >= 0 && value >= 100 && value < 110) 
	    textfield.setText("1.0" + valueString2);
    else if (value >= 0 && value >= 110 && value < 200) 
	    textfield.setText("1." + valueString2);
    else if (value >= 0 && value >= 200 && value < 210) 
	    textfield.setText("2.0" + valueString3);
    else if (value >= 0 && value >= 210 && value < 300) 
	    textfield.setText("2." + valueString3);
    else if (value >= 0 && value >= 300 && value < 310) 
	    textfield.setText("3.0" + valueString4);
    else if (value >= 0 && value >= 310 && value < 400) 
	    textfield.setText("3." + valueString4);
    else if (value >= 0 && value >= 400 && value < 410) 
	    textfield.setText("4.0" + valueString5);
    else if (value >= 0 && value >= 410 && value < 500) 
	    textfield.setText("4." + valueString5);
    else if (value >= 0 && value >= 500 && value < 510) 
	    textfield.setText("5.0" + valueString6);
    else if (value >= 0 && value >= 510 && value < 600) 
	    textfield.setText("5." + valueString6);
    else if (value >= 0 && value >= 600 && value < 610) 
	    textfield.setText("6.0" + valueString7);
    else if (value >= 0 && value >= 610 && value < 700) 
	    textfield.setText("6." + valueString7);
    else if (value >= 0 && value >= 700 && value < 710) 
	    textfield.setText("7.0" + valueString8);
    else if (value >= 0 && value >= 710 && value < 800) 
	    textfield.setText("7." + valueString8);
    else if (value >= 0 && value >= 800 && value < 810) 
	    textfield.setText("8.0" + valueString9);
    else if (value >= 0 && value >= 810 && value < 900) 
	    textfield.setText("8." + valueString9);
    else if (value >= 0 && value >= 900 && value < 910) 
	    textfield.setText("9.0" + valueString10);
    else if (value >= 0 && value >= 910 && value < 1000) 
	    textfield.setText("9." + valueString10);
    else if (value >= 0 && value >= 1000) 
	    textfield.setText("10.00" );
    else if (value < 0 && value > -10) 
	    textfield.setText("-0.0" + valueString);
    else if (value < 0 && value <= -10 && value > -100) 
	    textfield.setText("-0." + valueString);
    else if (value < 0 && value <= -100 && value > -110) 
	    textfield.setText("-1.0" + valueString11);
    else if (value < 0 && value <= -110 && value > -200) 
	    textfield.setText("-1." + valueString11);
    else if (value < 0 && value <= -200 && value > -210) 
	    textfield.setText("-2.0" + valueString12);
    else if (value < 0 && value <= -210 && value > -300) 
	    textfield.setText("-2." + valueString12);
    else if (value < 0 && value <= -300 && value > -310) 
	    textfield.setText("-3.0" + valueString13);
    else if (value < 0 && value <= -310 && value > -400) 
	    textfield.setText("-3." + valueString13);
    else if (value < 0 && value <= -400 && value > -410) 
	    textfield.setText("-4.0" + valueString14);
    else if (value < 0 && value <= -410 && value > -500) 
	    textfield.setText("-4." + valueString14);
    else if (value < 0 && value <= -500 && value > -510) 
	    textfield.setText("-5.0" + valueString15);
    else if (value < 0 && value <= -510 && value > -600) 
	    textfield.setText("-5." + valueString15);
    else if (value < 0 && value <= -600 && value > -610) 
	    textfield.setText("-6.0" + valueString16);
    else if (value < 0 && value <= -610 && value > -700) 
	    textfield.setText("-6." + valueString16);
    else if (value < 0 && value <= -700 && value > -710) 
	    textfield.setText("-7.0" + valueString17);
    else if (value < 0 && value <= -710 && value > -800) 
	    textfield.setText("-7." + valueString17);
    else if (value < 0 && value <= -800 && value > -810) 
	    textfield.setText("-8.0" + valueString18);
    else if (value < 0 && value <= -810 && value > -900) 
	    textfield.setText("-8." + valueString18);
    else if (value < 0 && value <= -900 && value > -910) 
	    textfield.setText("-9.0" + valueString19);
    else if (value < 0 && value <= -910 && value > -1000) 
	    textfield.setText("-9." + valueString19);
    else 
	    textfield.setText("-10.00");
  }

  // Repeated String concatenation is expensive, but this is
  // only used to add a small amount of padding, so converting
  // to a StringBuffer would not pay off.

  private String padString(int value, int digits) {
    String result = String.valueOf(value);
    for(int i=result.length(); i<digits; i++) {
      result = " " + result;
    }
    return(result + " ");
  }

  // Determines the number of digits in a decimal number.

  private static final double LN10 = Math.log(10.0);

  private static int numDigits(int num) {
    return(1 + (int)Math.floor(Math.log((double)num)/LN10));
  }
}


// Here comes the float slider, high-precision version...
/** This is a special version that shows the slider value as 
    decimal number (divided by factor 1000) */
public class myFloat3Slider extends Panel implements ActionListener,
                                             AdjustmentListener {
  private Scrollbar scrollbar;
  private TextField textfield;
  private ScrollbarPanel scrollbarPanel;
  private int preferredWidth = 250;

  private emission1 el;

  /** Construct a slider with the specified min, max and initial
   *  values. The "bubble" (thumb) size is set to 1/10th the
   *  scrollbar range.
   */

  public myFloat3Slider(int minValue, int maxValue, int initialValue) {
    this(minValue, maxValue, initialValue,
         (maxValue - minValue)/10);
  }

  /** Construct a slider with the specified min, max,and initial
   *  values, plus the specified "bubble" (thumb) value. This
   *  bubbleSize should be specified in the units that min and
   *  max use, not in pixels. Thus, if min is 20 and max is 320,
   *  then a bubbleSize of 30 is 10% of the visible range.
   */

  public myFloat3Slider(int minValue, int maxValue, int initialValue,
                int bubbleSize) {
    setLayout(new BorderLayout());
    maxValue = maxValue + bubbleSize;
    scrollbar = new Scrollbar(Scrollbar.HORIZONTAL,
                              initialValue, bubbleSize,
                              minValue, maxValue);
    scrollbar.addAdjustmentListener(this);
    scrollbarPanel = new ScrollbarPanel(6);
    scrollbarPanel.add(scrollbar, BorderLayout.CENTER);
    add(scrollbarPanel, BorderLayout.CENTER);
    textfield = new TextField(numDigits(maxValue) + 2);
    textfield.addActionListener(this);
    setFontSize(12);
    textfield.setEditable(false);
    setTextFieldValue();
    add(textfield, BorderLayout.EAST);
  }

  /** Set parent address */
  public void setParent(emission1 thisEl)
  {
	el = thisEl;
  }

  /** A place holder to override for action to be taken when
   *  scrollbar changes.
   */

  public void doAction(int value) {
        el.doAction();
  }

  /** When textfield changes, sets the scrollbar */

  public void actionPerformed(ActionEvent event) {
    String value = textfield.getText();
    int oldValue = getValue();
    try {
      setValue(Integer.parseInt(value.trim()));
    } catch(NumberFormatException nfe) {
      setValue(oldValue);
    }
  }

  /** When scrollbar changes, sets the textfield */

  public void adjustmentValueChanged(AdjustmentEvent event) {
    setTextFieldValue();
    doAction(scrollbar.getValue());
  }

  /** This returns the current scrollbar value */

  public int getValue() {
    return(scrollbar.getValue());
  }

  /** This assigns the scrollbar value. If it is below the
   *  minimum value or above the maximum, the value is set to
   *  the min and max value, respectively.
   */

  public void setValue(int value) {
    scrollbar.setValue(value);
    setTextFieldValue();
  }

  /** Returns the current textfield string. In most cases this
   *  is just the same as a String version of getValue, except
   *  that there may be padded blank spaces at the left.
   */

  public String getText() {
    return(textfield.getText());
  }

  /** Rather than setting the whole font, you can just set the
   *  size (Monospaced bold will be used for the family/face).
   */

  public void setFontSize(int size) {
    setFont(new Font("Monospaced", Font.BOLD, size));
  }

  /** Determines if you can enter values directly into the
   *  textfield to change the scrollbar.
   */

  public void setEditable(boolean editable) {
    textfield.setEditable(editable);
  }

  // Sets a right-aligned textfield number.

  private void setTextFieldValue() {
    int value = scrollbar.getValue();
    int myvalue = Math.abs(scrollbar.getValue());
    int myvalue2 = Math.abs(scrollbar.getValue()-1000);
    int myvalue3 = Math.abs(scrollbar.getValue()+1000);
    int digits = numDigits(scrollbar.getMaximum());
//    String valueString = padString(myvalue, digits);
    String valueString = padString(myvalue, 0);
    String valueString2 = padString(myvalue2, 0);
    String valueString3 = padString(myvalue3, 0);
    if (value >= 0 && value < 10) 
	    textfield.setText("0.00" + valueString);
    else if (value >= 0 && value >= 10 && value < 100) 
	    textfield.setText("0.0" + valueString);
    else if (value >= 0 && value >= 100 && value < 1000) 
	    textfield.setText("0." + valueString);
    else if (value >= 0 && value >= 1000 && value < 2000) 
	    textfield.setText("1.0" + valueString2);
    else if (value >= 0 && value >= 2000) 
	    textfield.setText("2.000");
    else if (value < 0 && value > -10) 
	    textfield.setText("-0.00" + valueString);
    else if (value < 0 && value <= -10 && value > -100) 
	    textfield.setText("-0.0" + valueString);
    else if (value < 0 && value <= -100 && value > -1000) 
	    textfield.setText("-0." + valueString);
    else if (value < 0 && value <= -1000 && value > -2000) 
	    textfield.setText("-1." + valueString3);
    else 
	    textfield.setText("-2.000");
  }

  // Repeated String concatenation is expensive, but this is
  // only used to add a small amount of padding, so converting
  // to a StringBuffer would not pay off.

  private String padString(int value, int digits) {
    String result = String.valueOf(value);
    for(int i=result.length(); i<digits; i++) {
      result = " " + result;
    }
    return(result + " ");
  }

  // Determines the number of digits in a decimal number.

  private static final double LN10 = Math.log(10.0);

  private static int numDigits(int num) {
    return(1 + (int)Math.floor(Math.log((double)num)/LN10));
  }
}
