1 /* 2 * Copyright (c) 1997, 2015, 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.util.TooManyListenersException; 29 30 import java.io.IOException; 31 import java.io.ObjectInputStream; 32 import java.io.ObjectOutputStream; 33 import java.io.Serializable; 34 35 import java.awt.Component; 36 import java.awt.Dimension; 37 import java.awt.GraphicsEnvironment; 38 import java.awt.HeadlessException; 39 import java.awt.Insets; 40 import java.awt.Point; 41 import java.awt.Rectangle; 42 import java.awt.Toolkit; 43 import java.awt.event.ActionEvent; 44 import java.awt.event.ActionListener; 45 import java.awt.datatransfer.FlavorMap; 46 import java.awt.datatransfer.SystemFlavorMap; 47 import javax.swing.Timer; 48 import java.awt.peer.ComponentPeer; 49 import java.awt.peer.LightweightPeer; 50 import java.awt.dnd.peer.DropTargetPeer; 51 52 import sun.awt.AWTAccessor; 53 import sun.awt.AWTAccessor.ComponentAccessor; 54 55 56 /** 57 * The <code>DropTarget</code> is associated 58 * with a <code>Component</code> when that <code>Component</code> 59 * wishes 60 * to accept drops during Drag and Drop operations. 61 * <P> 62 * Each 63 * <code>DropTarget</code> is associated with a <code>FlavorMap</code>. 64 * The default <code>FlavorMap</code> hereafter designates the 65 * <code>FlavorMap</code> returned by <code>SystemFlavorMap.getDefaultFlavorMap()</code>. 66 * 67 * @since 1.2 68 */ 69 70 public class DropTarget implements DropTargetListener, Serializable { 71 72 private static final long serialVersionUID = -6283860791671019047L; 73 74 /** 75 * Creates a new DropTarget given the <code>Component</code> 76 * to associate itself with, an <code>int</code> representing 77 * the default acceptable action(s) to 78 * support, a <code>DropTargetListener</code> 79 * to handle event processing, a <code>boolean</code> indicating 80 * if the <code>DropTarget</code> is currently accepting drops, and 81 * a <code>FlavorMap</code> to use (or null for the default <CODE>FlavorMap</CODE>). 82 * <P> 83 * The Component will receive drops only if it is enabled. 84 * @param c The <code>Component</code> with which this <code>DropTarget</code> is associated 85 * @param ops The default acceptable actions for this <code>DropTarget</code> 86 * @param dtl The <code>DropTargetListener</code> for this <code>DropTarget</code> 87 * @param act Is the <code>DropTarget</code> accepting drops. 88 * @param fm The <code>FlavorMap</code> to use, or null for the default <CODE>FlavorMap</CODE> 89 * @exception HeadlessException if GraphicsEnvironment.isHeadless() 90 * returns true 91 * @see java.awt.GraphicsEnvironment#isHeadless 92 */ 93 public DropTarget(Component c, int ops, DropTargetListener dtl, 94 boolean act, FlavorMap fm) 95 throws HeadlessException 96 { 97 if (GraphicsEnvironment.isHeadless()) { 98 throw new HeadlessException(); 99 } 100 101 component = c; 102 103 setDefaultActions(ops); 104 105 if (dtl != null) try { 106 addDropTargetListener(dtl); 107 } catch (TooManyListenersException tmle) { 108 // do nothing! 109 } 110 111 if (c != null) { 112 c.setDropTarget(this); 113 setActive(act); 114 } 115 116 if (fm != null) { 117 flavorMap = fm; 118 } else { 119 flavorMap = SystemFlavorMap.getDefaultFlavorMap(); 120 } 121 } 122 123 /** 124 * Creates a <code>DropTarget</code> given the <code>Component</code> 125 * to associate itself with, an <code>int</code> representing 126 * the default acceptable action(s) 127 * to support, a <code>DropTargetListener</code> 128 * to handle event processing, and a <code>boolean</code> indicating 129 * if the <code>DropTarget</code> is currently accepting drops. 130 * <P> 131 * The Component will receive drops only if it is enabled. 132 * @param c The <code>Component</code> with which this <code>DropTarget</code> is associated 133 * @param ops The default acceptable actions for this <code>DropTarget</code> 134 * @param dtl The <code>DropTargetListener</code> for this <code>DropTarget</code> 135 * @param act Is the <code>DropTarget</code> accepting drops. 136 * @exception HeadlessException if GraphicsEnvironment.isHeadless() 137 * returns true 138 * @see java.awt.GraphicsEnvironment#isHeadless 139 */ 140 public DropTarget(Component c, int ops, DropTargetListener dtl, 141 boolean act) 142 throws HeadlessException 143 { 144 this(c, ops, dtl, act, null); 145 } 146 147 /** 148 * Creates a <code>DropTarget</code>. 149 * @exception HeadlessException if GraphicsEnvironment.isHeadless() 150 * returns true 151 * @see java.awt.GraphicsEnvironment#isHeadless 152 */ 153 public DropTarget() throws HeadlessException { 154 this(null, DnDConstants.ACTION_COPY_OR_MOVE, null, true, null); 155 } 156 157 /** 158 * Creates a <code>DropTarget</code> given the <code>Component</code> 159 * to associate itself with, and the <code>DropTargetListener</code> 160 * to handle event processing. 161 * <P> 162 * The Component will receive drops only if it is enabled. 163 * @param c The <code>Component</code> with which this <code>DropTarget</code> is associated 164 * @param dtl The <code>DropTargetListener</code> for this <code>DropTarget</code> 165 * @exception HeadlessException if GraphicsEnvironment.isHeadless() 166 * returns true 167 * @see java.awt.GraphicsEnvironment#isHeadless 168 */ 169 public DropTarget(Component c, DropTargetListener dtl) 170 throws HeadlessException 171 { 172 this(c, DnDConstants.ACTION_COPY_OR_MOVE, dtl, true, null); 173 } 174 175 /** 176 * Creates a <code>DropTarget</code> given the <code>Component</code> 177 * to associate itself with, an <code>int</code> representing 178 * the default acceptable action(s) to support, and a 179 * <code>DropTargetListener</code> to handle event processing. 180 * <P> 181 * The Component will receive drops only if it is enabled. 182 * @param c The <code>Component</code> with which this <code>DropTarget</code> is associated 183 * @param ops The default acceptable actions for this <code>DropTarget</code> 184 * @param dtl The <code>DropTargetListener</code> for this <code>DropTarget</code> 185 * @exception HeadlessException if GraphicsEnvironment.isHeadless() 186 * returns true 187 * @see java.awt.GraphicsEnvironment#isHeadless 188 */ 189 public DropTarget(Component c, int ops, DropTargetListener dtl) 190 throws HeadlessException 191 { 192 this(c, ops, dtl, true); 193 } 194 195 /** 196 * Note: this interface is required to permit the safe association 197 * of a DropTarget with a Component in one of two ways, either: 198 * <code> component.setDropTarget(droptarget); </code> 199 * or <code> droptarget.setComponent(component); </code> 200 * <P> 201 * The Component will receive drops only if it is enabled. 202 * @param c The new <code>Component</code> this <code>DropTarget</code> 203 * is to be associated with. 204 */ 205 206 public synchronized void setComponent(Component c) { 207 if (component == c || component != null && component.equals(c)) 208 return; 209 210 Component old; 211 ComponentPeer oldPeer = null; 212 213 if ((old = component) != null) { 214 clearAutoscroll(); 215 216 component = null; 217 218 if (componentPeer != null) { 219 oldPeer = componentPeer; 220 removeNotify(componentPeer); 221 } 222 223 old.setDropTarget(null); 224 225 } 226 227 if ((component = c) != null) try { 228 c.setDropTarget(this); 229 } catch (Exception e) { // undo the change 230 if (old != null) { 231 old.setDropTarget(this); 232 addNotify(oldPeer); 233 } 234 } 235 } 236 237 /** 238 * Gets the <code>Component</code> associated 239 * with this <code>DropTarget</code>. 240 * 241 * @return the current <code>Component</code> 242 */ 243 244 public synchronized Component getComponent() { 245 return component; 246 } 247 248 /** 249 * Sets the default acceptable actions for this <code>DropTarget</code> 250 * 251 * @param ops the default actions 252 * @see java.awt.dnd.DnDConstants 253 */ 254 255 public void setDefaultActions(int ops) { 256 getDropTargetContext().setTargetActions(ops & (DnDConstants.ACTION_COPY_OR_MOVE | DnDConstants.ACTION_REFERENCE)); 257 } 258 259 /* 260 * Called by DropTargetContext.setTargetActions() 261 * with appropriate synchronization. 262 */ 263 void doSetDefaultActions(int ops) { 264 actions = ops; 265 } 266 267 /** 268 * Gets an <code>int</code> representing the 269 * current action(s) supported by this <code>DropTarget</code>. 270 * 271 * @return the current default actions 272 */ 273 274 public int getDefaultActions() { 275 return actions; 276 } 277 278 /** 279 * Sets the DropTarget active if <code>true</code>, 280 * inactive if <code>false</code>. 281 * 282 * @param isActive sets the <code>DropTarget</code> (in)active. 283 */ 284 285 public synchronized void setActive(boolean isActive) { 286 if (isActive != active) { 287 active = isActive; 288 } 289 290 if (!active) clearAutoscroll(); 291 } 292 293 /** 294 * Reports whether or not 295 * this <code>DropTarget</code> 296 * is currently active (ready to accept drops). 297 * 298 * @return <CODE>true</CODE> if active, <CODE>false</CODE> if not 299 */ 300 301 public boolean isActive() { 302 return active; 303 } 304 305 /** 306 * Adds a new <code>DropTargetListener</code> (UNICAST SOURCE). 307 * 308 * @param dtl The new <code>DropTargetListener</code> 309 * 310 * @throws TooManyListenersException if a 311 * <code>DropTargetListener</code> is already added to this 312 * <code>DropTarget</code>. 313 */ 314 315 public synchronized void addDropTargetListener(DropTargetListener dtl) throws TooManyListenersException { 316 if (dtl == null) return; 317 318 if (equals(dtl)) throw new IllegalArgumentException("DropTarget may not be its own Listener"); 319 320 if (dtListener == null) 321 dtListener = dtl; 322 else 323 throw new TooManyListenersException(); 324 } 325 326 /** 327 * Removes the current <code>DropTargetListener</code> (UNICAST SOURCE). 328 * 329 * @param dtl the DropTargetListener to deregister. 330 */ 331 332 public synchronized void removeDropTargetListener(DropTargetListener dtl) { 333 if (dtl != null && dtListener != null) { 334 if(dtListener.equals(dtl)) 335 dtListener = null; 336 else 337 throw new IllegalArgumentException("listener mismatch"); 338 } 339 } 340 341 /** 342 * Calls <code>dragEnter</code> on the registered 343 * <code>DropTargetListener</code> and passes it 344 * the specified <code>DropTargetDragEvent</code>. 345 * Has no effect if this <code>DropTarget</code> 346 * is not active. 347 * 348 * @param dtde the <code>DropTargetDragEvent</code> 349 * 350 * @throws NullPointerException if this <code>DropTarget</code> 351 * is active and <code>dtde</code> is <code>null</code> 352 * 353 * @see #isActive 354 */ 355 public synchronized void dragEnter(DropTargetDragEvent dtde) { 356 isDraggingInside = true; 357 358 if (!active) return; 359 360 if (dtListener != null) { 361 dtListener.dragEnter(dtde); 362 } else 363 dtde.getDropTargetContext().setTargetActions(DnDConstants.ACTION_NONE); 364 365 initializeAutoscrolling(dtde.getLocation()); 366 } 367 368 /** 369 * Calls <code>dragOver</code> on the registered 370 * <code>DropTargetListener</code> and passes it 371 * the specified <code>DropTargetDragEvent</code>. 372 * Has no effect if this <code>DropTarget</code> 373 * is not active. 374 * 375 * @param dtde the <code>DropTargetDragEvent</code> 376 * 377 * @throws NullPointerException if this <code>DropTarget</code> 378 * is active and <code>dtde</code> is <code>null</code> 379 * 380 * @see #isActive 381 */ 382 public synchronized void dragOver(DropTargetDragEvent dtde) { 383 if (!active) return; 384 385 if (dtListener != null && active) dtListener.dragOver(dtde); 386 387 updateAutoscroll(dtde.getLocation()); 388 } 389 390 /** 391 * Calls <code>dropActionChanged</code> on the registered 392 * <code>DropTargetListener</code> and passes it 393 * the specified <code>DropTargetDragEvent</code>. 394 * Has no effect if this <code>DropTarget</code> 395 * is not active. 396 * 397 * @param dtde the <code>DropTargetDragEvent</code> 398 * 399 * @throws NullPointerException if this <code>DropTarget</code> 400 * is active and <code>dtde</code> is <code>null</code> 401 * 402 * @see #isActive 403 */ 404 public synchronized void dropActionChanged(DropTargetDragEvent dtde) { 405 if (!active) return; 406 407 if (dtListener != null) dtListener.dropActionChanged(dtde); 408 409 updateAutoscroll(dtde.getLocation()); 410 } 411 412 /** 413 * Calls <code>dragExit</code> on the registered 414 * <code>DropTargetListener</code> and passes it 415 * the specified <code>DropTargetEvent</code>. 416 * Has no effect if this <code>DropTarget</code> 417 * is not active. 418 * <p> 419 * This method itself does not throw any exception 420 * for null parameter but for exceptions thrown by 421 * the respective method of the listener. 422 * 423 * @param dte the <code>DropTargetEvent</code> 424 * 425 * @see #isActive 426 */ 427 public synchronized void dragExit(DropTargetEvent dte) { 428 isDraggingInside = false; 429 430 if (!active) return; 431 432 if (dtListener != null && active) dtListener.dragExit(dte); 433 434 clearAutoscroll(); 435 } 436 437 /** 438 * Calls <code>drop</code> on the registered 439 * <code>DropTargetListener</code> and passes it 440 * the specified <code>DropTargetDropEvent</code> 441 * if this <code>DropTarget</code> is active. 442 * 443 * @param dtde the <code>DropTargetDropEvent</code> 444 * 445 * @throws NullPointerException if <code>dtde</code> is null 446 * and at least one of the following is true: this 447 * <code>DropTarget</code> is not active, or there is 448 * no a <code>DropTargetListener</code> registered. 449 * 450 * @see #isActive 451 */ 452 public synchronized void drop(DropTargetDropEvent dtde) { 453 isDraggingInside = false; 454 455 clearAutoscroll(); 456 457 if (dtListener != null && active) 458 dtListener.drop(dtde); 459 else { // we shouldn't get here ... 460 dtde.rejectDrop(); 461 } 462 } 463 464 /** 465 * Gets the <code>FlavorMap</code> 466 * associated with this <code>DropTarget</code>. 467 * If no <code>FlavorMap</code> has been set for this 468 * <code>DropTarget</code>, it is associated with the default 469 * <code>FlavorMap</code>. 470 * 471 * @return the FlavorMap for this DropTarget 472 */ 473 474 public FlavorMap getFlavorMap() { return flavorMap; } 475 476 /** 477 * Sets the <code>FlavorMap</code> associated 478 * with this <code>DropTarget</code>. 479 * 480 * @param fm the new <code>FlavorMap</code>, or null to 481 * associate the default FlavorMap with this DropTarget. 482 */ 483 484 public void setFlavorMap(FlavorMap fm) { 485 flavorMap = fm == null ? SystemFlavorMap.getDefaultFlavorMap() : fm; 486 } 487 488 /** 489 * Notify the DropTarget that it has been associated with a Component 490 * 491 ********************************************************************** 492 * This method is usually called from java.awt.Component.addNotify() of 493 * the Component associated with this DropTarget to notify the DropTarget 494 * that a ComponentPeer has been associated with that Component. 495 * 496 * Calling this method, other than to notify this DropTarget of the 497 * association of the ComponentPeer with the Component may result in 498 * a malfunction of the DnD system. 499 ********************************************************************** 500 * 501 * @param peer The Peer of the Component we are associated with! 502 * 503 */ 504 505 public void addNotify(ComponentPeer peer) { 506 if (peer == componentPeer) return; 507 508 componentPeer = peer; 509 final ComponentAccessor acc = AWTAccessor.getComponentAccessor(); 510 511 for (Component c = component; 512 c != null && peer instanceof LightweightPeer; c = c.getParent()) { 513 peer = acc.getPeer(c); 514 } 515 516 if (peer instanceof DropTargetPeer) { 517 nativePeer = peer; 518 ((DropTargetPeer)peer).addDropTarget(this); 519 } else { 520 nativePeer = null; 521 } 522 } 523 524 /** 525 * Notify the DropTarget that it has been disassociated from a Component 526 * 527 ********************************************************************** 528 * This method is usually called from java.awt.Component.removeNotify() of 529 * the Component associated with this DropTarget to notify the DropTarget 530 * that a ComponentPeer has been disassociated with that Component. 531 * 532 * Calling this method, other than to notify this DropTarget of the 533 * disassociation of the ComponentPeer from the Component may result in 534 * a malfunction of the DnD system. 535 ********************************************************************** 536 * 537 * @param peer The Peer of the Component we are being disassociated from! 538 */ 539 540 public void removeNotify(ComponentPeer peer) { 541 if (nativePeer != null) 542 ((DropTargetPeer)nativePeer).removeDropTarget(this); 543 544 componentPeer = nativePeer = null; 545 546 synchronized (this) { 547 if (isDraggingInside) { 548 dragExit(new DropTargetEvent(getDropTargetContext())); 549 } 550 } 551 } 552 553 /** 554 * Gets the <code>DropTargetContext</code> associated 555 * with this <code>DropTarget</code>. 556 * 557 * @return the <code>DropTargetContext</code> associated with this <code>DropTarget</code>. 558 */ 559 560 public DropTargetContext getDropTargetContext() { 561 return dropTargetContext; 562 } 563 564 /** 565 * Creates the DropTargetContext associated with this DropTarget. 566 * Subclasses may override this method to instantiate their own 567 * DropTargetContext subclass. 568 * 569 * This call is typically *only* called by the platform's 570 * DropTargetContextPeer as a drag operation encounters this 571 * DropTarget. Accessing the Context while no Drag is current 572 * has undefined results. 573 * @return the DropTargetContext associated with this DropTarget 574 */ 575 576 protected DropTargetContext createDropTargetContext() { 577 return new DropTargetContext(this); 578 } 579 580 /** 581 * Serializes this <code>DropTarget</code>. Performs default serialization, 582 * and then writes out this object's <code>DropTargetListener</code> if and 583 * only if it can be serialized. If not, <code>null</code> is written 584 * instead. 585 * 586 * @serialData The default serializable fields, in alphabetical order, 587 * followed by either a <code>DropTargetListener</code> 588 * instance, or <code>null</code>. 589 * @since 1.4 590 */ 591 private void writeObject(ObjectOutputStream s) throws IOException { 592 s.defaultWriteObject(); 593 594 s.writeObject(SerializationTester.test(dtListener) 595 ? dtListener : null); 596 } 597 598 /** 599 * Deserializes this <code>DropTarget</code>. This method first performs 600 * default deserialization for all non-<code>transient</code> fields. An 601 * attempt is then made to deserialize this object's 602 * <code>DropTargetListener</code> as well. This is first attempted by 603 * deserializing the field <code>dtListener</code>, because, in releases 604 * prior to 1.4, a non-<code>transient</code> field of this name stored the 605 * <code>DropTargetListener</code>. If this fails, the next object in the 606 * stream is used instead. 607 * 608 * @since 1.4 609 */ 610 private void readObject(ObjectInputStream s) 611 throws ClassNotFoundException, IOException 612 { 613 ObjectInputStream.GetField f = s.readFields(); 614 615 try { 616 dropTargetContext = 617 (DropTargetContext)f.get("dropTargetContext", null); 618 } catch (IllegalArgumentException e) { 619 // Pre-1.4 support. 'dropTargetContext' was previously transient 620 } 621 if (dropTargetContext == null) { 622 dropTargetContext = createDropTargetContext(); 623 } 624 625 component = (Component)f.get("component", null); 626 actions = f.get("actions", DnDConstants.ACTION_COPY_OR_MOVE); 627 active = f.get("active", true); 628 629 // Pre-1.4 support. 'dtListener' was previously non-transient 630 try { 631 dtListener = (DropTargetListener)f.get("dtListener", null); 632 } catch (IllegalArgumentException e) { 633 // 1.4-compatible byte stream. 'dtListener' was written explicitly 634 dtListener = (DropTargetListener)s.readObject(); 635 } 636 } 637 638 /*********************************************************************/ 639 640 /** 641 * this protected nested class implements autoscrolling 642 */ 643 644 protected static class DropTargetAutoScroller implements ActionListener { 645 646 /** 647 * construct a DropTargetAutoScroller 648 * 649 * @param c the <code>Component</code> 650 * @param p the <code>Point</code> 651 */ 652 653 protected DropTargetAutoScroller(Component c, Point p) { 654 super(); 655 656 component = c; 657 autoScroll = (Autoscroll)component; 658 659 Toolkit t = Toolkit.getDefaultToolkit(); 660 661 Integer initial = Integer.valueOf(100); 662 Integer interval = Integer.valueOf(100); 663 664 try { 665 initial = (Integer)t.getDesktopProperty("DnD.Autoscroll.initialDelay"); 666 } catch (Exception e) { 667 // ignore 668 } 669 670 try { 671 interval = (Integer)t.getDesktopProperty("DnD.Autoscroll.interval"); 672 } catch (Exception e) { 673 // ignore 674 } 675 676 timer = new Timer(interval.intValue(), this); 677 678 timer.setCoalesce(true); 679 timer.setInitialDelay(initial.intValue()); 680 681 locn = p; 682 prev = p; 683 684 try { 685 hysteresis = ((Integer)t.getDesktopProperty("DnD.Autoscroll.cursorHysteresis")).intValue(); 686 } catch (Exception e) { 687 // ignore 688 } 689 690 timer.start(); 691 } 692 693 /** 694 * update the geometry of the autoscroll region 695 */ 696 697 @SuppressWarnings("deprecation") 698 private void updateRegion() { 699 Insets i = autoScroll.getAutoscrollInsets(); 700 Dimension size = component.getSize(); 701 702 if (size.width != outer.width || size.height != outer.height) 703 outer.reshape(0, 0, size.width, size.height); 704 705 if (inner.x != i.left || inner.y != i.top) 706 inner.setLocation(i.left, i.top); 707 708 int newWidth = size.width - (i.left + i.right); 709 int newHeight = size.height - (i.top + i.bottom); 710 711 if (newWidth != inner.width || newHeight != inner.height) 712 inner.setSize(newWidth, newHeight); 713 714 } 715 716 /** 717 * cause autoscroll to occur 718 * 719 * @param newLocn the <code>Point</code> 720 */ 721 722 protected synchronized void updateLocation(Point newLocn) { 723 prev = locn; 724 locn = newLocn; 725 726 if (Math.abs(locn.x - prev.x) > hysteresis || 727 Math.abs(locn.y - prev.y) > hysteresis) { 728 if (timer.isRunning()) timer.stop(); 729 } else { 730 if (!timer.isRunning()) timer.start(); 731 } 732 } 733 734 /** 735 * cause autoscrolling to stop 736 */ 737 738 protected void stop() { timer.stop(); } 739 740 /** 741 * cause autoscroll to occur 742 * 743 * @param e the <code>ActionEvent</code> 744 */ 745 746 public synchronized void actionPerformed(ActionEvent e) { 747 updateRegion(); 748 749 if (outer.contains(locn) && !inner.contains(locn)) 750 autoScroll.autoscroll(locn); 751 } 752 753 /* 754 * fields 755 */ 756 757 private Component component; 758 private Autoscroll autoScroll; 759 760 private Timer timer; 761 762 private Point locn; 763 private Point prev; 764 765 private Rectangle outer = new Rectangle(); 766 private Rectangle inner = new Rectangle(); 767 768 private int hysteresis = 10; 769 } 770 771 /*********************************************************************/ 772 773 /** 774 * create an embedded autoscroller 775 * 776 * @param c the <code>Component</code> 777 * @param p the <code>Point</code> 778 * @return an embedded autoscroller 779 */ 780 781 protected DropTargetAutoScroller createDropTargetAutoScroller(Component c, Point p) { 782 return new DropTargetAutoScroller(c, p); 783 } 784 785 /** 786 * initialize autoscrolling 787 * 788 * @param p the <code>Point</code> 789 */ 790 791 protected void initializeAutoscrolling(Point p) { 792 if (component == null || !(component instanceof Autoscroll)) return; 793 794 autoScroller = createDropTargetAutoScroller(component, p); 795 } 796 797 /** 798 * update autoscrolling with current cursor location 799 * 800 * @param dragCursorLocn the <code>Point</code> 801 */ 802 803 protected void updateAutoscroll(Point dragCursorLocn) { 804 if (autoScroller != null) autoScroller.updateLocation(dragCursorLocn); 805 } 806 807 /** 808 * clear autoscrolling 809 */ 810 811 protected void clearAutoscroll() { 812 if (autoScroller != null) { 813 autoScroller.stop(); 814 autoScroller = null; 815 } 816 } 817 818 /** 819 * The DropTargetContext associated with this DropTarget. 820 * 821 * @serial 822 */ 823 private DropTargetContext dropTargetContext = createDropTargetContext(); 824 825 /** 826 * The Component associated with this DropTarget. 827 * 828 * @serial 829 */ 830 private Component component; 831 832 /* 833 * That Component's Peer 834 */ 835 private transient ComponentPeer componentPeer; 836 837 /* 838 * That Component's "native" Peer 839 */ 840 private transient ComponentPeer nativePeer; 841 842 843 /** 844 * Default permissible actions supported by this DropTarget. 845 * 846 * @see #setDefaultActions 847 * @see #getDefaultActions 848 * @serial 849 */ 850 int actions = DnDConstants.ACTION_COPY_OR_MOVE; 851 852 /** 853 * <code>true</code> if the DropTarget is accepting Drag & Drop operations. 854 * 855 * @serial 856 */ 857 boolean active = true; 858 859 /* 860 * the auto scrolling object 861 */ 862 863 private transient DropTargetAutoScroller autoScroller; 864 865 /* 866 * The delegate 867 */ 868 869 private transient DropTargetListener dtListener; 870 871 /* 872 * The FlavorMap 873 */ 874 875 private transient FlavorMap flavorMap; 876 877 /* 878 * If the dragging is currently inside this drop target 879 */ 880 private transient boolean isDraggingInside; 881 }