Package org.mt4j.components.visibleComponents.widgets

Source Code of org.mt4j.components.visibleComponents.widgets.MTSvg

/***********************************************************************
* mt4j Copyright (c) 2008 - 2009 Christopher Ruff, Fraunhofer-Gesellschaft All rights reserved.
*   This program is free software: you can redistribute it and/or modify
*   it under the terms of the GNU General Public License as published by
*   the Free Software Foundation, either version 3 of the License, or
*   (at your option) any later version.
*
*   This program is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*   GNU General Public License for more details.
*
*   You should have received a copy of the GNU General Public License
*   along with this program.  If not, see <http://www.gnu.org/licenses/>.
*
***********************************************************************/
package org.mt4j.components.visibleComponents.widgets;

import org.mt4j.components.MTComponent;
import org.mt4j.components.TransformSpace;
import org.mt4j.components.visibleComponents.shapes.AbstractShape;
import org.mt4j.input.gestureAction.DefaultDragAction;
import org.mt4j.input.gestureAction.DefaultRotateAction;
import org.mt4j.input.gestureAction.DefaultScaleAction;
import org.mt4j.input.inputProcessors.componentProcessors.dragProcessor.DragProcessor;
import org.mt4j.input.inputProcessors.componentProcessors.rotateProcessor.RotateProcessor;
import org.mt4j.input.inputProcessors.componentProcessors.scaleProcessor.ScaleProcessor;
import org.mt4j.util.math.Matrix;
import org.mt4j.util.math.Vector3D;
import org.mt4j.util.math.Vertex;
import org.mt4j.util.xml.svg.SVGLoader;

import processing.core.PApplet;

/**
* The Class MTSvg. Loads and displays scalable vector graphics (SVG) files.
*
* @author Christopher Ruff
*/
public class MTSvg extends MTComponent {

  /** The width vect. */
  private Vector3D widthVect;
 
  /** The height vect. */
  private Vector3D heightVect;
 
  /** The width. */
  private float width;
 
  /** The height. */
  private float height;

  /** The center point local. */
  private Vector3D centerPointLocal;

  //TODO we could extens mtpolygon and set the polygon points to be the svg's bounding rectangle
 
