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