Package org.jgraph.graph

Source Code of org.jgraph.graph.GraphTransferHandler

/*
* @(#)GraphTransferHandler.java  1.0 31-DEC-04
*
* Copyright (c) 2001-2004 Gaudenz Alder
*/
package org.jgraph.graph;

import java.awt.Point;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.event.InputEvent;
import java.awt.event.MouseEvent;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.Hashtable;
import java.util.Map;

import javax.swing.JComponent;
import javax.swing.TransferHandler;

import org.jgraph.JGraph;

/**
* @author Gaudenz Alder
*
* Default datatransfer handler.
*/
public class GraphTransferHandler extends TransferHandler {

  /* Pointer to the last inserted array of cells. */
  protected Object out, in;

  /* How many times the last transferable was inserted. */
  protected int inCount = 0;

  public boolean canImport(JComponent comp, DataFlavor[] flavors) {
    for (int i = 0; i < flavors.length; i++)
      if (flavors[i] == GraphTransferable.dataFlavor)
        return true;
    return false;
  }

  /* Public entry point to create a Transferable. */
  public Transferable createTransferableForGraph(JGraph graph) {
    return createTransferable(graph);
  }

  protected Transferable createTransferable(JComponent c) {
    if (c instanceof JGraph) {
      JGraph graph = (JGraph) c;
      GraphModel model = graph.getModel();
      if (!graph.isSelectionEmpty()) {
        Object[] flat = graph.getDescendants(graph.order(graph
            .getSelectionCells()));
        ParentMap pm = ParentMap.create(model, flat, false, true);
        ConnectionSet cs = ConnectionSet.create(model, flat, false);
        Map viewAttributes = GraphConstants.createAttributes(flat,
            graph.getGraphLayoutCache());
        Rectangle2D bounds = graph.getCellBounds(graph
            .getSelectionCells());
        out = flat;
        return create(graph, flat, viewAttributes, bounds, cs, pm);
      }
    }
    return null;
  }

  protected GraphTransferable create(JGraph graph, Object[] cells,
      Map viewAttributes, Rectangle2D bounds, ConnectionSet cs,
      ParentMap pm) {
    return new GraphTransferable(cells, viewAttributes, bounds, cs, pm);
  }

  protected void exportDone(JComponent comp, Transferable data, int action) {
    if (comp instanceof JGraph && data instanceof GraphTransferable) {
      JGraph graph = (JGraph) comp;
      if (action == TransferHandler.MOVE) {
        Object[] cells = ((GraphTransferable) data).getCells();
        graph.getGraphLayoutCache().remove(cells);
      }
      graph.getUI().updateHandle();
      graph.getUI().setInsertionLocation(null);
    }
  }

  public int getSourceActions(JComponent c) {
    return COPY_OR_MOVE;
  }

