Package gwt.g2d.client.mouse

Source Code of gwt.g2d.client.mouse.MouseSurface$Handlers

package gwt.g2d.client.mouse;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Vector;

import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.canvas.dom.client.Context2d.Composite;


import gwt.g2d.client.graphics.ImageData;
import gwt.g2d.client.graphics.Surface;
import gwt.g2d.shared.Color;
import gwt.g2d.shared.math.Rectangle;
import gwt.g2d.shared.math.Vector2;

/**
* A mouse surface is tied to a normal surface, and registers different shapes that can be checked for
* clicks or hovers form the mouse. This system works with any complex shape, and will detect hovers/clicks on
* all non-transparent areas in the drawn shape or image.
* @author Karel
*
*/
public class MouseSurface {
 
  // handlers
  private class Handlers {
    public SurfaceClickHandler clickHandler;
    public SurfaceMouseOutHandler mouseOutHandler;
    public SurfaceMouseOverHandler mouseOverHandler;
    public SurfaceMouseMoveHandler mouseMoveHandler;
  };
 
  // the surface we are tied to
  Surface fOriginalSurface;
 
  // original context
  Context2d fOriginalContext;
 
  // the temporary surface which is used to draw on during mouse registration
  public Surface fTempSurface = null;
 
  // current id
  Long fCurrentId = null;
 
  // map of id to handlers
  Map<Long, Handlers> fIdToHandlers = new HashMap<Long, Handlers>();
 
  // map of id to surface (used for checking against this specific collision)
  Map<Long, Surface> fIdToSurface = new HashMap<Long, Surface>();
 
  // drag handlers
  Vector<SurfaceMouseDragHandler> fDragHandlers = new Vector<SurfaceMouseDragHandler>();
 
  // the id where the drag begin
  Long fStartDragId = null;
 
  // the position where the drag began
  Vector2 fStartDragLoc = null;
 
  // list of id's in the order in which they were drawn - used to make sure that only the topmost object is actually triggered
  List<Long> fIds = new LinkedList<Long>();
 
  // last color
  Color fCurrentColor = new Color(200, 200, 0);
 
  // last id that was hovered by the mouse
  Long fLastId = null;
 
  // does this surface has move handlers - otherwise, don't perform the calculations
  boolean fHasMoveHandlers = false;
 
 
  // create a new mouse surface
  public MouseSurface(Surface originalSurface) {
    fOriginalSurface = originalSurface;
    fOriginalContext = fOriginalSurface.getContext();
  }
 
 
  // start registering a new clickable surface
  public void startRegister(Long id) {
   
    // set id
    fCurrentId = id;
   
    // surface
    Surface surface = null;
   
    // doesn't exist yet - create a new canvas
    if (!fIdToSurface.containsKey(id)) {
      surface = new Surface(fOriginalSurface.getCoordinateSpaceWidth(), fOriginalSurface.getCoordinateSpaceHeight());
      fIdToSurface.put(id,  surface);
      fIdToHandlers.put(id, new Handlers());
      fIds.add(id);
    }
   
    // exist - get the existing canvas
    else {
     
      // get the surface
      surface = fIdToSurface.get(id);
      surface.clear();
     
      // find the position of this id, and put it at the end of our draw list
      fIds.remove(id);
      fIds.add(id);
    }
   
    // start drawing on the temp surface now
    fTempSurface = surface;
    fOriginalSurface.replaceContext(fTempSurface.getContext());
  }
 
 
  // stop registering
  public void stopRegister(boolean draw) {
   
    // invalid - surface doesn't exist
    if (fTempSurface == null) return;
   
    // switch back to the original context
    fOriginalSurface.replaceContext(fOriginalContext);
    if (draw) fOriginalSurface.drawImage(fTempSurface.getCanvasElement(), 0, 0, fTempSurface.getCoordinateSpaceWidth(), fTempSurface.getCoordinateSpaceHeight());
   
    // done
    fCurrentId = null;
    fTempSurface = null;
   

  }
 
 
  // next color
  private void generateNextColor() {
    fCurrentColor = new Color(fCurrentColor.red, fCurrentColor.green, fCurrentColor.blue+1);
    if (fCurrentColor.blue > 255) {
      fCurrentColor = new Color(fCurrentColor.red, fCurrentColor.green+1, 0);
      if (fCurrentColor.green > 255) {
        fCurrentColor = new Color(fCurrentColor.red+1, 0, 0);
        if (fCurrentColor.red > 255) {
          fCurrentColor = new Color(0, 0, 0); // reset back to zero
        }
      }
    }
  }
 
 
  // active?
  public boolean isActive() {
    return fCurrentId != null;
  }
 
 
  // add click handler
  public void addClickHandler(SurfaceClickHandler handler) {
    if (fCurrentId == null) return;
    Handlers handlers = fIdToHandlers.get(fCurrentId);
    if (handlers == null) return;
    handlers.clickHandler = handler;
  }
 
 
  // add mouse down handler
  public void addMouseDragHandler(SurfaceMouseDragHandler handler) {
    fDragHandlers.add(handler);
  }
 
