analogapplet.java

来自「Zword公司的Rabbit2000系列相关文件」· Java 代码 · 共 858 行 · 第 1/2 页

JAVA
858
字号
/**   AnalogApplet.java
 *
 *	Z-World, 2001
 *
 *      An applet framework for control of the analog output on a BL2000.
 *      Uses a TCP connection back to BL2000 for control messages.
 *	Code tries to use java 1.1 classes. It uses the version 1.1 input
 *	event model.
 *
 *	@Version 0.05
 *	@date	May 2001
 *	@Author	Z-World, Inc (software)
 *
 */


import java.awt.*;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
import java.applet.*;
import java.net.*;
import java.io.*;
import java.util.Vector;


/**
 *	Applet class.  Creates visual components and network connection objects
 *	as well.  User drags the scrollbars to control the DAC outputs.
 *	<br> The applet appearance looks like this:
 *<pre> 	Message Line..
 *	{ label(0) + slider(0).. }
 *	{ label(1) + slider(1).. }
 *	Status Text..
 *	Value Text.. </pre>
 *	The &quot;Status Text&quot; is separate from the browser status line.
 *
 *	<P> Will not connect with session ID 0.  That means server already
 *	has a client it is serving.  Ensures Java 1.1 classes we need
 *	(e.g. AWT Listener) are present.
 */
public class AnalogApplet extends Applet
{

    /**
     *	Create layout with text labels and value scrollers.
     *	Connects back to host establishing a command socket.
     *	Uses <code>this.getCodeBase().getHost()</code> to find host system.
     *  Will not connect with session ID 0.  That means server already
     *  has a client it is serving.
     *
     *	<p> Ensures Java 1.1 classes we need (AWT Listener) are present.
     */
    public void init()
    {
	int    server_tcp_port = 0;

	/*  Proof of geekiness: We use the GridBagLayout manager.  Rows
	 *  with text labels stretch to full width with left-side alignment.
	 *  Rows with scrollbars and value bars have a fixed width label
	 *  on the leftside with a full-stretch scroll "cell".
	 */
	myGridBag = new GridBagLayout();
	presetConstraints();

	/*  Now pile on the "cells" */
        messageLine = new Label();
	myGridBag.setConstraints( messageLine, _fullWidthConstraint );
        add( messageLine );

	myAnalogController = new ValueListenerBoardUpdater();
	myAnalogController.init();

	/*  Make sure classes exist before trying to use them. */
	if( !checkRuntime() ) {
	    outMessage( "ERROR: Required Java 1.1 classes are missing!");
	    outStatus( "ERROR: Applet cannot continue." );
	    return ;
	}

	/** We've check that all our Java 1.1 classes exist, proceed. **/

        makeControl(0);
        makeControl(1);

	if( SW_A_TO_D_WORKING ) {
	makeValueBar(-1);		// "-1" means no A/D selected.
	}

        statusLine = new Label();
	myGridBag.setConstraints( statusLine, _fullWidthConstraint );
        add( statusLine );

	valueText = new Label();
	myGridBag.setConstraints( valueText, _fullWidthConstraint );
	add( valueText );
	valueText.setText( "    " );

	String param = "";
        try {
	    param = this.getParameter( "SESSION_ID" );
            if( (sessID = Integer.parseInt(param)) < 0 ) {
		outMessage( "ERROR: Session ID isn't valid." );
            }
	    param = this.getParameter( "CMD_PORT" );
	    if( (server_tcp_port = Integer.parseInt(param)) <= 0 ) {
		outMessage( "ERROR: Illegal server TCP port." );
	    }
	    param = this.getParameter( "MAX_VOLTAGE" );
	    if( (myMaxVolts = (new Float(param).floatValue())) <= 0.0 ) {
		outMessage( "ERROR: Illegal server TCP port." );
	    }
        } catch( NumberFormatException e ) {
	    /*  Either SESSION_ID wasn't found or a number conversion 
	     *  occurred.  Oh well, display a diagnostic.
	     */
	    outStatus( "ERROR: Bad params ("+param+"), you need to restart." +
		       sessID + "/" + server_tcp_port + "/" + myMaxVolts );
	    return ;
	}

	if( sessID == 0 ) {
	    /*  Could make a frame here, effectively creating a dialog box.
	     *  That exercise is left to the reader... :)
	     */
	    outMessage( "NOTICE: Analog server is busy." );
	    outStatus(  "NOTICE: Not connecting to remote server." );
	    return ;
	}

	myAnalogController.setOutput( statusLine );
	myAnalogController.setVoltageLabel( valueText );

	/*  Connect to Rabbit "server" */
	showStatus( "Connecting..." );
	myConn = new RabbitNetworkClient();
	myConn.hookupTCP( this.getCodeBase().getHost(), server_tcp_port, this ); 
	myAnalogController.setConnection( myConn );

	/*  Display `ready' message in browser's status line. */
	showStatus( "applet ready" );

    }  /* end init() method */