  // NOTE: 1. We abuse return value to signal removal to the sender.
  //       2. We always clone cells when transferred between two models
  //          This is because they contain parts of the model's data.
  //       3. Transfer is passed to importDataImpl for unsupported
  //          dataflavors (becaue method may return false, see 1.)
  public boolean importData(JComponent comp, Transferable t) {
    try {
      if (comp instanceof JGraph) {
        JGraph graph = (JGraph) comp;
        GraphModel model = graph.getModel();
        GraphLayoutCache cache = graph.getGraphLayoutCache();
        if (t.isDataFlavorSupported(GraphTransferable.dataFlavor)
            && graph.isEnabled()) {
          // May be null
          Point p = graph.getUI().getInsertionLocation();

          // Get Local Machine Flavor
          Object obj = t
              .getTransferData(GraphTransferable.dataFlavor);
          GraphTransferable gt = (GraphTransferable) obj;

          // Get Transferred Cells
          Object[] cells = gt.getCells();

          // Check if all cells are in the model
          boolean allInModel = true;
          for (int i = 0; i < cells.length && allInModel; i++)
            allInModel = allInModel && model.contains(cells[i]);

          // Count repetitive inserts
          if (in == cells)
            inCount++;
          else
            inCount = (allInModel) ? 1 : 0;
          in = cells;

          // Delegate to handle
          if (p != null && in == out
              && graph.getUI().getHandle() != null) {
            int mod = (graph.getUI().getDropAction() == TransferHandler.COPY) ? InputEvent.CTRL_MASK
                : 0;
            graph.getUI().getHandle().mouseReleased(
                new MouseEvent(comp, 0, 0, mod, p.x, p.y, 1,
                    false));
            return false;
          }

          // Get more Transfer Data
          Rectangle2D bounds = gt.getBounds();
          Map nested = gt.getAttributeMap();
          ConnectionSet cs = gt.getConnectionSet();
          ParentMap pm = gt.getParentMap();

          // Move across models or via clipboard always clones
          if (!allInModel
              || p == null
              || graph.getUI().getDropAction() == TransferHandler.COPY) {

            // Translate cells
            double dx = 0, dy = 0;

            // Cloned via Drag and Drop
            if (nested != null) {
              if (p != null && bounds != null) {
                Point2D insert = graph.fromScreen(graph
                    .snap((Point2D) p.clone()));
                dx = insert.getX() - bounds.getX();
                dy = insert.getY() - bounds.getY();

                // Cloned via Clipboard
              } else {
                dx = inCount * graph.getGridSize();
                dy = inCount * graph.getGridSize();
              }
            }

            cache.insertClones(cells, graph.cloneCells(cells),
                nested, cs, pm, dx, dy);

            // Signal sender to remove only if moved between
            // different models
            return (graph.getUI().getDropAction() == TransferHandler.MOVE && !allInModel);

            // We are dealing with a move across multiple views
            // of the same model
          } else {

            // Moved via Drag and Drop
            if (p != null) {
              // Scale insertion location
              Point2D insert = graph.fromScreen(graph
                  .snap(new Point(p)));

              // Compute translation vector and translate all
              // attribute maps.
              if (bounds != null && nested != null) {
                double dx = insert.getX() - bounds.getX();
                double dy = insert.getY() - bounds.getY();
                AttributeMap.translate(nested.values(), dx, dy);
              } else if (bounds == null) {

                // Prevents overwriting view-local
                // attributes
                // for known cells. Note: This is because
                // if bounds is null, the caller wants
                // to signal that the bounds were
                // not available, which is typically the
                // case if no graph layout cache
                // is at hand. To avoid overriding the
                // local attributes such as the bounds
                // with the default bounds from the model,
                // we remove all attributes that travel
                // along with the transferable. (Since
                // all cells are already in the model
                // no information is lost by doing this.)
                double gs2 = 2 * graph.getGridSize();
                nested = new Hashtable();
                Map emptyMap = new Hashtable();
                for (int i = 0; i < cells.length; i++) {

                  // This also gives us the chance to
                  // provide useful default location and
                  // resize if there are no useful bounds
                  // that travel along with the cells.
                  if (!model.isEdge(cells[i])
                      && !model.isPort(cells[i])) {
                   
                    // Check if there are useful bounds
                    // defined in the model, otherwise resize,
                    // because the view does not yet exist.
                    Rectangle2D tmp = graph.getCellBounds(cells[i]);
                    if (tmp == null)
                      tmp = GraphConstants
                        .getBounds(model
                            .getAttributes(cells[i]));
                   
                    // Clone the rectangle to force a repaint
                    if (tmp != null)
                      tmp = (Rectangle2D) tmp.clone();

                    Hashtable attrs = new Hashtable();
                    Object parent = model.getParent(cells[i]);
                    if (tmp == null) {
                      tmp = new Rectangle2D.Double(p
                          .getX(), p.getY(),
                          gs2 / 2, gs2);
                      GraphConstants.setResize(attrs,
                          true);
                     
                      // Shift
                      p.setLocation(p.getX() + gs2, p.getY()
                          + gs2);
                      graph.snap(p);
                    // If parent processed then childs are already located
                    } else if (parent == null || !nested.keySet().contains(model.getParent(cells[i]))) {
                      CellView view = graph.getGraphLayoutCache().getMapping(cells[i], false);
                      if (view != null && !view.isLeaf()) {
                        double dx = p.getX() - tmp.getX();
                        double dy = p.getY() - tmp.getY();
                        GraphLayoutCache.translateViews(new CellView[]{view}, dx, dy);
                      } else {
                        tmp.setFrame(p.getX(), p.getY(),
                          tmp.getWidth(), tmp
                              .getHeight());
                      }

                      // Shift
                      p.setLocation(p.getX() + gs2, p.getY()
                          + gs2);
                      graph.snap(p);
                    }
                    GraphConstants.setBounds(attrs, tmp);
                    nested.put(cells[i], attrs);
                  } else {
                    nested.put(cells[i], emptyMap);
                  }
                }
              }

              // Edit cells (and make visible)
              cache.edit(nested, null, null, null);
            }

            // Select topmost cells in group-structure
            graph.setSelectionCells(DefaultGraphModel
                .getTopmostCells(model, cells));

            // Don't remove at sender
            return false;
          }
        } else
          return importDataImpl(comp, t);
      }
    } catch (Exception exception) {
      //System.err.println("Cannot import: " +
      // exception.getMessage());
      exception.printStackTrace();
    }
    return false;
  }

  // For subclassers if above does not handle the insertion
  protected boolean importDataImpl(JComponent comp, Transferable t) {
    return false;
  }

}
TOP

Related Classes of org.jgraph.graph.GraphTransferHandler

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.