  // add mouse over handler
  public void addMouseOverHandler(SurfaceMouseOverHandler handler) {
    if (fCurrentId == null) return;
    Handlers handlers = fIdToHandlers.get(fCurrentId);
    if (handlers == null) return;
    handlers.mouseOverHandler = handler;
    fHasMoveHandlers = true;
  }
 
 
  // add mouse out handler
  public void addMouseOutHandler(SurfaceMouseOutHandler handler) {
    if (fCurrentId == null) return;
    Handlers handlers = fIdToHandlers.get(fCurrentId);
    if (handlers == null) return;
    handlers.mouseOutHandler = handler;
    fHasMoveHandlers = true;
  }
 
 
  // add mouse move handler
  public void addMouseMoveHandler(SurfaceMouseMoveHandler handler) {
    if (fCurrentId == null) return;
    Handlers handlers = fIdToHandlers.get(fCurrentId);
    if (handlers == null) return;
    handlers.mouseMoveHandler = handler;
    fHasMoveHandlers = true;
  }
 
 
  /**
   * We clicked on the canvas - check where we clicked exactly.
   */
  public void onClick(int x, int y) {
   
    // get all different canvases and check for a collision
    ListIterator<Long> it = fIds.listIterator(fIds.size());
    while (it.hasPrevious()) {
      Long id = it.previous();
      Surface surface = fIdToSurface.get(id);
     
      // get the color at the given location
      ImageData data = surface.getImageData(x, y, 1, 1);
      double alpha = data.getAlpha(0, 0);
     
      // hit is not transparent - we got a hit!
      if (alpha > Double.MIN_VALUE) {
       
        // look up color
        Handlers handlers = fIdToHandlers.get(id);
        if (handlers != null && handlers.clickHandler != null) handlers.clickHandler.onClick(new Vector2(x, y), id);
        return;

      }
    }
  }
 
 
  /**
   * We put our mouse down on the canvas - check where we clicked exactly.
   */
  public void onMouseDown(int x, int y) {
   
    // perform one single onMouseMove call to detect where we are
    fStartDragLoc = new Vector2(x, y);
    onMouseMove(x, y);
   
    // set the id matched by onMouseMove
    fStartDragId = fLastId;
   
    // let all handlers know
    for (SurfaceMouseDragHandler handler : fDragHandlers) {
      handler.onDragStart(fStartDragLoc, fStartDragId);
    }
  }
 
 
  /**
   * We lifted up our mouse on the canvas - check where we clicked exactly.
   */
  public void onMouseUp(int x, int y) {
   
    // let all handlers know
    for (SurfaceMouseDragHandler handler : fDragHandlers) {
      handler.onDragStop(fStartDragLoc, new Vector2(x, y), fStartDragId, fLastId);
    }
   
    // disable the onMouseMove calls again by setting fStartDragLoc to null
    fStartDragId = null;
    fStartDragLoc = null;
  }
 
 
  /**
   * We're entering the canvas - check if we entered immediately on an object.
   */
  public void onMouseOver(int x, int y) {
    if (!fHasMoveHandlers) return;
   
    // get all different canvases and check for a collision
    ListIterator<Long> it = fIds.listIterator(fIds.size());
    while (it.hasPrevious()) {
      Long id = it.previous();
      Surface surface = fIdToSurface.get(id);
     
      // get the color at the given location
      ImageData data = surface.getImageData(x, y, 1, 1);
      double alpha = data.getAlpha(0, 0);
     
      // hit is not transparent - we got a hit!
      if (alpha > Double.MIN_VALUE) {
       
        // we entered on an object, signal it
        Handlers handlers = fIdToHandlers.get(id);
        if (handlers != null && handlers.mouseOverHandler != null) handlers.mouseOverHandler.onMouseOver(new Vector2(x, y), id);
        fLastId = id;
        return;
      }
    }
  }
 
