1 /* 2 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.awt.dnd; 27 28 import java.awt.event.InputEvent; 29 import java.awt.Component; 30 import java.awt.Point; 31 32 import java.io.InvalidObjectException; 33 import java.util.Collections; 34 import java.util.TooManyListenersException; 35 import java.util.ArrayList; 36 37 import java.io.IOException; 38 import java.io.ObjectInputStream; 39 import java.io.ObjectOutputStream; 40 import java.io.Serializable; 41 42 /** 43 * The {@code DragGestureRecognizer} is an 44 * abstract base class for the specification 45 * of a platform-dependent listener that can be associated with a particular 46 * {@code Component} in order to 47 * identify platform-dependent drag initiating gestures. 48 * <p> 49 * The appropriate {@code DragGestureRecognizer} 50 * subclass instance is obtained from the 51 * {@link DragSource} associated with 52 * a particular {@code Component}, or from the {@code Toolkit} object via its 53 * {@link java.awt.Toolkit#createDragGestureRecognizer createDragGestureRecognizer()} 54 * method. 55 * <p> 56 * Once the {@code DragGestureRecognizer} 57 * is associated with a particular {@code Component} 58 * it will register the appropriate listener interfaces on that 59 * {@code Component} 60 * in order to track the input events delivered to the {@code Component}. 61 * <p> 62 * Once the {@code DragGestureRecognizer} identifies a sequence of events 63 * on the {@code Component} as a drag initiating gesture, it will notify 64 * its unicast {@code DragGestureListener} by 65 * invoking its 66 * {@link java.awt.dnd.DragGestureListener#dragGestureRecognized gestureRecognized()} 67 * method. 68 * <P> 69 * When a concrete {@code DragGestureRecognizer} 70 * instance detects a drag initiating 71 * gesture on the {@code Component} it is associated with, 72 * it fires a {@link DragGestureEvent} to 73 * the {@code DragGestureListener} registered on 74 * its unicast event source for {@code DragGestureListener} 75 * events. This {@code DragGestureListener} is responsible 76 * for causing the associated 77 * {@code DragSource} to start the Drag and Drop operation (if 78 * appropriate). 79 * 80 * @author Laurence P. G. Cable 81 * @see java.awt.dnd.DragGestureListener 82 * @see java.awt.dnd.DragGestureEvent 83 * @see java.awt.dnd.DragSource 84 */ 85 86 public abstract class DragGestureRecognizer implements Serializable { 87 88 private static final long serialVersionUID = 8996673345831063337L; 89 90 /** 91 * Construct a new {@code DragGestureRecognizer} 92 * given the {@code DragSource} to be used 93 * in this Drag and Drop operation, the {@code Component} 94 * this {@code DragGestureRecognizer} should "observe" 95 * for drag initiating gestures, the action(s) supported 96 * for this Drag and Drop operation, and the 97 * {@code DragGestureListener} to notify 98 * once a drag initiating gesture has been detected. 99 * 100 * @param ds the {@code DragSource} this 101 * {@code DragGestureRecognizer} 102 * will use to process the Drag and Drop operation 103 * 104 * @param c the {@code Component} 105 * this {@code DragGestureRecognizer} 106 * should "observe" the event stream to, 107 * in order to detect a drag initiating gesture. 108 * If this value is {@code null}, the 109 * {@code DragGestureRecognizer} 110 * is not associated with any {@code Component}. 111 * 112 * @param sa the set (logical OR) of the 113 * {@code DnDConstants} 114 * that this Drag and Drop operation will support 115 * 116 * @param dgl the {@code DragGestureRecognizer} 117 * to notify when a drag gesture is detected 118 * 119 * @throws IllegalArgumentException 120 * if ds is {@code null}. 121 */ 122 123 protected DragGestureRecognizer(DragSource ds, Component c, int sa, DragGestureListener dgl) { 124 super(); 125 126 if (ds == null) throw new IllegalArgumentException("null DragSource"); 127 128 dragSource = ds; 129 component = c; 130 sourceActions = sa & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK); 131 132 try { 133 if (dgl != null) addDragGestureListener(dgl); 134 } catch (TooManyListenersException tmle) { 135 // cant happen ... 136 } 137 } 138 139 /** 140 * Construct a new {@code DragGestureRecognizer} 141 * given the {@code DragSource} to be used in this 142 * Drag and Drop 143 * operation, the {@code Component} this 144 * {@code DragGestureRecognizer} should "observe" 145 * for drag initiating gestures, and the action(s) 146 * supported for this Drag and Drop operation. 147 * 148 * @param ds the {@code DragSource} this 149 * {@code DragGestureRecognizer} will use to 150 * process the Drag and Drop operation 151 * 152 * @param c the {@code Component} this 153 * {@code DragGestureRecognizer} should "observe" the event 154 * stream to, in order to detect a drag initiating gesture. 155 * If this value is {@code null}, the 156 * {@code DragGestureRecognizer} 157 * is not associated with any {@code Component}. 158 * 159 * @param sa the set (logical OR) of the {@code DnDConstants} 160 * that this Drag and Drop operation will support 161 * 162 * @throws IllegalArgumentException 163 * if ds is {@code null}. 164 */ 165 166 protected DragGestureRecognizer(DragSource ds, Component c, int sa) { 167 this(ds, c, sa, null); 168 } 169 170 /** 171 * Construct a new {@code DragGestureRecognizer} 172 * given the {@code DragSource} to be used 173 * in this Drag and Drop operation, and 174 * the {@code Component} this 175 * {@code DragGestureRecognizer} 176 * should "observe" for drag initiating gestures. 177 * 178 * @param ds the {@code DragSource} this 179 * {@code DragGestureRecognizer} 180 * will use to process the Drag and Drop operation 181 * 182 * @param c the {@code Component} 183 * this {@code DragGestureRecognizer} 184 * should "observe" the event stream to, 185 * in order to detect a drag initiating gesture. 186 * If this value is {@code null}, 187 * the {@code DragGestureRecognizer} 188 * is not associated with any {@code Component}. 189 * 190 * @throws IllegalArgumentException 191 * if ds is {@code null}. 192 */ 193 194 protected DragGestureRecognizer(DragSource ds, Component c) { 195 this(ds, c, DnDConstants.ACTION_NONE); 196 } 197 198 /** 199 * Construct a new {@code DragGestureRecognizer} 200 * given the {@code DragSource} to be used in this 201 * Drag and Drop operation. 202 * 203 * @param ds the {@code DragSource} this 204 * {@code DragGestureRecognizer} will 205 * use to process the Drag and Drop operation 206 * 207 * @throws IllegalArgumentException 208 * if ds is {@code null}. 209 */ 210 211 protected DragGestureRecognizer(DragSource ds) { 212 this(ds, null); 213 } 214 215 /** 216 * register this DragGestureRecognizer's Listeners with the Component 217 * 218 * subclasses must override this method 219 */ 220 221 protected abstract void registerListeners(); 222 223 /** 224 * unregister this DragGestureRecognizer's Listeners with the Component 225 * 226 * subclasses must override this method 227 */ 228 229 protected abstract void unregisterListeners(); 230 231 /** 232 * This method returns the {@code DragSource} 233 * this {@code DragGestureRecognizer} 234 * will use in order to process the Drag and Drop 235 * operation. 236 * 237 * @return the DragSource 238 */ 239 240 public DragSource getDragSource() { return dragSource; } 241 242 /** 243 * This method returns the {@code Component} 244 * that is to be "observed" by the 245 * {@code DragGestureRecognizer} 246 * for drag initiating gestures. 247 * 248 * @return The Component this DragGestureRecognizer 249 * is associated with 250 */ 251 252 public synchronized Component getComponent() { return component; } 253 254 /** 255 * set the Component that the DragGestureRecognizer is associated with 256 * 257 * registerListeners() and unregisterListeners() are called as a side 258 * effect as appropriate. 259 * 260 * @param c The {@code Component} or {@code null} 261 */ 262 263 public synchronized void setComponent(Component c) { 264 if (component != null && dragGestureListener != null) 265 unregisterListeners(); 266 267 component = c; 268 269 if (component != null && dragGestureListener != null) 270 registerListeners(); 271 } 272 273 /** 274 * This method returns an int representing the 275 * type of action(s) this Drag and Drop 276 * operation will support. 277 * 278 * @return the currently permitted source action(s) 279 */ 280 281 public synchronized int getSourceActions() { return sourceActions; } 282 283 /** 284 * This method sets the permitted source drag action(s) 285 * for this Drag and Drop operation. 286 * 287 * @param actions the permitted source drag action(s) 288 */ 289 290 public synchronized void setSourceActions(int actions) { 291 sourceActions = actions & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK); 292 } 293 294 /** 295 * This method returns the first event in the 296 * series of events that initiated 297 * the Drag and Drop operation. 298 * 299 * @return the initial event that triggered the drag gesture 300 */ 301 302 public InputEvent getTriggerEvent() { return events.isEmpty() ? null : events.get(0); } 303 304 /** 305 * Reset the Recognizer, if its currently recognizing a gesture, ignore 306 * it. 307 */ 308 309 public void resetRecognizer() { events.clear(); } 310 311 /** 312 * Register a new {@code DragGestureListener}. 313 * 314 * @param dgl the {@code DragGestureListener} to register 315 * with this {@code DragGestureRecognizer}. 316 * 317 * @throws java.util.TooManyListenersException if a 318 * {@code DragGestureListener} has already been added. 319 */ 320 321 public synchronized void addDragGestureListener(DragGestureListener dgl) throws TooManyListenersException { 322 if (dragGestureListener != null) 323 throw new TooManyListenersException(); 324 else { 325 dragGestureListener = dgl; 326 327 if (component != null) registerListeners(); 328 } 329 } 330 331 /** 332 * unregister the current DragGestureListener 333 * 334 * @param dgl the {@code DragGestureListener} to unregister 335 * from this {@code DragGestureRecognizer} 336 * 337 * @throws IllegalArgumentException if 338 * dgl is not (equal to) the currently registered {@code DragGestureListener}. 339 */ 340 341 public synchronized void removeDragGestureListener(DragGestureListener dgl) { 342 if (dragGestureListener == null || !dragGestureListener.equals(dgl)) 343 throw new IllegalArgumentException(); 344 else { 345 dragGestureListener = null; 346 347 if (component != null) unregisterListeners(); 348 } 349 } 350 351 /** 352 * Notify the DragGestureListener that a Drag and Drop initiating 353 * gesture has occurred. Then reset the state of the Recognizer. 354 * 355 * @param dragAction The action initially selected by the users gesture 356 * @param p The point (in Component coords) where the gesture originated 357 */ 358 protected synchronized void fireDragGestureRecognized(int dragAction, Point p) { 359 try { 360 if (dragGestureListener != null) { 361 dragGestureListener.dragGestureRecognized(new DragGestureEvent(this, dragAction, p, events)); 362 } 363 } finally { 364 events.clear(); 365 } 366 } 367 368 /** 369 * Listeners registered on the Component by this Recognizer shall record 370 * all Events that are recognized as part of the series of Events that go 371 * to comprise a Drag and Drop initiating gesture via this API. 372 * <P> 373 * This method is used by a {@code DragGestureRecognizer} 374 * implementation to add an {@code InputEvent} 375 * subclass (that it believes is one in a series 376 * of events that comprise a Drag and Drop operation) 377 * to the array of events that this 378 * {@code DragGestureRecognizer} maintains internally. 379 * 380 * @param awtie the {@code InputEvent} 381 * to add to this {@code DragGestureRecognizer}'s 382 * internal array of events. Note that {@code null} 383 * is not a valid value, and will be ignored. 384 */ 385 386 protected synchronized void appendEvent(InputEvent awtie) { 387 events.add(awtie); 388 } 389 390 /** 391 * Serializes this {@code DragGestureRecognizer}. This method first 392 * performs default serialization. Then, this object's 393 * {@code DragGestureListener} is written out if and only if it can be 394 * serialized. If not, {@code null} is written instead. 395 * 396 * @serialData The default serializable fields, in alphabetical order, 397 * followed by either a {@code DragGestureListener}, or 398 * {@code null}. 399 * @since 1.4 400 */ 401 private void writeObject(ObjectOutputStream s) throws IOException { 402 s.defaultWriteObject(); 403 404 s.writeObject(SerializationTester.test(dragGestureListener) 405 ? dragGestureListener : null); 406 } 407 408 /** 409 * Deserializes this {@code DragGestureRecognizer}. This method first 410 * performs default deserialization for all non-{@code transient} 411 * fields. This object's {@code DragGestureListener} is then 412 * deserialized as well by using the next object in the stream. 413 * 414 * @since 1.4 415 */ 416 @SuppressWarnings("unchecked") 417 private void readObject(ObjectInputStream s) 418 throws ClassNotFoundException, IOException 419 { 420 ObjectInputStream.GetField f = s.readFields(); 421 422 DragSource newDragSource = (DragSource)f.get("dragSource", null); 423 if (newDragSource == null) { 424 throw new InvalidObjectException("null DragSource"); 425 } 426 dragSource = newDragSource; 427 428 component = (Component)f.get("component", null); 429 sourceActions = f.get("sourceActions", 0) & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_LINK); 430 events = (ArrayList<InputEvent>)f.get("events", new ArrayList<>(1)); 431 432 dragGestureListener = (DragGestureListener)s.readObject(); 433 } 434 435 /* 436 * fields 437 */ 438 439 /** 440 * The {@code DragSource} 441 * associated with this 442 * {@code DragGestureRecognizer}. 443 * 444 * @serial 445 */ 446 protected DragSource dragSource; 447 448 /** 449 * The {@code Component} 450 * associated with this {@code DragGestureRecognizer}. 451 * 452 * @serial 453 */ 454 protected Component component; 455 456 /** 457 * The {@code DragGestureListener} 458 * associated with this {@code DragGestureRecognizer}. 459 */ 460 protected transient DragGestureListener dragGestureListener; 461 462 /** 463 * An {@code int} representing 464 * the type(s) of action(s) used 465 * in this Drag and Drop operation. 466 * 467 * @serial 468 */ 469 protected int sourceActions; 470 471 /** 472 * The list of events (in order) that 473 * the {@code DragGestureRecognizer} 474 * "recognized" as a "gesture" that triggers a drag. 475 * 476 * @serial 477 */ 478 protected ArrayList<InputEvent> events = new ArrayList<InputEvent>(1); 479 } --- EOF ---