1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1999-2000 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 import java.awt.*; 28 import java.awt.event.*; 29 30 /** 31 * Creates a panel with two buttons (+ and - side by side on it). The 32 * panel registers a DCListener with it that gets notified whenever 33 * these butons are clicked. <bold>The buttons may also be kept continously 34 * pressed for faster increments/decrements.</bold> 35 * <para> 36 * On a single click of the button, the listener is notified to 37 * increment/decrement itself by a small amount. When the button is kept 38 * pressed the following notifications are sent out for larger 39 * increments/decrements. (It is up to the listener to decide the 40 * increment/decrement corresponding to large/small.) Moreover, these 41 * notifications will be sent out much faster if the button is kept 42 * pressed. 43 */ 44 45 // The panel waits for a period of BIG_SLEEP_TIME before the faster 46 // increments are sent out. They, in turn, are sent out after 47 // intervals of SMALL_SLEEP_TIME. Therfore, an instance of this class 48 // is associated with 2 timers - a longer one that starts off and then 49 // schedules the shorter one. The shorter one keeps scheduling itself 50 // every time it wakes up. 51 52 public class DCPanel extends Panel { 53 54 private Button plusButton; 55 private Button minusButton; 56 57 private DCListener listener = null; 58 59 private Timer bigTimer; 60 private Timer smallTimer; 61 62 private static int BIG_SLEEP_TIME = 1000; 63 private static int SMALL_SLEEP_TIME = 100; 64 65 private boolean incrementFlag; 66 67 public DCPanel() { 68 69 setLayout(new GridLayout(1, 2)); 70 71 bigTimer = new BigTimer(); 72 smallTimer = new SmallTimer(); 73 74 bigTimer.start(); 75 smallTimer.start(); 76 77 plusButton = new DCButton("+"); 78 minusButton = new DCButton("-"); 79 80 add(plusButton); 81 add(minusButton); 82 83 } 84 85 /** 86 * Ensures that this component is not brought into focus by 87 * tabbing. This prevents the tab focus from moving in here instead 88 * of going to a text field. 89 * @return false always. 90 */ 91 public boolean isFocusable() { 92 return false; 93 } 94 95 /** 96 * Sets the listener for this tab. 97 * @param listener the DCListener that needs to be notified when the 98 * buttons on this panel are pressed. 99 * @return the old listener 100 */ 101 public DCListener setListener(DCListener listener) { 102 DCListener oldListener = this.listener; 103 this.listener = listener; 104 return oldListener; 105 } 106 107 /** 108 * Removes the listener when it no longer need to be notified. 109 * @return the old listener 110 */ 111 public DCListener removeListener() { 112 return setListener(null); 113 } 114 115 /** 116 * Kicks the times into action. Is called when a button is pressed. 117 */ 118 private void startAction() { 119 bigTimer.request(); 120 } 121 122 /** 123 * Stops the timers. Is called when a button is released. 124 */ 125 private void stopAction() { 126 smallTimer.cancel(); 127 bigTimer.cancel(); 128 } 129 130 /** 131 * Notifies the listener about whether to increment or decrement and 132 * by how much. 133 * @param bigFlag true if the listener needs to increment/decrement 134 * by a large amount, false otherwise. 135 */ 136 private void informListener(boolean bigFlag) { 137 // System.out.println("DCPanel.informListener: " + bigFlag); 138 139 if (listener != null) { 140 141 if (bigFlag) { 142 // request a big change 143 if (incrementFlag) 144 listener.bigIncrement(); 145 else 146 listener.bigDecrement(); 147 } else { 148 // request a small change 149 if (incrementFlag) 150 listener.increment(); 151 else 152 listener.decrement(); 153 } 154 155 } 156 157 } // informListener 158 159 160 // *********************************************** 161 // I N N E R C L A S S E S F O L L O W 162 // *********************************************** 163 164 /** 165 * A timer class since java does not have one. 166 */ 167 private abstract class Timer extends Thread { 168 private boolean running = false; 169 170 /** 171 * Sleeps till the timer's services are requested using wait() and 172 * notify(). Then it does its task and goes back to sleep. And 173 * loops forever like this. 174 */ 175 public void run() { 176 while (true) { 177 try { 178 synchronized (this) { 179 running = false; 180 // Wait till the timer is required 181 wait(); 182 running = true; 183 } 184 doTask(); 185 } catch (InterruptedException e) {} 186 } // while loop 187 } // run method 188 189 protected void doTask() {} // bug in java workshop 190 191 /** 192 * Wakes up the timer. 193 */ 194 public synchronized void request() { 195 notify(); 196 } 197 198 /** 199 * Cancels the timer if it is running. 200 */ 201 public void cancel() { 202 if (running) { 203 interrupt(); 204 } 205 } 206 207 }// class Timer 208 209 /** 210 * The first stage of timer - is a longer timer. Wait to see if the 211 * user really wants to amek the increments/decrements go by fast. 212 */ 213 private class BigTimer extends Timer { 214 215 /** 216 * Sleep for the long amount of time. Then inform the listener 217 * to have a bigIncrement/bigDecrement. After that, your job is 218 * done, schedule the smaller (faster) timer from this point on. 219 */ 220 protected void doTask() { 221 try { 222 sleep(BIG_SLEEP_TIME); 223 informListener(true); 224 smallTimer.request(); 225 } catch (InterruptedException e) { 226 informListener(false); 227 } 228 } 229 230 } // class BigTimer 231 232 233 /** 234 * The second stage of timers. This timer keeps rescheduling itself 235 * everytime it wakes up. In between this, it sends a notification 236 * to the listener to do a big Increment/Decrement. 237 */ 238 private class SmallTimer extends Timer { 239 240 protected void doTask() { 241 try { 242 // loop forever and keep rescheduling yourself 243 while (true) { 244 sleep(SMALL_SLEEP_TIME); 245 informListener(true); 246 } 247 } catch (InterruptedException e) {} 248 } // doTask method 249 250 } // class SmallTimer 251 252 /** 253 * A mouse listener to detect when a button has been 254 * pressed/released. One instance of this is bound to the plus 255 * button and the other instance to the minus button. 256 */ 257 private class DCMouseListener extends MouseAdapter { 258 private boolean plusOrMinus; 259 260 /** 261 * Constructor for DCMouseListener. 262 * @param plusOrMinus true if this is a listener for the plus 263 * button, false if it is for the minus button. 264 */ 265 public DCMouseListener(boolean plusOrMinus) { 266 this.plusOrMinus = plusOrMinus; 267 } 268 269 /** 270 * Kicks in when the mouse is pressed. 271 */ 272 public void mousePressed(MouseEvent e) { 273 incrementFlag = plusOrMinus; 274 DCPanel.this.startAction(); 275 } 276 277 /** 278 * Kicks in when the mouse is released. 279 */ 280 public void mouseReleased(MouseEvent e) { 281 incrementFlag = plusOrMinus; 282 DCPanel.this.stopAction(); 283 } 284 } 285 286 /** 287 * The button used by this DCPanel. 288 */ 289 private class DCButton extends Button { 290 public DCButton(String text) { 291 super(text); 292 if (text.equals("+")) 293 addMouseListener(new DCMouseListener(true)); 294 else 295 addMouseListener(new DCMouseListener(false)); 296 } 297 298 /** 299 * Make the button non-focus traversable so that it cannot be 300 * tabbed in to. 301 */ 302 public boolean isFocusable() { 303 return false; 304 } 305 306 } // DCButton 307 308 309 /** 310 * Test method for DCPanel class to see appearance. 311 */ 312 public static void main(String args[]) { 313 Frame f = new Frame("Testing DCPanel"); 314 f.add(new DCPanel()); 315 f.setBounds(new Rectangle(100, 100, 100, 100)); 316 f.setVisible(true); 317 } 318 319 } 320