  /**
   * Instantiates a new mT svg.
   *
   * @param applet the applet
   * @param fileName the file name
   */
  public MTSvg(PApplet applet, String fileName) {
    super(applet);
   
    this.setName("SVG: " + fileName);
    this.setComposite(true);
   
    this.registerInputProcessor(new DragProcessor(applet));
    this.addGestureListener(DragProcessor.class, new DefaultDragAction());
    this.registerInputProcessor(new RotateProcessor(applet));
    this.addGestureListener(RotateProcessor.class, new DefaultRotateAction());
    this.registerInputProcessor(new ScaleProcessor(applet));
    this.addGestureListener(ScaleProcessor.class, new DefaultScaleAction());
   
    SVGLoader loader = new SVGLoader(applet);
    MTComponent svg = loader.loadSvg(fileName);
    this.addChild(svg);
   
   
    //so lange MTSvg noch nicht an einem vater h�ngt und transform=identity, ist die world width die
    //parent relative width (und local width?)
    //wenn added to parent -> parentrelative width vect * globalMatrix
//    Tools3D.getMinXYMaxXY(Vector3DLists)
     //Float.MAX_VALUE[0]minX, Float.MAX_VALUE[1]minY,  Float.MIN_VALUE[2]maxX,  Float.MIN_VALUE[3]maxY
    float[] bounds = calcBounds(this, new float[]{Float.MAX_VALUE, Float.MIN_VALUE, Float.MAX_VALUE, Float.MIN_VALUE});
//    System.out.println("SVG Bounds -> minX: " + bounds[0] + " minY: " + bounds[2] + " maxX: " + bounds[1] + " maxY: " + bounds[3]);
    float minX = bounds[0];
    float minY = bounds[2];
    float maxX = bounds[1];
    float maxY = bounds[3];
    Vector3D upperLeft   = new Vector3D(minX, minY, 0);
    Vector3D upperRight = new Vector3D(maxX, minY, 0);
    Vector3D lowerRight  = new Vector3D(maxX, maxY, 0);
   
    this.widthVect    = upperRight.getSubtracted(upperLeft);
    this.heightVect   = lowerRight.getSubtracted(upperRight);
    this.width   = maxX-minX;
    this.height = maxY-minY;
   
    this.centerPointLocal = new Vector3D(
        upperLeft.x + ((upperRight.x - upperLeft.x)/2f),
        upperRight.y + ((lowerRight.y - upperRight.y)/2f),
        0);
   
    //System.out.println("Center local " + centerPointLocal);
   
//    this.addStateChangeListener(StateChange.ADDED_TO_PARENT, new StateChangeListener(){
//      @Override
//      public void stateChanged(StateChangeEvent evt) {
//        Vector3D widthCopy = widthVect.getCopy();
//       
//      }
//    });
   
    //Draw this component and its children above
    //everything previously drawn and avoid z-fighting
    this.setDepthBufferDisabled(true);
  }
 
 
  /**
   * Calc bounds.
   *
   * @param currentComp the current comp
   * @param bounds the bounds
   *
   * @return the float[]
   */
  private  float[] calcBounds(MTComponent currentComp, float[] bounds){
    if (currentComp instanceof AbstractShape){
      AbstractShape shape = (AbstractShape)currentComp;
      Vertex[] globalVecs = shape.getVerticesGlobal();
      for (int j = 0; j < globalVecs.length; j++) {
        Vertex v = globalVecs[j];
        if (v.x < bounds[0])
          bounds[0] = v.x;
        if (v.x > bounds[1])
          bounds[1] = v.x;
        if (v.y < bounds[2])
          bounds[2] = v.y;
        if (v.y > bounds[3])
          bounds[3] = v.y;
      }
    }
   
    for(MTComponent child : currentComp.getChildren()){
      bounds = calcBounds(child, bounds);
    }
    return bounds;
  }
 
 
 
//  public float getWidthXY(TransformSpace transformSpace) {
//    switch (transformSpace) {
//    case LOCAL:
//      return this.getWidthXYLocal();
//    case RELATIVE_TO_PARENT:
//      return this.getWidthXYRelativeToParent();
//    case GLOBAL:
//      return this.getWidthXYGlobal();
//    default:
//      return -1;
//    }
//  }
 
 
  /**
* Calculates the width of this shape, by using its
* bounding rect.
* Uses the objects local transform. So the width will be
* relative to the parent only - not the whole world
*
* @return the width xy relative to parent
*
* the width
*/
  public float getWidthXYRelativeToParent() {
    Vector3D p = this.widthVect.getCopy();
    Matrix m = new Matrix(this.getLocalMatrix());
    m.removeTranslationFromMatrix();
    p.transform(m);
    return p.length();
  }
 
 
  /**
   * Gets the "Width vector" and transforms it to world space, then calculates
   * its length.
   *
   * @return the width xy global
   *
   * the Width relative to the world space
   */
  public float getWidthXYGlobal() {
    Vector3D p = this.widthVect.getCopy();
    Matrix m = new Matrix(this.getGlobalMatrix());
    m.removeTranslationFromMatrix();
    p.transform(m);
    return p.length();
  }
 
 
 
//  public float getHeightXY(TransformSpace transformSpace) {
//    switch (transformSpace) {
//    case LOCAL:
//      return this.getHeightXYLocal();
//    case RELATIVE_TO_PARENT:
//      return this.getHeightXYRelativeToParent();
//    case GLOBAL:
//      return this.getHeightXYGlobal();
//    default:
//      return -1;
//    }
//  }
 
  /**
* Gets the "height vector" and transforms it to parent relative space, then calculates
* its length.
*
* @return the height xy relative to parent
*
* the height relative to its parent space frame
*/
  public float getHeightXYRelativeToParent() {
    Vector3D p = this.heightVect.getCopy();
    Matrix m = new Matrix(this.getLocalMatrix());
    m.removeTranslationFromMatrix();
    p.transform(m);
    return p.length();
  }
 
