protected void checkSubclass() {
   String name = getClass().getName();
   String validName = DragSource.class.getName();
   if (!validName.equals(name)) {
     DND.error(SWT.ERROR_INVALID_SUBCLASS);
   }
 }
 /**
  * Adds the listener to the collection of listeners who will be notified when a drag and drop
  * operation is in progress, by sending it one of the messages defined in the <code>
  * DragSourceListener</code> interface.
  *
  * <p>
  *
  * <ul>
  *   <li><code>dragStart</code> is called when the user has begun the actions required to drag the
  *       widget. This event gives the application the chance to decide if a drag should be
  *       started.
  *   <li><code>dragSetData</code> is called when the data is required from the drag source.
  *   <li><code>dragFinished</code> is called when the drop has successfully completed (mouse up
  *       over a valid target) or has been terminated (such as hitting the ESC key). Perform
  *       cleanup such as removing data from the source side on a successful move operation.
  * </ul>
  *
  * @param listener the listener which should be notified
  * @exception IllegalArgumentException
  *     <ul>
  *       <li>ERROR_NULL_ARGUMENT - if the listener is null
  *     </ul>
  *
  * @exception SWTException
  *     <ul>
  *       <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  *       <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  *     </ul>
  *
  * @see DragSourceListener
  * @see #getDragListeners
  * @see #removeDragListener
  * @see DragSourceEvent
  */
 public void addDragListener(DragSourceListener listener) {
   if (listener == null) DND.error(SWT.ERROR_NULL_ARGUMENT);
   DNDListener typedListener = new DNDListener(listener);
   typedListener.dndWidget = this;
   addListener(DND.DragStart, typedListener);
   addListener(DND.DragSetData, typedListener);
   addListener(DND.DragEnd, typedListener);
 }
  /**
   * Creates a new <code>DragSource</code> to handle dragging from the specified <code>Control
   * </code>. Creating an instance of a DragSource may cause system resources to be allocated
   * depending on the platform. It is therefore mandatory that the DragSource instance be disposed
   * when no longer required.
   *
   * @param control the <code>Control</code> that the user clicks on to initiate the drag
   * @param style the bitwise OR'ing of allowed operations; this may be a combination of any of
   *     DND.DROP_NONE, DND.DROP_COPY, DND.DROP_MOVE, DND.DROP_LINK
   * @exception SWTException
   *     <ul>
   *       <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
   *       <li>ERROR_INVALID_SUBCLASS - if this class is not an allowed subclass
   *     </ul>
   *
   * @exception SWTError
   *     <ul>
   *       <li>ERROR_CANNOT_INIT_DRAG - unable to initiate drag source; this will occur if more than
   *           one drag source is created for a control or if the operating system will not allow
   *           the creation of the drag source
   *     </ul>
   *     <p>NOTE: ERROR_CANNOT_INIT_DRAG should be an SWTException, since it is a recoverable error,
   *     but can not be changed due to backward compatibility.
   * @see Widget#dispose
   * @see DragSource#checkSubclass
   * @see DND#DROP_NONE
   * @see DND#DROP_COPY
   * @see DND#DROP_MOVE
   * @see DND#DROP_LINK
   */
  public DragSource(Control control, int style) {
    super(control, checkStyle(style));
    this.control = control;
    if (control.getData(DND.DRAG_SOURCE_KEY) != null) {
      DND.error(DND.ERROR_CANNOT_INIT_DRAG);
    }
    control.setData(DND.DRAG_SOURCE_KEY, this);
    createCOMInterfaces();
    this.AddRef();

    controlListener =
        new Listener() {
          public void handleEvent(Event event) {
            if (event.type == SWT.Dispose) {
              if (!DragSource.this.isDisposed()) {
                DragSource.this.dispose();
              }
            }
            if (event.type == SWT.DragDetect) {
              if (!DragSource.this.isDisposed()) {
                DragSource.this.drag(event);
              }
            }
          }
        };
    control.addListener(SWT.Dispose, controlListener);
    control.addListener(SWT.DragDetect, controlListener);

    this.addListener(
        SWT.Dispose,
        new Listener() {
          public void handleEvent(Event e) {
            DragSource.this.onDispose();
          }
        });

    Object effect = control.getData(DEFAULT_DRAG_SOURCE_EFFECT);
    if (effect instanceof DragSourceEffect) {
      dragEffect = (DragSourceEffect) effect;
    } else if (control instanceof Tree) {
      dragEffect = new TreeDragSourceEffect((Tree) control);
    } else if (control instanceof Table) {
      dragEffect = new TableDragSourceEffect((Table) control);
    }
  }
 /**
  * Removes the listener from the collection of listeners who will be notified when a drag and drop
  * operation is in progress.
  *
  * @param listener the listener which should no longer be notified
  * @exception IllegalArgumentException
  *     <ul>
  *       <li>ERROR_NULL_ARGUMENT - if the listener is null
  *     </ul>
  *
  * @exception SWTException
  *     <ul>
  *       <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed
  *       <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
  *     </ul>
  *
  * @see DragSourceListener
  * @see #addDragListener
  * @see #getDragListeners
  */
 public void removeDragListener(DragSourceListener listener) {
   if (listener == null) DND.error(SWT.ERROR_NULL_ARGUMENT);
   removeListener(DND.DragStart, listener);
   removeListener(DND.DragSetData, listener);
   removeListener(DND.DragEnd, listener);
 }