Package com.mxgraph.swing.handler

Source Code of com.mxgraph.swing.handler.mxCellMarker

/**
* Copyright (c) 2008-2012, JGraph Ltd
*/
package com.mxgraph.swing.handler;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Stroke;
import java.awt.event.MouseEvent;

import javax.swing.JComponent;

import com.mxgraph.swing.mxGraphComponent;
import com.mxgraph.swing.util.mxSwingConstants;
import com.mxgraph.util.mxConstants;
import com.mxgraph.util.mxEvent;
import com.mxgraph.util.mxEventObject;
import com.mxgraph.util.mxEventSource;
import com.mxgraph.util.mxEventSource.mxIEventListener;
import com.mxgraph.util.mxUtils;
import com.mxgraph.view.mxCellState;
import com.mxgraph.view.mxGraphView;

/**
* Implements a mouse tracker that marks cells under the mouse.
*
* This class fires the following event:
*
* mxEvent.MARK fires in mark and unmark to notify the listener of a new cell
* under the mouse. The <code>state</code> property contains the mxCellState
* of the respective cell or null if no cell is under the mouse.
*
* To create a cell marker which highlights cells "in-place", the following
* code can be used:
* <code>
* mxCellMarker highlighter = new mxCellMarker(graphComponent) {
*
*   protected Map<String, Object> lastStyle;
*  
*   public mxCellState process(MouseEvent e)
*   {
*     mxCellState state = null;
*    
*     if (isEnabled())
*     {
*       state = getState(e);
*       boolean isValid = (state != null) ? isValidState(state) : false;
*      
*       if (!isValid)
*       {
*         state = null;
*       }
*      
*       highlight(state);
*     }
*    
*     return state;
*   }
*  
*   public void highlight(mxCellState state)
*   {
*     if (validState != state)
*     {
*       Rectangle dirty = null;
*      
*       if (validState != null)
*       {
*         validState.setStyle(lastStyle);
*         dirty = validState.getBoundingBox().getRectangle();
*         dirty.grow(4, 4);
*       }
*      
*       if (state != null)
*       {
*         lastStyle = state.getStyle();
*         state.setStyle(new Hashtable<String, Object>(state.getStyle()));
*         state.getStyle().put("strokeColor", "#00ff00");
*         state.getStyle().put("fontColor", "#00ff00");
*         state.getStyle().put("strokeWidth", "3");
*         
*         Rectangle tmp = state.getBoundingBox().getRectangle();
*        
*         if (dirty != null)
*         {
*           dirty.add(tmp);
*         }
*         else
*         {
*           dirty = tmp;
*         }
*        
*         dirty.grow(4, 4);
*       }
*      
*       validState = state;
*       graphComponent.repaint(dirty);
*     }
*   }
*
*   public void reset()
*   {
*     highlight(null);
*   }
*
*   public void paint(Graphics g)
*   {
*     // do nothing
*   }
* };
* graphComponent.getConnectionHandler().setMarker(highlighter);
* </code>
*/
public class mxCellMarker extends JComponent
{

  /**
   *
   */
  private static final long serialVersionUID = 614473367053597572L;

  /**
   * Specifies if the highlights should appear on top of everything
   * else in the overlay pane. Default is false.
   */
  public static boolean KEEP_ON_TOP = false;

  /**
   * Specifies the default stroke for the marker.
   */
  public static Stroke DEFAULT_STROKE = new BasicStroke(3);

  /**
   * Holds the event source.
   */
  protected mxEventSource eventSource = new mxEventSource(this);

  /**
   * Holds the enclosing graph component.
   */
  protected mxGraphComponent graphComponent;

  /**
   * Specifies if the marker is enabled. Default is true.
   */
  protected boolean enabled = true;

  /**
   * Specifies the portion of the width and height that should trigger
   * a highlight. The area around the center of the cell to be marked is used
   * as the hotspot. Possible values are between 0 and 1. Default is
   * mxConstants.DEFAULT_HOTSPOT.
   */
  protected double hotspot;

  /**
   * Specifies if the hotspot is enabled. Default is false.
   */
  protected boolean hotspotEnabled = false;

  /**
   * Specifies if the the content area of swimlane should be non-transparent
   * to mouse events. Default is false.
   */
  protected boolean swimlaneContentEnabled = false;

  /**
   * Specifies the valid- and invalidColor for the marker.
   */
  protected Color validColor, invalidColor;

  /**
   * Holds the current marker color.
   */
  protected transient Color currentColor;

  /**
   * Holds the marked state if it is valid.
   */
  protected transient mxCellState validState;

  /**
   * Holds the marked state.
   */
  protected transient mxCellState markedState;

