Package ca.nengo.ui.lib.world.piccolo.objects

Source Code of ca.nengo.ui.lib.world.piccolo.objects.BoundsHandle

package ca.nengo.ui.lib.world.piccolo.objects;

/*
* Copyright (c) 2002-@year@, University of Maryland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions
* and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
* and the following disclaimer in the documentation and/or other materials provided with the
* distribution.
*
* Neither the name of the University of Maryland nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* Piccolo was written at the Human-Computer Interaction Laboratory www.cs.umd.edu/hcil by Jesse Grosjean
* under the supervision of Ben Bederson. The Piccolo website is www.cs.umd.edu/hcil/piccolo.
*/

import java.awt.Cursor;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.Iterator;

import javax.swing.SwingConstants;

import ca.nengo.ui.lib.world.piccolo.WorldObjectImpl;
import edu.umd.cs.piccolo.PCamera;
import edu.umd.cs.piccolo.PNode;
import edu.umd.cs.piccolo.event.PBasicInputEventHandler;
import edu.umd.cs.piccolo.event.PInputEvent;
import edu.umd.cs.piccolo.util.PBounds;
import edu.umd.cs.piccolo.util.PDimension;
import edu.umd.cs.piccolo.util.PPickPath;
import edu.umd.cs.piccolox.handles.PHandle;
import edu.umd.cs.piccolox.util.PBoundsLocator;

/**
* <b>PBoundsHandle</b> a handle for resizing the bounds of another node. If a
* bounds handle is dragged such that the other node's width or height becomes
* negative then the each drag handle's locator assciated with that other node
* is "flipped" so that they are attached to and dragging a different corner of
* the nodes bounds.
* <P>
*
* @version 1.0
* @author Jesse Grosjean
*/
public class BoundsHandle extends PHandle {

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

  public static void addBoundsHandlesTo(WorldObjectImpl wo) {
    PNode aNode = wo.getPiccolo();
    aNode
        .addChild(new BoundsHandle(PBoundsLocator
            .createEastLocator(aNode)));
    aNode
        .addChild(new BoundsHandle(PBoundsLocator
            .createWestLocator(aNode)));
    aNode.addChild(new BoundsHandle(PBoundsLocator
        .createNorthLocator(aNode)));
    aNode.addChild(new BoundsHandle(PBoundsLocator
        .createSouthLocator(aNode)));
    aNode.addChild(new BoundsHandle(PBoundsLocator
        .createNorthEastLocator(aNode)));
    aNode.addChild(new BoundsHandle(PBoundsLocator
        .createNorthWestLocator(aNode)));
    aNode.addChild(new BoundsHandle(PBoundsLocator
        .createSouthEastLocator(aNode)));
    aNode.addChild(new BoundsHandle(PBoundsLocator
        .createSouthWestLocator(aNode)));
  }

  public static void addStickyBoundsHandlesTo(PNode aNode, PCamera camera) {
    camera.addChild(new BoundsHandle(PBoundsLocator
        .createEastLocator(aNode)));
    camera.addChild(new BoundsHandle(PBoundsLocator
        .createWestLocator(aNode)));
    camera.addChild(new BoundsHandle(PBoundsLocator
        .createNorthLocator(aNode)));
    camera.addChild(new BoundsHandle(PBoundsLocator
        .createSouthLocator(aNode)));
    camera.addChild(new BoundsHandle(PBoundsLocator
        .createNorthEastLocator(aNode)));
    camera.addChild(new BoundsHandle(PBoundsLocator
        .createNorthWestLocator(aNode)));
    camera.addChild(new BoundsHandle(PBoundsLocator
        .createSouthEastLocator(aNode)));
    camera.addChild(new BoundsHandle(PBoundsLocator
        .createSouthWestLocator(aNode)));
  }

  @SuppressWarnings("unchecked")
    public static void removeBoundsHandlesFrom(WorldObjectImpl wo) {
    PNode aNode = wo.getPiccolo();

    ArrayList<BoundsHandle> handles = new ArrayList<BoundsHandle>();

    Iterator<PNode> i = aNode.getChildrenIterator();
    while (i.hasNext()) {
      PNode each = i.next();
      if (each instanceof BoundsHandle) {
        handles.add((BoundsHandle) each);
      }
    }
    aNode.removeChildren(handles);
  }

