/* * SimpleNumeric.java - Numeric indicator applet. * * Copyright (c) 1996 Chuck McManis, All Rights Reserved. * * Permission to use, copy, modify, and distribute this software * and its documentation for NON-COMMERCIAL purposes and without * fee is hereby granted provided that this copyright notice * appears in all copies. * * CHUCK MCMANIS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. CHUCK MCMANIS * SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT * OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. */ import java.applet.Applet; import java.awt.*; import util.comm.*; /** * This is a very simple "consumer" class. It consumes long integer values and * displays them in a "sunken" box. */ public class SimpleNumeric extends Applet implements Runnable { Thread updater = null; long currentValue = 0; DataChannel myChannel = null; double minValue, maxValue; double multiple = 1; Image altImage = null; Graphics offscreen = null; Dimension altSize = new Dimension(0, 0); Font numberFont = new Font("Courier", Font.BOLD, 14); Color bkGround, dkColor, brColor; /** * Return a Color value from the parameter list. Colors are * specified using HEX notation as in NetScape. If there is any * error, return the defaultColor instead. */ Color getColor(String name, Color defaultColor) { String x = getParameter(name); if (x != null) { if (x.startsWith("#")) { int z; try { z = Integer.parseInt(x.substring(1), 16); return( new Color( (z >>> 16) & 0xff, (z >>> 8) & 0xff, (z & 0xff))); } catch (NumberFormatException e) { return defaultColor; } } } return defaultColor; } /** * This helper function returns a "double" value from a passed * applet parameter. */ double getDouble(String parmName, double defaultValue) { double res; String val = getParameter(parmName); if (val == null) return defaultValue; try { res = (Double.valueOf(val)).doubleValue(); } catch (NumberFormatException e) { res = defaultValue; } return res; } /** * Get the name of our input channel. */ String getChannel(String name, String defaultName) { String x = getParameter(name); return ((x == null) ? defaultName : x); } String channelName; /** * Initialize the applet, parse our parameters. */ public void init() { String x; bkGround = getColor("bgcolor", Color.lightGray); brColor = bkGround.brighter(); dkColor = bkGround.darker(); channelName = getChannel("datachannel", "BOGUS"); minValue = getDouble("minvalue", 0.0); maxValue = getDouble("maxvalue", 100.0); } /** * double buffered version of update for smooth display. */ public void update(Graphics g) { if (offscreen == null) { altImage = createImage(size().width, size().height); offscreen = altImage.getGraphics(); altSize.width = size().width; altSize.height = size().height; } paint(offscreen); g.drawImage(altImage, 0, 0, null); } char digits[]; /** * Draw the current value in a sunken box on the screen. */ public void paint(Graphics g) { FontMetrics fm; long tempValue; int actualWidth, actualHeight; int offX, offY; int tmpvalue; g.setColor(bkGround); g.fillRect(0, 0, altSize.width, altSize.height); g.setFont(numberFont); fm = g.getFontMetrics(); int charWidth = fm.stringWidth("0"); int numChars = (size().width - 4)/charWidth; if ((digits == null) || (digits.length != numChars)) { digits = new char[numChars]; } actualWidth = (charWidth * numChars) + 4; actualHeight = fm.getHeight() + 4; offX = altSize.width - (actualWidth + 1); offY = (altSize.height - actualHeight) / 2; // draw the back drop (black) g.setColor(Color.black); g.fillRect(offX, offY, actualWidth, actualHeight); // draw a simple 3D rectangle "look" g.setColor(dkColor); g.drawLine(offX, offY, offX+actualWidth, offY); g.drawLine(offX, offY, offX, offY+actualHeight); g.setColor(brColor); g.drawLine(offX+actualWidth, offY, offX+actualWidth, offY+actualHeight); g.drawLine(offX, offY+actualHeight, offX+actualWidth, offY+actualHeight); // draw the numbers. g.setColor(Color.white); for (int i = 0; i < digits.length; i++) digits[i] = ' '; digits[digits.length - 1] = '0'; tempValue = currentValue; for (int i = (digits.length - 1); i >= 0; i--) { if (tempValue == 0) { if (currentValue < 0) digits[i] = '-'; break; } digits[i] = (char) ('0' + Math.abs(tempValue - ((tempValue / 10) * 10))); tempValue = tempValue / 10; } g.drawChars(digits, 0, digits.length, offX+2, fm.getAscent() + offY + 2); } /** * Create a new thread to monitor the data channel and start it. */ public void start() { updater = new Thread(this); myChannel = DataChannel.getChannel(channelName, updater, 4); updater.start(); } /** * Shutdown the thread that is monitoring the data channel. */ public void stop() { myChannel.releaseChannel(updater); updater = null; } /** * Implement runnable, in this thread we just read values and * call repaint when they come in. */ public void run() { double x = 0; while (Thread.currentThread() == updater) { repaint(); try { x = ((Integer)myChannel.getValue()).doubleValue(); } catch (DataChannelOverrun e) { System.out.println("Numeric: OVERRUN!"); } catch (DataChannelShutdown e) { return; } catch (DataChannelTimeout e) { continue; } catch (DataChannelException ee) { System.out.println("We're dead."); ee.printStackTrace(); } currentValue = (long) (((((maxValue - minValue) * x) / 2000.0) + minValue) * multiple); } } }