Package com.mxgraph.swing.view

Source Code of com.mxgraph.swing.view.mxCellStatePreview

/**
* Copyright (c) 2007, Gaudenz Alder
*/
package com.mxgraph.swing.view;

import java.awt.AlphaComposite;
import java.awt.Composite;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import com.mxgraph.canvas.mxGraphics2DCanvas;
import com.mxgraph.model.mxGeometry;
import com.mxgraph.model.mxIGraphModel;
import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.util.mxPoint;
import com.mxgraph.util.mxRectangle;
import com.mxgraph.util.mxUtils;
import com.mxgraph.view.mxCellState;
import com.mxgraph.view.mxGraph;

/**
* Represents the current state of a cell in a given graph view.
*/
public class mxCellStatePreview
{
  /**
   *
   */
  protected Map<mxCellState, mxPoint> deltas = new LinkedHashMap<mxCellState, mxPoint>();

  /**
   *
   */
  protected int count = 0;

  /**
   *
   */
  protected mxGraphComponent graphComponent;

  /**
   * Specifies if cell states should be cloned or changed in-place.
   */
  protected boolean cloned;

  /**
   *
   */
  protected float opacity = 1;

  /**
   *
   */
  protected List<mxCellState> cellStates;

  /**
   * Constructs a new state preview. The paint handler to invoke the paint
   * method must be installed elsewhere.
   */
  public mxCellStatePreview(mxGraphComponent graphComponent, boolean cloned)
  {
    this.graphComponent = graphComponent;
    this.cloned = cloned;
  }

  /**
   *
   */
  public boolean isCloned()
  {
    return cloned;
  }

  /**
   *
   */
  public void setCloned(boolean value)
  {
    cloned = value;
  }

  /**
   *
   */
  public boolean isEmpty()
  {
    return count == 0;
  }

  /**
   *
   */
  public int getCount()
  {
    return count;
  }

  /**
   *
   */
  public Map<mxCellState, mxPoint> getDeltas()
  {
    return deltas;
  }

  /**
   *
   */
  public void setOpacity(float value)
  {
    opacity = value;
  }

  /**
   *
   */
  public float getOpacity()
  {
    return opacity;
  }

  /**
   *
   */
  public mxPoint moveState(mxCellState state, double dx, double dy)
  {
    return moveState(state, dx, dy, true, true);
  }

  /**
   *
   */
  public mxPoint moveState(mxCellState state, double dx, double dy,
      boolean add, boolean includeEdges)
  {
    mxPoint delta = deltas.get(state);

    if (delta == null)
    {
      delta = new mxPoint(dx, dy);
      deltas.put(state, delta);
      count++;
    }
    else
    {
      if (add)
      {
        delta.setX(delta.getX() + dx);
        delta.setY(delta.getY() + dy);
      }
      else
      {
        delta.setX(dx);
        delta.setY(dy);
      }
    }

    if (includeEdges)
    {
      addEdges(state);
    }

    return delta;
  }