  private transient PBasicInputEventHandler handleCursorHandler;

  public BoundsHandle(PBoundsLocator aLocator) {
    super(aLocator);
  }

  @Override
  protected void installHandleEventHandlers() {
    super.installHandleEventHandlers();
    handleCursorHandler = new PBasicInputEventHandler() {
      boolean cursorPushed = false;

      @Override
      public void mouseEntered(PInputEvent aEvent) {
        if (!cursorPushed) {
          aEvent
              .pushCursor(getCursorFor(((PBoundsLocator) getLocator())
                  .getSide()));
          cursorPushed = true;
        }
      }

      @Override
      public void mouseExited(PInputEvent aEvent) {
        PPickPath focus = aEvent.getInputManager().getMouseFocus();
        if (cursorPushed) {
          if (focus == null
              || focus.getPickedNode() != BoundsHandle.this) {
            aEvent.popCursor();
            cursorPushed = false;
          }
        }
      }

      @Override
      public void mouseReleased(PInputEvent event) {
        if (cursorPushed) {
          event.popCursor();
          cursorPushed = false;
        }
      }
    };
    addInputEventListener(handleCursorHandler);
  }

  @Override
  public void dragHandle(PDimension aLocalDimension, PInputEvent aEvent) {
    PBoundsLocator l = (PBoundsLocator) getLocator();

    PNode n = l.getNode();
    PBounds b = n.getBounds();

    PNode parent = getParent();
    if (parent != n && parent instanceof PCamera) {
      ((PCamera) parent).localToView(aLocalDimension);
    }

    localToGlobal(aLocalDimension);
    n.globalToLocal(aLocalDimension);

    double dx = aLocalDimension.getWidth();
    double dy = aLocalDimension.getHeight();

    switch (l.getSide()) {
    case SwingConstants.NORTH:
      b.setRect(b.x, b.y + dy, b.width, b.height - dy);
      break;

    case SwingConstants.SOUTH:
      b.setRect(b.x, b.y, b.width, b.height + dy);
      break;

    case SwingConstants.EAST:
      b.setRect(b.x, b.y, b.width + dx, b.height);
      break;

    case SwingConstants.WEST:
      b.setRect(b.x + dx, b.y, b.width - dx, b.height);
      break;

    case SwingConstants.NORTH_WEST:
      b.setRect(b.x + dx, b.y + dy, b.width - dx, b.height - dy);
      break;

    case SwingConstants.SOUTH_WEST:
      b.setRect(b.x + dx, b.y, b.width - dx, b.height + dy);
      break;

    case SwingConstants.NORTH_EAST:
      b.setRect(b.x, b.y + dy, b.width + dx, b.height - dy);
      break;

    case SwingConstants.SOUTH_EAST:
      b.setRect(b.x, b.y, b.width + dx, b.height + dy);
      break;
    }

    boolean flipX = false;
    boolean flipY = false;

    if (b.width < 0) {
      flipX = true;
      b.width = -b.width;
      b.x -= b.width;
    }

    if (b.height < 0) {
      flipY = true;
      b.height = -b.height;
      b.y -= b.height;
    }

    if (flipX || flipY) {
      flipSiblingBoundsHandles(flipX, flipY);
    }

    /*
     * Edit by "shuwu83@gmail.com" Bound beginnings are kept constant while
     * the offset is changed by the handles
     */
    n.translate(b.x, b.y);
    b.x = 0;
    b.y = 0;
    /*
     * End edit
     */

    n.setBounds(b);
  }

