/** Returns the data to be transferred in a drag and drop operation. */
 @Override
 public void dragSetData(DragSourceEvent event) {
   if (event.doit == false) return;
   if (ModelDataTransfer.getInstance().isSupportedType(event.dataType)) {
     event.data = getSelectedModelObjects();
     fDragData = event.data;
     return;
   }
   if (TextTransfer.getInstance().isSupportedType(event.dataType)) {
     event.data =
         createTextualRepresentation((IStructuredSelection) fSelectionProvider.getSelection());
     fDragData = null;
     return;
   }
 }
  /*
   * (non-Javadoc)
   *
   * @see org.eclipse.update.ui.forms.internal.FormSection#createClient(org.eclipse.swt.widgets.Composite,
   *      org.eclipse.update.ui.forms.internal.FormWidgetFactory)
   */
  public void createClient(Section section, FormToolkit toolkit) {
    fModel = (ISiteModel) getPage().getModel();
    fModel.addModelChangedListener(this);

    Composite container = createClientContainer(section, 2, toolkit);
    createViewerPartControl(container, SWT.MULTI, 2, toolkit);
    fCategoryTreePart = getTreePart();
    fCategoryViewer = fCategoryTreePart.getTreeViewer();
    fCategoryViewer.setContentProvider(new CategoryContentProvider());
    fSiteLabelProvider = new SiteLabelProvider();
    fCategoryViewer.setLabelProvider(fSiteLabelProvider);

    fCategoryViewer.setInput(fModel.getSite());
    int ops = DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_DEFAULT;
    Transfer[] transfers = new Transfer[] {ModelDataTransfer.getInstance()};
    if (isEditable()) {
      fCategoryViewer.addDropSupport(
          ops,
          transfers,
          new ViewerDropAdapter(fCategoryViewer) {
            public void dragEnter(DropTargetEvent event) {
              Object target = determineTarget(event);
              if (target == null && event.detail == DND.DROP_COPY) {
                event.detail = DND.DROP_MOVE;
              }
              super.dragEnter(event);
            }

            /*
             * (non-Javadoc)
             *
             * @see org.eclipse.jface.viewers.ViewerDropAdapter#dragOperationChanged(org.eclipse.swt.dnd.DropTargetEvent)
             */
            public void dragOperationChanged(DropTargetEvent event) {
              Object target = determineTarget(event);
              if (target == null && event.detail == DND.DROP_COPY) {
                event.detail = DND.DROP_MOVE;
              }
              super.dragOperationChanged(event);
            }

            /*
             * (non-Javadoc)
             *
             * @see org.eclipse.jface.viewers.ViewerDropAdapter#dragOver(org.eclipse.swt.dnd.DropTargetEvent)
             */
            public void dragOver(DropTargetEvent event) {
              Object target = determineTarget(event);
              if (target == null && event.detail == DND.DROP_COPY) {
                event.detail = DND.DROP_MOVE;
              }
              super.dragOver(event);
            }

            /**
             * Returns the position of the given event's coordinates relative to its target. The
             * position is determined to be before, after, or on the item, based on some threshold
             * value.
             *
             * @param event the event
             * @return one of the <code>LOCATION_* </code> constants defined in this class
             */
            protected int determineLocation(DropTargetEvent event) {
              if (!(event.item instanceof Item)) {
                return LOCATION_NONE;
              }
              Item item = (Item) event.item;
              Point coordinates = new Point(event.x, event.y);
              coordinates = getViewer().getControl().toControl(coordinates);
              if (item != null) {
                Rectangle bounds = getBounds(item);
                if (bounds == null) {
                  return LOCATION_NONE;
                }
              }
              return LOCATION_ON;
            }

            public boolean performDrop(Object data) {
              if (!(data instanceof Object[])) return false;
              Object target = getCurrentTarget();

              int op = getCurrentOperation();
              Object[] objects = (Object[]) data;
              if (objects.length > 0 && objects[0] instanceof SiteFeatureAdapter) {
                if (op == DND.DROP_COPY && target != null) {
                  copyFeature((SiteFeatureAdapter) objects[0], target);
                } else {
                  moveFeature((SiteFeatureAdapter) objects[0], target);
                }
                return true;
              }
              return false;
            }

            public boolean validateDrop(Object target, int operation, TransferData transferType) {
              return (target instanceof ISiteCategoryDefinition || target == null);
            }
          });
    }

    fCategoryViewer.addDragSupport(
        DND.DROP_MOVE | DND.DROP_COPY,
        transfers,
        new DragSourceListener() {
          public void dragStart(DragSourceEvent event) {
            IStructuredSelection ssel = (IStructuredSelection) fCategoryViewer.getSelection();
            if (ssel == null
                || ssel.isEmpty()
                || !(ssel.getFirstElement() instanceof SiteFeatureAdapter)) {
              event.doit = false;
            }
          }

          public void dragSetData(DragSourceEvent event) {
            IStructuredSelection ssel = (IStructuredSelection) fCategoryViewer.getSelection();
            event.data = ssel.toArray();
          }

          public void dragFinished(DragSourceEvent event) {}
        });

    fCategoryTreePart.setButtonEnabled(BUTTON_ADD_CATEGORY, isEditable());
    fCategoryTreePart.setButtonEnabled(BUTTON_ADD_FEATURE, isEditable());
    fCategoryTreePart.setButtonEnabled(BUTTON_BUILD_FEATURE, isEditable());
    fCategoryTreePart.setButtonEnabled(BUTTON_BUILD_ALL, isEditable());

    // fCategoryViewer.expandAll();
    toolkit.paintBordersFor(container);
    section.setClient(container);
    initialize();
  }