Package org.jgraph.plaf.basic

Source Code of org.jgraph.plaf.basic.BasicGraphDropTargetListener

/*
* @(#)BasicGraphDropTargetListener  1.0 03-JUL-04
*
* Copyright (c) 2001-2004 Gaudenz Alder
*/
package org.jgraph.plaf.basic;

import java.awt.Insets;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.dnd.DropTargetContext;
import java.awt.dnd.DropTargetDragEvent;
import java.awt.dnd.DropTargetDropEvent;
import java.awt.dnd.DropTargetEvent;
import java.awt.dnd.DropTargetListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JComponent;
import javax.swing.Scrollable;
import javax.swing.SwingConstants;
import javax.swing.Timer;
import javax.swing.plaf.UIResource;

public class BasicGraphDropTargetListener
  implements DropTargetListener, UIResource, ActionListener {

  /**
   * construct a DropTargetAutoScroller
   */
  public BasicGraphDropTargetListener() {
  }

  /**
   * called to save the state of a component in case it needs to
   * be restored because a drop is not performed.
   */
  protected void saveComponentState(JComponent c) {
  }

  /**
   * called to restore the state of a component in case a drop
   * is not performed.
   */
  protected void restoreComponentState(JComponent c) {
  }

  /**
   * called to restore the state of a component in case a drop
   * is performed.
   */
  protected void restoreComponentStateForDrop(JComponent c) {
  }

  /**
   * called to set the insertion location to match the current
   * mouse pointer coordinates.
   */
  protected void updateInsertionLocation(JComponent c, Point p) {
  }

  /**
   * Update the geometry of the autoscroll region.  The geometry is
   * maintained as a pair of rectangles.  The region can cause
   * a scroll if the pointer sits inside it for the duration of the
   * timer.  The region that causes the timer countdown is the area
   * between the two rectangles.
   * <p>
   * This is implemented to use the visible area of the component
   * as the outer rectangle and the insets are based upon the
   * Scrollable information (if any).  If the Scrollable is
   * scrollable along an axis, the step increment is used as
   * the autoscroll inset.  If the component is not scrollable,
   * the insets will be zero (i.e. autoscroll will not happen).
   */
  void updateAutoscrollRegion(JComponent c) {
    // compute the outer
    Rectangle visible = c.getVisibleRect();
    outer.setBounds(visible.x, visible.y, visible.width, visible.height);

    // compute the insets
    // TBD - the thing with the scrollable
    Insets i = new Insets(0, 0, 0, 0);
    if (c instanceof Scrollable) {
      Scrollable s = (Scrollable) c;
      i.left =
        s.getScrollableUnitIncrement(
          visible,
          SwingConstants.HORIZONTAL,
          1);
      i.top =
        s.getScrollableUnitIncrement(
          visible,
          SwingConstants.VERTICAL,
          1);
      i.right =
        s.getScrollableUnitIncrement(
          visible,
          SwingConstants.HORIZONTAL,
          -1);
      i.bottom =
        s.getScrollableUnitIncrement(
          visible,
          SwingConstants.VERTICAL,
          -1);
    }

    // set the inner from the insets
    inner.setBounds(
      visible.x + i.left,
      visible.y + i.top,
      visible.width - (i.left + i.right),
      visible.height - (i.top + i.bottom));
  }

  /**
   * Perform an autoscroll operation.  This is implemented to scroll by the
   * unit increment of the Scrollable using scrollRectToVisible.  If the
   * cursor is in a corner of the autoscroll region, more than one axis will
   * scroll.
   */
  void autoscroll(JComponent c, Point pos) {
    if (c instanceof org.jgraph.JGraph)
      BasicGraphUI.autoscroll((org.jgraph.JGraph) c, pos);
  }

  /**
   * Initializes the internal properties if they haven't been already
   * inited. This is done lazily to avoid loading of desktop properties.
   */
  private void initPropertiesIfNecessary() {
    if (timer == null) {
      Toolkit t = Toolkit.getDefaultToolkit();
      Integer initial = new Integer(100);
      Integer interval = new Integer(100);

      try {
        initial =
          (Integer) t.getDesktopProperty(
            "DnD.Autoscroll.initialDelay");
      } catch (Exception e) {
        // ignore
      }
      try {
        interval =
          (Integer) t.getDesktopProperty("DnD.Autoscroll.interval");
      } catch (Exception e) {
        // ignore
      }
      timer = new Timer(interval.intValue(), this);

      timer.setCoalesce(true);
      timer.setInitialDelay(initial.intValue());

      try {
        hysteresis =
          ((Integer) t
            .getDesktopProperty("DnD.Autoscroll.cursorHysteresis"))
            .intValue();
      } catch (Exception e) {
        // ignore
      }
    }
  }

  static JComponent getComponent(DropTargetEvent e) {
    DropTargetContext context = e.getDropTargetContext();
    return (JComponent) context.getComponent();
  }

  // --- ActionListener methods --------------------------------------

  /**
   * The timer fired, perform autoscroll if the pointer is within the
   * autoscroll region.
   * <P>
   * @param e the <code>ActionEvent</code>
   */
  public synchronized void actionPerformed(ActionEvent e) {
    updateAutoscrollRegion(component);
    if (outer.contains(lastPosition) && !inner.contains(lastPosition)) {
      autoscroll(component, lastPosition);
    }
  }

  // --- DropTargetListener methods -----------------------------------

  public void dragEnter(DropTargetDragEvent e) {
    component = getComponent(e);
      // DO NOT REMOVE OR MODIFY THIS LINE!
      javax.swing.TransferHandler // JAVA13: org.jgraph.plaf.basic.TransferHandler
        th = (
      // DO NOT REMOVE OR MODIFY THIS LINE!
      (JComponent) // JAVA13: (org.jgraph.plaf.basic.TransferHandler.JDNDAdapter)
  component).getTransferHandler();
    canImport = th.canImport(component, e.getCurrentDataFlavors());
    if (canImport) {
      saveComponentState(component);
      lastPosition = e.getLocation();
      updateAutoscrollRegion(component);
      initPropertiesIfNecessary();
    }
  }

  public void dragOver(DropTargetDragEvent e) {
    if (canImport) {
      Point p = e.getLocation();
      updateInsertionLocation(component, p);

      // check autoscroll
      synchronized (this) {
        if (Math.abs(p.x - lastPosition.x) > hysteresis
          || Math.abs(p.y - lastPosition.y) > hysteresis) {
          // no autoscroll
          if (timer.isRunning())
            timer.stop();
        } else {
          if (!timer.isRunning())
            timer.start();
        }
        lastPosition = p;
      }
    }
  }

  public void dragExit(DropTargetEvent e) {
    if (canImport) {
      restoreComponentState(component);
    }
    cleanup();
  }

  public void drop(DropTargetDropEvent e) {
    if (canImport) {
      restoreComponentStateForDrop(component);
    }
    cleanup();
  }

  public void dropActionChanged(DropTargetDragEvent e) {
  }

  /**
   * Cleans up internal state after the drop has finished (either succeeded
   * or failed).
   */
  private void cleanup() {
    if (timer != null) {
      timer.stop();
    }
    component = null;
    lastPosition = null;
  }

  // --- fields --------------------------------------------------

  private Timer timer;
  private Point lastPosition;
  private Rectangle outer = new Rectangle();
  private Rectangle inner = new Rectangle();
  private int hysteresis = 10;
  private boolean canImport;

  /**
   * The current component. The value is cached from the drop events and used
   * by the timer. When a drag exits or a drop occurs, this value is cleared.
   */
  private JComponent component;

}
TOP

Related Classes of org.jgraph.plaf.basic.BasicGraphDropTargetListener

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.