  /**
   * Gets the "height vector" and transforms it to world space, then calculates
   * its length.
   *
   * @return the height xy global
   *
   * the height relative to the world space
   */
  public float getHeightXYGlobal() {
    Vector3D p = this.heightVect.getCopy();
    Matrix m = new Matrix(this.getGlobalMatrix());
    m.removeTranslationFromMatrix();
    p.transform(m);
    return p.length();
  }
 
  /**
   * Scales the shape to the given height relative to parent space.
   * Aspect ratio is preserved! The scaling is done Axis aligned, so
   * shearing might occour if rotated!
   * <br>Uses the shapes bounding shape for calculation.
   *
   * @param height the height
   *
   * @return true, if the height isnt negative
   */
  public boolean setHeightXYRelativeToParent(float height){
    if (height > 0){
      Vector3D centerPoint = this.getCenterPointGlobal();
      this.scale(1/this.getHeightXYRelativeToParent(), 1/this.getHeightXYRelativeToParent(), 1, centerPoint);
      this.scale(height, height, 1, centerPoint);
      return true;
    }else
      return false;
  }
 
 
  /**
   * Scales the shape to the given height relative to world space.
   * Aspect ratio is preserved! The scaling is done Axis aligned, so
   * shearing might occour if rotated!
   * <br>Uses the shapes bounding shape for calculation.
   *
   * @param height the height
   *
   * @return true, if sets the height xy global
   */
  public boolean setHeightXYGlobal(float height){
    if (height > 0){
      Vector3D centerPoint = this.getCenterPointGlobal();
      this.scaleGlobal(1/this.getHeightXYGlobal(), 1/this.getHeightXYGlobal(), 1, centerPoint);
      this.scaleGlobal(height, height, 1, centerPoint);
      return true;
    }else
      return false;
  }
 
 
  /**
   * Scales the shape to the given width relative to parent space.
   * Aspect ratio is preserved!
   * <br>NOTE: The scaling is done Axis aligned, so
   * shearing might occour if rotated before!
   * <br>Uses the shapes bounding shape for calculation.
   *
   * @param width the width
   *
   * @return true, if the width isnt negative
   */
  public boolean setWidthXYRelativeToParent(float width){
    if (width > 0){
      Vector3D centerPoint = this.getCenterPointGlobal();
      this.scale(1/this.getWidthXYRelativeToParent(), 1/this.getWidthXYRelativeToParent(), 1, centerPoint);
      this.scale(width, width, 1, centerPoint);
      return true;
    }else
      return false;
  }
 
 
  /**
   * Scales the shape to the given width relative to world space.
   * Aspect ratio is preserved! The scaling is done Axis aligned, so
   * shearing might occour if rotated!
   * <br>Uses the shapes bounding shape for calculation.
   *
   * @param width the width
   *
   * @return true, if sets the width xy global
   */
  public boolean setWidthXYGlobal(float width){
    if (width > 0){
      Vector3D centerPoint = this.getCenterPointGlobal();
      this.scaleGlobal(1/this.getWidthXYGlobal(), 1/this.getWidthXYGlobal(), 1, centerPoint);
      this.scaleGlobal(width, width, 1, centerPoint);
      return true;
    }else
      return false;
  }
 
 
  /**
   * Sets the size xy relative to parent.
   *
   * @param width the width
   * @param height the height
   *
   * @return true, if successful
   */
  public boolean setSizeXYRelativeToParent(float width, float height){
    if (width > 0 && height > 0){
      Vector3D centerPoint = this.getCenterPointGlobal(); //FIXME use centerRelToParent?
      this.scale(1/this.getWidthXYRelativeToParent(), 1/this.getHeightXYRelativeToParent(), 1, centerPoint);
      this.scale(width, height, 1, centerPoint);
      return true;
    }else
      return false;
  }
 
 
  /**
   * Sets the size xy global.
   *
   * @param width the width
   * @param height the height
   *
   * @return true, if successful
   */
  public boolean setSizeXYGlobal(float width, float height){
    if (width > 0 && height > 0){
      Vector3D centerPoint = this.getCenterPointGlobal();
      this.scaleGlobal(1/this.getWidthXYGlobal(), 1/this.getHeightXYGlobal(), 1, centerPoint);
      this.scaleGlobal(width, height, 1, centerPoint);
      return true;
    }else
      return false;
  }
 
 
 
 
  /**
   * Gets the center point local.
   *
   * @return the center point local
   */
  public Vector3D getCenterPointLocal(){
    return this.centerPointLocal.getCopy();
  }
 