  /**
   * Constructs a new marker for the given graph component.
   *
   * @param graphComponent
   */
  public mxCellMarker(mxGraphComponent graphComponent)
  {
    this(graphComponent, mxSwingConstants.DEFAULT_VALID_COLOR);
  }

  /**
   * Constructs a new marker for the given graph component.
   */
  public mxCellMarker(mxGraphComponent graphComponent, Color validColor)
  {
    this(graphComponent, validColor, mxSwingConstants.DEFAULT_INVALID_COLOR);
  }

  /**
   * Constructs a new marker for the given graph component.
   */
  public mxCellMarker(mxGraphComponent graphComponent, Color validColor,
      Color invalidColor)
  {
    this(graphComponent, validColor, invalidColor,
        mxConstants.DEFAULT_HOTSPOT);
  }

  /**
   * Constructs a new marker for the given graph component.
   */
  public mxCellMarker(mxGraphComponent graphComponent, Color validColor,
      Color invalidColor, double hotspot)
  {
    this.graphComponent = graphComponent;
    this.validColor = validColor;
    this.invalidColor = invalidColor;
    this.hotspot = hotspot;
  }

  /**
   * Sets the enabled state of the marker.
   */
  public void setEnabled(boolean enabled)
  {
    this.enabled = enabled;
  }

  /**
   * Returns true if the marker is enabled, that is, if it processes events
   * in process.
   */
  public boolean isEnabled()
  {
    return enabled;
  }

  /**
   * Sets the hotspot.
   */
  public void setHotspot(double hotspot)
  {
    this.hotspot = hotspot;
  }

  /**
   * Returns the hotspot.
   */
  public double getHotspot()
  {
    return hotspot;
  }

  /**
   * Specifies whether the hotspot should be used in intersects.
   */
  public void setHotspotEnabled(boolean enabled)
  {
    this.hotspotEnabled = enabled;
  }

  /**
   * Returns true if hotspot is used in intersects.
   */
  public boolean isHotspotEnabled()
  {
    return hotspotEnabled;
  }

  /**
   * Sets if the content area of swimlanes should not be transparent to
   * events.
   */
  public void setSwimlaneContentEnabled(boolean swimlaneContentEnabled)
  {
    this.swimlaneContentEnabled = swimlaneContentEnabled;
  }

  /**
   * Returns true if the content area of swimlanes is non-transparent to
   * events.
   */
  public boolean isSwimlaneContentEnabled()
  {
    return swimlaneContentEnabled;
  }

  /**
   * Sets the color used for valid highlights.
   */
  public void setValidColor(Color value)
  {
    validColor = value;
  }

  /**
   * Returns the color used for valid highlights.
   */
  public Color getValidColor()
  {
    return validColor;
  }

  /**
   * Sets the color used for invalid highlights.
   */
  public void setInvalidColor(Color value)
  {
    invalidColor = value;
  }

  /**
   * Returns the color used for invalid highlights.
   */
  public Color getInvalidColor()
  {
    return invalidColor;
  }

  /**
   * Returns true if validState is not null.
   */
  public boolean hasValidState()
  {
    return (validState != null);
  }

  /**
   * Returns the valid state.
   */
  public mxCellState getValidState()
  {
    return validState;
  }

  /**
   * Sets the current color.
   */
  public void setCurrentColor(Color value)
  {
    currentColor = value;
  }

  /**
   * Returns the current color.
   */
  public Color getCurrentColor()
  {
    return currentColor;
  }

  /**
   * Sets the marked state.
   */
  public void setMarkedState(mxCellState value)
  {
    markedState = value;
  }

  /**
   * Returns the marked state.
   */
  public mxCellState getMarkedState()
  {
    return markedState;
  }

  /**
   * Resets the state of the cell marker.
   */
  public void reset()
  {
    validState = null;

    if (markedState != null)
    {
      markedState = null;
      unmark();
    }
  }

  /**
   * Processes the given event and marks the state returned by getStateAt
   * with the color returned by getMarkerColor. If the markerColor is not
   * null, then the state is stored in markedState. If isValidState returns
   * true, then the state is stored in validState regardless of the marker
   * color. The state is returned regardless of the marker color and
   * valid state.
   */
  public mxCellState process(MouseEvent e)
  {
    mxCellState state = null;

    if (isEnabled())
    {
      state = getState(e);
      boolean valid = (state != null) ? isValidState(state) : false;
      Color color = getMarkerColor(e, state, valid);
     
      highlight(state, color, valid);
    }

    return state;
  }
 
  /**
   *
   */
  public void highlight(mxCellState state, Color color)
  {
    highlight(state, color, true);
  }
 