    /**  Make sure network object can close and cleanup.  "destory"
     *   called when applet no longer needed (not just hidden).
     */
    public void destroy()	/* override */
    {
	myConn.destroy();
    }   /* end destroy() method */

    /* ---------------------------------------------------------- */

    /**
     *	Ensure our 1.1 classes exist in the browser's Java runtime.
     *  Returns TRUE when life is good.  Otherwise FALSE.  <b>The
     *	application must not continue since required classes are
     *	missing!</b>
     *
     *	@return	<code>FALSE</code> if a Java 1.1 class is missing.
     */
    private boolean checkRuntime()
    {
	Class	gotit;

	try {
	    gotit = Class.forName( "java.awt.AWTEvent" );
	    gotit = Class.forName( "java.util.EventListener" );
	    gotit = Class.forName( "java.awt.event.AdjustmentListener" );
	}
	catch( ClassNotFoundException ex ) {
	    return false;
	}
	return true;
    }   /* end checkRuntime() */

    /* ---------------------------------------------------------- */

    /**
     *	Returns identification string for this application.
     *	Includes a psuedo-version number.  String viewable through browser's
     *	&quot;About..&quot; dialog, but this author can't seem to find the
     *	right dialog...
     *	@return	String with program name and version number.
     */
    public String getAppletInfo() /* override */
    {
	return "BL2000 DAC and A/D controller / Z-World / Vers 0.05" ;
    }

    /**
     *	Returns list of <tt>PARAM</tt> keys this applet understands.
     */
    public String[][] getParameterInfo()	/* override */
    {
	String[][]	result = new String[3 /* =count */ ][3];

	result[0][0] = "SESSION_ID";
	result[0][1] = "int";
	result[0][2] = "Session ID cookie to pass to remote target.";

	result[1][0] = "CMD_PORT";
	result[1][1] = "int";
	result[1][2] = "TCP port where command interpreter is listening on host.";

	result[2][0] = "MAX_VOLTAGE";
	result[2][1] = "float";
	result[2][2] = "Maximum voltage can set on DAC channel.";

	return( result );
    }

    /* ---------------------------------------------------------- */

    /**
     *	Display messages for human.  outMessage() display above sliders.
     *  Usually this is system status.
     */
    public void outMessage( String text )
    {
	messageLine.setText( text );
    }
    /**
     *	Display messages for human.  outStatus() display below sliders.
     *	Usually this is value updates and transient information.
     *	@see	java.applet.showStatus
     */
    public void outStatus( String text )
    {
	statusLine.setText( text );
    }

    /* ---------------------------------------------------------- */

    /**  Create a scrollbar with a label to the leftside.  Label is based
     *   on the DAC channel we're to control.  Uses proper constraints.
     *   The slider is an input component, sending commands to remote.
     */
    private void makeControl( int channel )
    {
        /*  Scrollbar as slider with label... */
	Scrollbar    slider = new Scrollbar( Scrollbar.HORIZONTAL );

        slider.setValues( 0, 0, MIN_DAC_STEP_VALUE, MAX_DAC_STEP_VALUE+1 );
        slider.setUnitIncrement((MAX_DAC_STEP_VALUE-MIN_DAC_STEP_VALUE+1) / 8);
	slider.setBlockIncrement( slider.getUnitIncrement()/2 );

	Label lab = new Label( "DAC "+channel, Label.LEFT );
	myGridBag.setConstraints( lab, _labelConstraint );
	lab.setAlignment( Label.CENTER );
	add( lab );

	myGridBag.setConstraints( slider, _valueBarConstraint );
        add( slider );

	myAnalogController.addInputComponent( slider, channel );

    }   /* end makeControl() */


    /**  Create an output-only "value" bar with a choice component with a Choice
     *   component to the left-hand side.  
     */
    private void makeValueBar(int which)
    {
	Choice	ch = new Choice();
	int 	j;

	ch.addItem( "none" );
	for( j=0 ; j < MAX_ADC_CHANNELS ; ++j ) {
	    ch.addItem( "ADC "+ j );
	}

	myGridBag.setConstraints( ch, _labelConstraint );
	add( ch );
	// XXX- ch.addItemListener( myConn );

	ValueDisplay	vb = new ValueDisplay(this);
	// XXX- myConn.setAnaOutDisplay( vb );
	myGridBag.setConstraints( vb, _valueBarConstraint );
	add( vb );


    }   /* end makeValueBar() */

    /* ---------------------------------------------------------- */

