/* * Slider.java - Slider control. * * 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.awt.*; import java.util.Random; import util.comm.*; public class Slider extends VJApplet implements Runnable { Thread updater = null; DataChannel rr = null; Image altImage = null; Graphics offscreen = null; final static int SLIDER_RESOLUTION = 2000; final static int HORIZONTAL = 1; final static int VERTICAL = 2; int myLength; int myOrientation; int currentPosition = 500; String myChannel; public void init() { myOrientation = HORIZONTAL; bgColor = getColor("bgcolor", Color.lightGray); brColor = bgColor.brighter(); dkColor = bgColor.darker(); String x = getParameter("orientation"); if (x != null) { if (x.compareTo("horizontal") == 0) { myOrientation = HORIZONTAL; myHeight = 21; myWidth = size().width; } else if (x.compareTo("vertical") == 0) { myOrientation = VERTICAL; myWidth = 21; myHeight = size().height; } else System.out.println("Bogus orientation."); } else { myWidth = size().width; myHeight = 21; myOrientation = HORIZONTAL; } myChannel = getParameter("datachannel"); setBackground(bgColor); } Color pad; void drawSquare(Graphics g, int x, int y, int size) { g.setColor(bgColor); g.fillRect(x+2, y+2, size, size); rect3D(g, x+3, y+3, size-2, size-2, 2, true); g.setColor(Color.black); } /** * Draw the left end cap on a horizontal slider. */ void leftCap(Graphics g, int x, int y) { drawSquare(g, x, y, capSize); for (int i = 0; i < 5; i++) { g.drawLine(x+8+i, 10 - i, x+8+i, 10+i); } } void rightCap(Graphics g, int x, int y) { drawSquare(g, x, y, capSize); for (int i = 0; i < 5; i++) { g.drawLine(x+9+i, 10 - (4 - i), x+9+i, 10 + (4 - i)); } } void topCap(Graphics g, int x, int y) { drawSquare(g, x, y, capSize); for (int i = 0; i < 5; i++) { g.drawLine(10 - i, y+8+i, 10 + i, y+8+i); } } void bottomCap(Graphics g, int x, int y) { drawSquare(g, x, y, capSize); for (int i = 0; i < 5; i++) { g.drawLine(10 - (4-i), y+8+i, 10 + (4-i), y+8+i); } } int capSize = 17; int elevatorSize = 17; /** * Paint the elevator on to the slider. Note that the computation for * the minimum and maximum positions overlap the end caps by one pixel. * this is done to leave a single pixel line between the cap and the * elevator when fully extended. */ void elevator(Graphics g) { int minPos, maxPos, pos; minPos = capSize - 1; maxPos = ((myOrientation == HORIZONTAL) ? myWidth : myHeight) - capSize - 2 - elevatorSize; pos = (((maxPos - minPos) * currentPosition) / SLIDER_RESOLUTION) + minPos; if (myOrientation == HORIZONTAL) { drawSquare(g, pos, 0, elevatorSize); } else { drawSquare(g, 0, pos, elevatorSize); } } public void paint(Graphics g) { g.setColor(bgColor); g.fillRect(0, 0, myWidth, myHeight); g.setColor(Color.black); rect3D(g, 0, 0, myWidth, myHeight, 2, false); if (myOrientation == HORIZONTAL) { leftCap(g, 0, 0); rightCap(g, myWidth - 21, 0); } else { topCap(g, 0, 0); bottomCap(g, 0, myHeight - 21); } elevator(g); } public void start() { System.out.println("Slider:: start()"); updater = new Thread(this); rr = DataChannel.getChannel(myChannel, updater, 8); updater.start(); } public void stop() { rr.releaseChannel(updater); updater = null; } public void run() { System.out.println("Slider thread running..."); while (true) { try { currentPosition = ((Integer) rr.getValue()).intValue(); } catch (DataChannelOverrun e) { System.out.println("Slider: OVERRUN!"); } catch (DataChannelShutdown e) { System.out.println("Slider thread shutting down."); return; } catch (DataChannelTimeout e) { continue; } catch (DataChannelException ee) { System.out.println("We're dead."); ee.printStackTrace(); } currentPosition = Math.max(0, currentPosition); currentPosition = Math.min(SLIDER_RESOLUTION, currentPosition); repaint(); } } /* * ****** * Slider User Interface Mechanics * ****** */ /** Calculate a new result value given the x and y coordinates of the mouse */ void newPosition(int x, int y) { int loVal, hiVal, midRange, sample; // zero is when the midpoint of the elevator is against the bottom loVal = 18 + (elevatorSize/2); // lowest value hiVal = ((myOrientation == HORIZONTAL) ? myWidth : myHeight) - 18 - (elevatorSize/2); midRange = hiVal - loVal; sample = Math.max(((myOrientation == HORIZONTAL) ? x : y), loVal); sample = Math.min(sample, hiVal); rr.putValue(new Integer(((sample - loVal) * SLIDER_RESOLUTION) / midRange)); } public boolean mouseDown(Event ev, int x, int y) { int result = currentPosition; if (((myOrientation == HORIZONTAL) && ((x <= 20) && (x >= 0))) || (((myOrientation == VERTICAL) && (y <= 20) && (y >= 0)))) { result -= (SLIDER_RESOLUTION * .025); if (result < 0) result = 0; rr.putValue(new Integer(result)); return true; } if (((myOrientation == HORIZONTAL) && ((x >= (myWidth - 20)) && (x <= myWidth))) || (((myOrientation == VERTICAL) && (y >= (myHeight - 20)) && (y <= myHeight)))) { result += (SLIDER_RESOLUTION * .025); if (result > SLIDER_RESOLUTION) result = SLIDER_RESOLUTION; rr.putValue(new Integer(result)); return true; } return true; } public boolean mouseDrag(Event ev, int x, int y) { // ignore if it is inside the end caps if ((myOrientation == HORIZONTAL) && ((y <= myHeight) && (y >= 0)) && ( ((x <= (capSize + 2)) && (x >= 0)) || ((x >= (myWidth - capSize - 2)) && (x <= myWidth)) ) ) { return true; } if ((myOrientation == VERTICAL) && ((x <= myHeight) && (x >= 0)) && ( ((y <= (capSize + 2)) && (y >= 0)) || ((y >= (myHeight - capSize - 2)) && (y <= myHeight)) ) ) { return true; } newPosition(x, y); return true; } }