  /**
   * We left the surface - make sure we send the last selected object a message.
   */
  public void onMouseOut(int x, int y) {
    if (!fHasMoveHandlers) return;
   
    // no entity selected when we left the surface - don't do anything
    if (fLastId == null) return;
   
    // look up color
    Handlers handlers = fIdToHandlers.get(fLastId);
    if (handlers != null && handlers.mouseOutHandler != null) handlers.mouseOutHandler.onMouseOut(new Vector2(x, y));
    fLastId = null;
  }
 
  /**
   * We moved the mouse over the canvas - check for collision with a registered object.
   */
  public void onMouseMove(int x, int y) {
    if (!fHasMoveHandlers && fStartDragLoc == null) return;
   
    // get all different canvases and check for a collision
    boolean hit = false;
    ListIterator<Long> it = fIds.listIterator(fIds.size());
    while (it.hasPrevious()) {
      Long id = it.previous();
      Surface surface = fIdToSurface.get(id);
     
      // get the color at the given location
      ImageData data = surface.getImageData(x, y, 1, 1);
      double alpha = data.getAlpha(0, 0);
     
      // hit is not transparent - we got a hit!
      if (alpha > Double.MIN_VALUE) {
        hit = true;
       
        // we were hovering over another id and now we're hovering over nothing or a new id - send a mouse out event
        if (fLastId != null && fLastId != id) {
          Handlers handlers = fIdToHandlers.get(fLastId);
          if (handlers != null && handlers.mouseOutHandler != null) handlers.mouseOutHandler.onMouseOut(new Vector2(x, y));
          fLastId = null;
         
        }
       
        // we enter a new object
        if (fLastId == null) {
          fLastId = id;
          Handlers handlers = fIdToHandlers.get(fLastId);
          if (handlers != null && handlers.mouseOverHandler != null) handlers.mouseOverHandler.onMouseOver(new Vector2(x, y), fLastId);
        }
       
        // we were already on this object, but we moved the mouse
        else {
          Handlers handlers = fIdToHandlers.get(fLastId);
          if (handlers != null && handlers.mouseMoveHandler != null) handlers.mouseMoveHandler.onMouseMove(new Vector2(x, y), fLastId);
        }
       
        // only process one hit
        break;
      }
    }
   
    // update drag
    if (fStartDragLoc != null) {
      for (SurfaceMouseDragHandler handler : fDragHandlers) {
        handler.onDragChange(fStartDragLoc, new Vector2(x, y), fStartDragId, fLastId);
      }
    }
   
    // we got here - this means there was no hit
    // if we were above an object in the previous cycle, let it know we left
    if (!hit) {
      Handlers handlers = fIdToHandlers.get(fLastId);
      if (handlers != null && handlers.mouseOutHandler != null) handlers.mouseOutHandler.onMouseOut(new Vector2(x, y));
      fLastId = null;
    }
  }
}
TOP

Related Classes of gwt.g2d.client.mouse.MouseSurface$Handlers

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.