    /*  Build three containts: _fullWidth stretches a component to fill
     *	a full row.  _label wraps tightly around and lives in first column.
     *  _valueBar Lives in the second column, and stretches to fill space.
     */
    private void presetConstraints()
    {
	setLayout( myGridBag );

	_fullWidthConstraint = new GridBagConstraints();
	_fullWidthConstraint.gridx = 1;
	_fullWidthConstraint.gridy = GridBagConstraints.RELATIVE;
	_fullWidthConstraint.gridwidth = GridBagConstraints.REMAINDER;
	_fullWidthConstraint.gridheight = 1;
	_fullWidthConstraint.weightx = 10.0;
	_fullWidthConstraint.weighty = 1.0;
	_fullWidthConstraint.fill = GridBagConstraints.BOTH;
	_fullWidthConstraint.insets = new Insets( 4, 1, 4, 1 );

	_labelConstraint = new GridBagConstraints();
	_labelConstraint.gridx = 1;
	_labelConstraint.gridy = GridBagConstraints.RELATIVE;
	_labelConstraint.gridwidth = 1;
	_labelConstraint.gridheight = 1;
	_labelConstraint.weightx = 0.0;
	_labelConstraint.weighty = 1.0;
	_labelConstraint.fill = GridBagConstraints.BOTH;
	_labelConstraint.insets = new Insets( 2,2,2,2 );

	_valueBarConstraint = new GridBagConstraints();
	_valueBarConstraint.gridx = 2;
	_valueBarConstraint.gridy = GridBagConstraints.RELATIVE;
	_valueBarConstraint.gridwidth = GridBagConstraints.REMAINDER;
	_valueBarConstraint.gridheight = 1;
	_valueBarConstraint.weightx = 10.0;
	_valueBarConstraint.weighty = 1.0;
	_valueBarConstraint.fill = GridBagConstraints.BOTH;
	_valueBarConstraint.insets = new Insets( 4, 4, 4, 4 );

    }   /* end presetConstraints() */

    /* ---------------------------------------------------------- */

    /*  If A/D code working, change this to "true" */
    final static boolean	SW_A_TO_D_WORKING = false;

    final static int    MIN_DAC_STEP_VALUE = 0;
    final static int    MAX_DAC_STEP_VALUE = 4095;
    static float	myMaxVolts;

    final static int 	MAX_ADC_CHANNELS = 8;

    /**  _fullWidth stretches a component to fill a full row. */
    static GridBagConstraints	_fullWidthConstraint;

    /**  _label wraps tightly around and lives in first column.  */
    static GridBagConstraints	_labelConstraint;

    /**  _valueBar Lives in the second column, and stretches to fill space. */
    static GridBagConstraints	_valueBarConstraint;

    GridBagLayout		myGridBag;

    Label		valueText;		/* Current voltage */
    Label               messageLine;            /* Above slider */
    Label               statusLine;             /* Below slider */

    RabbitNetworkClient  myConn;
    ValueListenerBoardUpdater  myAnalogController;

    /**  Session key sent as PARAM value to this applet. */
    int                 sessID = 0;

}   /* end class AnalogApplet */


/* ============================================================= */
/* ============================================================= */

/**	Some other class listens. 
 *	Keep the <code>ValueDisplay->myValue</code> and
 *	<code>ValueDisplay->myMax</code> consistent.
 *	Call <code>ValueDisplay()->repaint()</code> when something changes.
 */
class ValueDisplay extends Label
{
    /**
     *	Build a displaying element with some default value.
     *  Since we extends Label, must give it default value.
     *	Label text alignment is <tt>LEFT</tt>.
     */
    public ValueDisplay(AnalogApplet owner)
    {
	super( "---", Label.LEFT );
	myOwner = owner;

	myValue = 2.0f;
	myMax = 4.0f;
    }   /* end constructor */

    /* ---------------------------------------------------------- */

    public void paint( Graphics g )	/* override */
    {
	final int 	INSET = 1;
	final int 	BORDER = 1;
	Dimension d = getSize();
	Color	bgclr = getBackground();
	Color	fgclr = getForeground();
	Color	temp;
	float	ratio = 0.0f;
	int 	xoff;

	try {
	    ratio = myValue / myMax;
	    if( ratio > 1.0f ) { ratio = 1.0f; }
	    xoff = (int) (ratio * (d.width - 2 * INSET));

	    /*  Hue:	cool=160(blue), hot=0(red)
	     *  Saturation:  cool=40, hot=255.
	     *  Value:	cool=64, hot=200
	     */
	    temp = new Color(
			Color.HSBtoRGB(
				       (1.0f - ratio) * 0.63f,
				       0.156f + (ratio * 0.84F),
				       0.25f + (ratio * 0.75f) ) );

	} catch ( RuntimeException e ) {
	    g.drawString( " oppss..("+ ratio +")",
			  (int) (d.width * 0.40), (int)(d.height * 0.75) );
	    return ;
	}
	/*  Always clear our background.  It would be better to
	 *  have an offscreen area and then just blit...
	 */
	g.setColor( bgclr );
	g.fillRect( 0, 0, d.width, d.height );

	/*  Form a triangle that has one edge along the left-side
	 *  edge (top to bottom).  The point of the triangle lies

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?