  /**
   * Gets the center point relative to parent.
   *
   * @return the center point relative to parent
   */
  public Vector3D getCenterPointRelativeToParent(){
    Vector3D c = this.centerPointLocal.getCopy();
    c.transform(this.getLocalMatrix());
    return c;
  }
 
  /**
   * Gets the center point global.
   *
   * @return the center point global
   */
  public Vector3D getCenterPointGlobal(){
    Vector3D c = this.centerPointLocal.getCopy();
    c.transform(this.getGlobalMatrix());
    return c;
  }
 
  /**
   * Sets the global position of the component. (In global coordinates)
   * <br>Note: The center of this component is the reference point, not the upper left corner.
   *
   * @param pos the pos
   */
  public void setPositionGlobal(Vector3D pos){
    this.translateGlobal(pos.getSubtracted(this.getCenterPointGlobal()));
  }
 
  /**
   * Sets the position of the component, relative to its parent component.
   * <br>Note: The center of this component is the reference point, not the upper left corner.
   *
   * @param pos the pos
   */
  public void setPositionRelativeToParent(Vector3D pos){
    this.translate(pos.getSubtracted(this.getCenterPointRelativeToParent()), TransformSpace.RELATIVE_TO_PARENT);
  }
 
 
  /**
   * Returns the component with the largest x,y dimension to use for picking by default.
   *
   * @param comp the comp
   * @param compWithBiggestBoundingRect the comp with biggest bounding rect
   * @param biggestWidth the biggest width
   * @param biggestHeight the biggest height
   *
   * @return the largest svg comp
   */
  private AbstractShape getLargestSvgComp(MTComponent comp, AbstractShape compWithBiggestBoundingRect, float biggestWidth, float biggestHeight){
////    System.out.println("Checking: " + comp.getName());
    if (comp instanceof AbstractShape) {
      AbstractShape shape = (AbstractShape) comp;
      float rectWidthGlobal = shape.getWidthXY(TransformSpace.GLOBAL);
      float rectHeightGlobal = shape.getHeightXY(TransformSpace.GLOBAL);
      if (
//          compWithBiggestBoundingRect != null
             biggestWidth > 0
          && biggestHeight > 0
      ){
//        System.out.println("Fromer biggest != null, checking if " + comp.getName() + " is bigger.");
        if rectWidthGlobal   >= compWithBiggestBoundingRect.getWidthXY(TransformSpace.GLOBAL)
          ||   rectHeightGlobal   >= compWithBiggestBoundingRect.getHeightXY(TransformSpace.GLOBAL)
        ){
//          System.out.println(comp.getName() + " is bigger!");
          compWithBiggestBoundingRect = shape;
        }else{
//          System.out.println(compWithBiggestBoundingRect.getName() + " is still bigger");
        }
      }else{
//        System.out.println("Reference is null, take " + comp.getName() + " as the new biggest.");
        compWithBiggestBoundingRect = shape;
      }
    }

    for(MTComponent child : comp.getChildren()){
      compWithBiggestBoundingRect = getLargestSvgComp(child, compWithBiggestBoundingRect, biggestWidth, biggestHeight);
    }
    return compWithBiggestBoundingRect;
  }
 
  /* (non-Javadoc)
   * @see org.mt4j.components.MTComponent#setPickable(boolean)
   */
  @Override
  public void setPickable(boolean pickable) {
    super.setPickable(pickable);
    setPickableRecursive(this, pickable);
  }
 
  /**
   * Sets the pickable recursive.
   *
   * @param current the current
   * @param pickable the pickable
   */
  private void setPickableRecursive(MTComponent current, boolean pickable){
    if (!current.equals(this))
        current.setPickable(pickable);
    MTComponent[] children = current.getChildren();
    for (int i = 0; i < children.length; i++) {
      MTComponent child = children[i];
      setPickableRecursive(child, pickable);
    }
  }
}
TOP

Related Classes of org.mt4j.components.visibleComponents.widgets.MTSvg

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.