  @Override
  public void endHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) {
    PBoundsLocator l = (PBoundsLocator) getLocator();
    l.getNode().endResizeBounds();
  }

  public void flipHandleIfNeeded(boolean flipX, boolean flipY) {
    PBoundsLocator l = (PBoundsLocator) getLocator();

    if (flipX || flipY) {
      switch (l.getSide()) {
      case SwingConstants.NORTH: {
        if (flipY) {
          l.setSide(SwingConstants.SOUTH);
        }
        break;
      }

      case SwingConstants.SOUTH: {
        if (flipY) {
          l.setSide(SwingConstants.NORTH);
        }
        break;
      }

      case SwingConstants.EAST: {
        if (flipX) {
          l.setSide(SwingConstants.WEST);
        }
        break;
      }

      case SwingConstants.WEST: {
        if (flipX) {
          l.setSide(SwingConstants.EAST);
        }
        break;
      }

      case SwingConstants.NORTH_WEST: {
        if (flipX && flipY) {
          l.setSide(SwingConstants.SOUTH_EAST);
        } else if (flipX) {
          l.setSide(SwingConstants.NORTH_EAST);
        } else if (flipY) {
          l.setSide(SwingConstants.SOUTH_WEST);
        }

        break;
      }

      case SwingConstants.SOUTH_WEST: {
        if (flipX && flipY) {
          l.setSide(SwingConstants.NORTH_EAST);
        } else if (flipX) {
          l.setSide(SwingConstants.SOUTH_EAST);
        } else if (flipY) {
          l.setSide(SwingConstants.NORTH_WEST);
        }
        break;
      }

      case SwingConstants.NORTH_EAST: {
        if (flipX && flipY) {
          l.setSide(SwingConstants.SOUTH_WEST);
        } else if (flipX) {
          l.setSide(SwingConstants.NORTH_WEST);
        } else if (flipY) {
          l.setSide(SwingConstants.SOUTH_EAST);
        }
        break;
      }

      case SwingConstants.SOUTH_EAST: {
        if (flipX && flipY) {
          l.setSide(SwingConstants.NORTH_WEST);
        } else if (flipX) {
          l.setSide(SwingConstants.SOUTH_WEST);
        } else if (flipY) {
          l.setSide(SwingConstants.NORTH_EAST);
        }
        break;
      }
      }
    }

    // reset locator to update layout
    setLocator(l);
  }

  @SuppressWarnings("unchecked")
  public void flipSiblingBoundsHandles(boolean flipX, boolean flipY) {
    Iterator<Object> i = getParent().getChildrenIterator();
    while (i.hasNext()) {
      Object each = i.next();
      if (each instanceof BoundsHandle) {
        ((BoundsHandle) each).flipHandleIfNeeded(flipX, flipY);
      }
    }
  }

  public Cursor getCursorFor(int side) {
    switch (side) {
    case SwingConstants.NORTH:
      return new Cursor(Cursor.N_RESIZE_CURSOR);

    case SwingConstants.SOUTH:
      return new Cursor(Cursor.S_RESIZE_CURSOR);

    case SwingConstants.EAST:
      return new Cursor(Cursor.E_RESIZE_CURSOR);

    case SwingConstants.WEST:
      return new Cursor(Cursor.W_RESIZE_CURSOR);

    case SwingConstants.NORTH_WEST:
      return new Cursor(Cursor.NW_RESIZE_CURSOR);

    case SwingConstants.SOUTH_WEST:
      return new Cursor(Cursor.SW_RESIZE_CURSOR);

    case SwingConstants.NORTH_EAST:
      return new Cursor(Cursor.NE_RESIZE_CURSOR);

    case SwingConstants.SOUTH_EAST:
      return new Cursor(Cursor.SE_RESIZE_CURSOR);
    }
    return null;
  }

  /**
   * Return the event handler that is responsible for setting the mouse cursor
   * when it enters/exits this handle.
   */
  public PBasicInputEventHandler getHandleCursorEventHandler() {
    return handleCursorHandler;
  }

  @Override
  public void startHandleDrag(Point2D aLocalPoint, PInputEvent aEvent) {
    PBoundsLocator l = (PBoundsLocator) getLocator();
    l.getNode().startResizeBounds();
  }
}
TOP

Related Classes of ca.nengo.ui.lib.world.piccolo.objects.BoundsHandle

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.