  /**
   * Returns a dirty rectangle to be repainted in mxGraphControl.
   */
  public mxRectangle show()
  {
    mxGraph graph = graphComponent.getGraph();
    mxIGraphModel model = graph.getModel();

    // Stores a copy of the cell states
    List<mxCellState> previousStates = null;

    if (isCloned())
    {
      previousStates = new LinkedList<mxCellState>();
      Iterator<mxCellState> it = deltas.keySet().iterator();

      while (it.hasNext())
      {
        mxCellState state = it.next();
        previousStates.addAll(snapshot(state));
      }
    }

    // Translates the states in step
    Iterator<mxCellState> it = deltas.keySet().iterator();

    while (it.hasNext())
    {
      mxCellState state = it.next();
      mxPoint delta = deltas.get(state);
      mxCellState parentState = graph.getView().getState(
          model.getParent(state.getCell()));
      translateState(parentState, state, delta.getX(), delta.getY());
    }

    // Revalidates the states in step
    mxRectangle dirty = null;
    it = deltas.keySet().iterator();

    while (it.hasNext())
    {
      mxCellState state = it.next();
      mxPoint delta = deltas.get(state);
      mxCellState parentState = graph.getView().getState(
          model.getParent(state.getCell()));
      mxRectangle tmp = revalidateState(parentState, state, delta.getX(),
          delta.getY());

      if (dirty != null)
      {
        dirty.add(tmp);
      }
      else
      {
        dirty = tmp;
      }
    }

    // Takes a snapshot of the states for later drawing. If the states
    // are not cloned then this does nothing and just expects a repaint
    // of the dirty rectangle.
    if (previousStates != null)
    {
      cellStates = new LinkedList<mxCellState>();
      it = deltas.keySet().iterator();

      while (it.hasNext())
      {
        mxCellState state = it.next();
        cellStates.addAll(snapshot(state));
      }

      // Restores the previous states
      restore(previousStates);
    }

    if (dirty != null)
    {
      dirty.grow(2);
    }

    return dirty;
  }

  /**
   *
   */
  public void restore(List<mxCellState> snapshot)
  {
    mxGraph graph = graphComponent.getGraph();
    Iterator<mxCellState> it = snapshot.iterator();

    while (it.hasNext())
    {
      mxCellState state = it.next();
      mxCellState orig = graph.getView().getState(state.getCell());

      if (orig != null && orig != state)
      {
        restoreState(orig, state);
      }
    }
  }

  /**
   *
   */
  public void restoreState(mxCellState state, mxCellState from)
  {
    state.setLabelBounds(from.getLabelBounds());
    state.setAbsolutePoints(from.getAbsolutePoints());
    state.setOrigin(from.getOrigin());
    state.setAbsoluteOffset(from.getAbsoluteOffset());
    state.setBoundingBox(from.getBoundingBox());
    state.setTerminalDistance(from.getTerminalDistance());
    state.setSegments(from.getSegments());
    state.setLength(from.getLength());
    state.setX(from.getX());
    state.setY(from.getY());
    state.setWidth(from.getWidth());
    state.setHeight(from.getHeight());
  }

  /**
   *
   */
  public List<mxCellState> snapshot(mxCellState state)
  {
    List<mxCellState> result = new LinkedList<mxCellState>();

    if (state != null)
    {
      result.add((mxCellState) state.clone());

      mxGraph graph = graphComponent.getGraph();
      mxIGraphModel model = graph.getModel();
      Object cell = state.getCell();
      int childCount = model.getChildCount(cell);

      for (int i = 0; i < childCount; i++)
      {
        result.addAll(snapshot(graph.getView().getState(
            model.getChildAt(cell, i))));
      }
    }

    return result;
  }

  /**
   *
   */
  protected void translateState(mxCellState parentState, mxCellState state,
      double dx, double dy)
  {
    if (state != null)
    {
      mxGraph graph = graphComponent.getGraph();
      mxIGraphModel model = graph.getModel();
      Object cell = state.getCell();

      if (model.isVertex(cell))
      {
        state.getView().updateCellState(state);
        mxGeometry geo = graph.getCellGeometry(cell);

        // Moves selection cells and non-relative vertices in
        // the first phase so that edge terminal points will
        // be updated in the second phase
        if ((dx != 0 || dy != 0) && geo != null
            && (!geo.isRelative() || deltas.get(state) != null))
        {
          state.setX(state.getX() + dx);
          state.setY(state.getY() + dy);
        }
      }

      int childCount = model.getChildCount(cell);

      for (int i = 0; i < childCount; i++)
      {
        translateState(state,
            graph.getView().getState(model.getChildAt(cell, i)),
            dx, dy);
      }
    }
  }