  /**
   *
   */
  public void highlight(mxCellState state, Color color, boolean valid)
  {
    if (valid)
    {
      validState = state;
    }
    else
    {
      validState = null;
    }

    if (state != markedState || color != currentColor)
    {
      currentColor = color;

      if (state != null && currentColor != null)
      {
        markedState = state;
        mark();
      }
      else if (markedState != null)
      {
        markedState = null;
        unmark();
      }
    }
  }

  /**
   * Marks the markedState and fires a mxEvent.MARK event.
   */
  public void mark()
  {
    if (markedState != null)
    {
      Rectangle bounds = markedState.getRectangle();
      bounds.grow(3, 3);
      bounds.width += 1;
      bounds.height += 1;
      setBounds(bounds);

      if (getParent() == null)
      {
        setVisible(true);

        if (KEEP_ON_TOP)
        {
          graphComponent.getGraphControl().add(this, 0);
        }
        else
        {
          graphComponent.getGraphControl().add(this);
        }
      }

      repaint();
      eventSource.fireEvent(new mxEventObject(mxEvent.MARK, "state",
          markedState));
    }
  }

  /**
   * Hides the marker and fires a mxEvent.MARK event.
   */
  public void unmark()
  {
    if (getParent() != null)
    {
      setVisible(false);
      getParent().remove(this);
      eventSource.fireEvent(new mxEventObject(mxEvent.MARK));
    }
  }

  /**
   * Returns true if the given state is a valid state. If this returns true,
   * then the state is stored in validState. The return value of this method
   * is used as the argument for getMarkerColor.
   */
  protected boolean isValidState(mxCellState state)
  {
    return true;
  }

  /**
   * Returns the valid- or invalidColor depending on the value of isValid.
   * The given state is ignored by this implementation.
   */
  protected Color getMarkerColor(MouseEvent e, mxCellState state,
      boolean isValid)
  {
    return (isValid) ? validColor : invalidColor;
  }

  /**
   * Uses getCell, getMarkedState and intersects to return the state for
   * the given event.
   */
  protected mxCellState getState(MouseEvent e)
  {
    Object cell = getCell(e);
    mxGraphView view = graphComponent.getGraph().getView();
    mxCellState state = getStateToMark(view.getState(cell));

    return (state != null && intersects(state, e)) ? state : null;
  }

  /**
   * Returns the state at the given location. This uses mxGraph.getCellAt.
   */
  protected Object getCell(MouseEvent e)
  {
    return graphComponent.getCellAt(e.getX(), e.getY(),
        swimlaneContentEnabled);
  }

  /**
   * Returns the state to be marked for the given state under the mouse. This
   * returns the given state.
   */
  protected mxCellState getStateToMark(mxCellState state)
  {
    return state;
  }

  /**
   * Returns true if the given mouse event intersects the given state. This
   * returns true if the hotspot is 0 or the event is inside the hotspot for
   * the given cell state.
   */
  protected boolean intersects(mxCellState state, MouseEvent e)
  {
    if (isHotspotEnabled())
    {
      return mxUtils.intersectsHotspot(state, e.getX(), e.getY(),
          hotspot, mxConstants.MIN_HOTSPOT_SIZE,
          mxConstants.MAX_HOTSPOT_SIZE);
    }

    return true;
  }

  /**
   * Adds the given event listener.
   */
  public void addListener(String eventName, mxIEventListener listener)
  {
    eventSource.addListener(eventName, listener);
  }

  /**
   * Removes the given event listener.
   */
  public void removeListener(mxIEventListener listener)
  {
    eventSource.removeListener(listener);
  }

  /**
   * Removes the given event listener for the specified event name.
   */
  public void removeListener(mxIEventListener listener, String eventName)
  {
    eventSource.removeListener(listener, eventName);
  }

  /**
   * Paints the outline of the markedState with the currentColor.
   */
  public void paint(Graphics g)
  {
    if (markedState != null && currentColor != null)
    {
      ((Graphics2D) g).setStroke(DEFAULT_STROKE);
      g.setColor(currentColor);

      if (markedState.getAbsolutePointCount() > 0)
      {
        Point last = markedState.getAbsolutePoint(0).getPoint();

        for (int i = 1; i < markedState.getAbsolutePointCount(); i++)
        {
          Point current = markedState.getAbsolutePoint(i).getPoint();
          g.drawLine(last.x - getX(), last.y - getY(), current.x
              - getX(), current.y - getY());
          last = current;
        }
      }
      else
      {
        g.drawRect(1, 1, getWidth() - 3, getHeight() - 3);
      }
    }
  }

}
TOP

Related Classes of com.mxgraph.swing.handler.mxCellMarker

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.