  /**
   *
   */
  protected mxRectangle revalidateState(mxCellState parentState,
      mxCellState state, double dx, double dy)
  {
    mxRectangle dirty = null;

    if (state != null)
    {
      mxGraph graph = graphComponent.getGraph();
      mxIGraphModel model = graph.getModel();
      Object cell = state.getCell();
     
      // Updates the edge terminal points and restores the
      // (relative) positions of any (relative) children
      if (model.isEdge(cell))
      {
        state.getView().updateCellState(state);
      }
     
      dirty = state.getView().getBoundingBox(state, false);

      // Moves selection vertices which are relative
      mxGeometry geo = graph.getCellGeometry(cell);

      if ((dx != 0 || dy != 0)
          && geo != null
          && geo.isRelative()
          && model.isVertex(cell)
          && (parentState == null
              || model.isVertex(parentState.getCell()) || deltas
              .get(state) != null))
      {
        state.setX(state.getX() + dx);
        state.setY(state.getY() + dy);

        // TODO: Check this change
        dirty.setX(dirty.getX() + dx);
        dirty.setY(dirty.getY() + dy);

        graph.getView().updateLabelBounds(state);
      }

      int childCount = model.getChildCount(cell);

      for (int i = 0; i < childCount; i++)
      {
        mxRectangle tmp = revalidateState(state, graph.getView()
            .getState(model.getChildAt(cell, i)), dx, dy);

        if (dirty != null)
        {
          dirty.add(tmp);
        }
        else
        {
          dirty = tmp;
        }
      }
    }

    return dirty;
  }

  /**
   *
   */
  public void addEdges(mxCellState state)
  {
    mxGraph graph = graphComponent.getGraph();
    mxIGraphModel model = graph.getModel();
    Object cell = state.getCell();
    int edgeCount = model.getEdgeCount(cell);

    for (int i = 0; i < edgeCount; i++)
    {
      mxCellState state2 = graph.getView().getState(
          model.getEdgeAt(cell, i));

      if (state2 != null)
      {
        moveState(state2, 0, 0);
      }
    }
  }

  /**
   *
   */
  public void paint(Graphics g)
  {
    if (cellStates != null && cellStates.size() > 0)
    {
      mxGraphics2DCanvas canvas = graphComponent.getCanvas();

      // Sets antialiasing
      if (graphComponent.isAntiAlias())
      {
        mxUtils.setAntiAlias((Graphics2D) g, true, true);
      }

      Graphics2D previousGraphics = canvas.getGraphics();
      Point previousTranslate = canvas.getTranslate();
      double previousScale = canvas.getScale();

      try
      {
        canvas.setScale(graphComponent.getGraph().getView().getScale());
        canvas.setTranslate(0, 0);
        canvas.setGraphics((Graphics2D) g);

        paintPreview(canvas);
      }
      finally
      {
        canvas.setScale(previousScale);
        canvas.setTranslate(previousTranslate.x, previousTranslate.y);
        canvas.setGraphics(previousGraphics);
      }
    }
  }

  /**
   *
   */
  protected float getOpacityForCell(Object cell)
  {
    return opacity;
  }

  /**
   * Draws the preview using the graphics canvas.
   */
  protected void paintPreview(mxGraphics2DCanvas canvas)
  {
    Composite previousComposite = canvas.getGraphics().getComposite();

    // Paints the preview states
    Iterator<mxCellState> it = cellStates.iterator();

    while (it.hasNext())
    {
      mxCellState state = it.next();
      canvas.getGraphics().setComposite(
          AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
              getOpacityForCell(state.getCell())));
      paintPreviewState(canvas, state);
    }

    canvas.getGraphics().setComposite(previousComposite);
  }

  /**
   * Draws the preview using the graphics canvas.
   */
  protected void paintPreviewState(mxGraphics2DCanvas canvas,
      mxCellState state)
  {
    graphComponent.getGraph().drawState(
        canvas,
        state,
        state.getCell() != graphComponent.getCellEditor()
            .getEditingCell());
  }
}
TOP

Related Classes of com.mxgraph.swing.view.mxCellStatePreview

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.