Package jsynoptic.builtin

Source Code of jsynoptic.builtin.PlotZoom

/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info:  http://jsynoptic.sourceforge.net/index.html
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2006, by :
*     Corporate:
*         EADS Astrium SAS
*     Individual:
*         Claude Cazenave
*
*
* $$Id$$
*
*/
package jsynoptic.builtin;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;

import javax.swing.event.UndoableEditEvent;
import javax.swing.undo.CompoundEdit;

import jsynoptic.builtin.Plot.PlotCompoundEdit;

import simtools.diagram.DiagramComponent;
import simtools.diagram.DiagramParameters;
import simtools.diagram.DiagramSelection;
import simtools.diagram.DiagramSelectionListener;

/**
* This class performs the additional drawing required to perform some zooms
* on one or several selected plots
*
* Zoom box
*  - Its location and size are defined thanks to mouse events received through the ContextualDrawing
* interface.When zoom defintion is over, on button 2 release, the rectangle
* coordinates are used to compute the zoom aplied to the selected plots.
* If there is one plot selected then the zoom concerns all the axes
* (even the secondary axes if thy exist). If there is more than a plot
* selected, the zoom is restricted to the axis with intersection with the
* zoom rectangle. In that case only one axis is changed but it is done
* on all the selected plots.
*  - A red dashed rectangle is drawn.
* Zoom wheel
*   - Its location and direction of rotation are defined thanks to mouse events received through the ContextualDrawing
* interface. Zoom wheel is performed on the selected plot that contains mouse position. Zoom whell
* concerns all the axes (even the secondary axes if thy exist).
*
* Translation
*  *  -  The translation vector is defined thanks to mouse events received through the ContextualDrawing
* interface. The translation concerns all the axes and all the selected plots.
*
*/
public class PlotZoom implements DiagramComponent.ContextualDrawing, DiagramSelectionListener{
 
  /** Kind of zoom  */
  protected int kindOfZoom;
  protected final static int  ZOOM_BOX  = 0;
  protected final static int  ZOOM_WHEEL  = 1;
  protected final static int  TRANSLATION  = 2;
 
 
  /** Zoom coordinates */
  protected int x1,y1,x2,y2;
 
  /** the plot on which the zoom definition starts */
  protected Plot plot1;
 
  /** on TRANSLATION: Zoom wheel factor */
  protected final static double  zoomWheelFactor  = 1.25;
 
  /**  on ZOOM_BOX, current selection on which the zoom will aply */
  final DiagramSelection selection;
 
  /** on ZOOM_BOX, the zoom area line color */
  protected static Color zoomColor=Color.red;
 
  /** on ZOOM_BOX, a stroke used to display the zoom rectangle */
  protected static BasicStroke dashStroke;
  static{
    float[] df={2.f,2.f};
    dashStroke=new BasicStroke(0.1f,
          BasicStroke.CAP_SQUARE,
          BasicStroke.JOIN_MITER,
          1.f, df,0.f);
  }
 
  /** on ZOOM_BOX, the zoom area shape */
  protected Rectangle zoomArea;
 
  /**  on ZOOM_BOX, is true when the 2 pairs of coordinates are valid */
  boolean twoPoints;

  /** on TRANSLATION: During draging operation, , several translation are performed, but a unique event is stored into undo operation stack.*/
  protected boolean firstTranslation;

 
  /**
   * Creates a new PlotZoom for the current selection
   * @param sel the selection to zoom
   */
  public PlotZoom(DiagramSelection sel){
    selection=sel;
    zoomArea=new Rectangle();
    twoPoints=false;
    plot1=null;
    firstTranslation=false;
  }
 

  /* (non-Javadoc)
   * @see simtools.diagram.DiagramComponent.ContextualDrawing#consumeKeyEvent(java.awt.event.KeyEvent)
   */
  public boolean consumeKeyEvent(KeyEvent e){
      if ((e.getModifiers() & KeyEvent.CTRL_MASK)== KeyEvent.CTRL_MASK){

          if (e.getKeyCode() == KeyEvent.VK_GREATER) {
              wheel(0, 0, true);
              return true;

          } else if (e.getKeyCode() == KeyEvent.VK_LESS) {
              wheel(0, 0, false);
              return true;
          }
      }
     
      return false;
  }
 

  /* (non-Javadoc)
   * @see simtools.diagram.DiagramComponent.ContextualDrawing#consumeMouseEvent(java.awt.event.MouseEvent)
   */
  public boolean consumeMouseEvent(MouseEvent e) {
    switch (e.getID()) {
    case MouseEvent.MOUSE_PRESSED:
      if(DiagramComponent.isMouseButton2(e)){
        if(selection.getElementContainer().getComponent().getContextualDrawing()==this){
         
          if ((e.getModifiers()&MouseEvent.CTRL_MASK)==MouseEvent.CTRL_MASK){
            kindOfZoom = PlotZoom.TRANSLATION;
          }else{
            kindOfZoom = PlotZoom.ZOOM_BOX;
          }
          press(e.getX(),e.getY());
        }
        else{
          abort();
        }
        return true;
      }
      return false;
    case MouseEvent.MOUSE_RELEASED:
      if(DiagramComponent.isMouseButton2(e) && selection.getElementContainer().getComponent().getContextualDrawing()==this){
        release(e.getX(),e.getY());
        return true;
      }
      return false;
    case MouseEvent.MOUSE_DRAGGED:
      if(DiagramComponent.isMouseButton2(e) && selection.getElementContainer().getComponent().getContextualDrawing()==this){
        drag(e.getX(),e.getY());
        return true;
      }
      return false;
    case MouseEvent.MOUSE_WHEEL:
      if(selection.getElementContainer().getComponent().getContextualDrawing()==this){
        if (e instanceof MouseWheelEvent) {
          kindOfZoom = PlotZoom.ZOOM_WHEEL;
          wheel(e.getX(),e.getY(), (((MouseWheelEvent)e).getWheelRotation()<0));
          return true;
        }
        return false;

      }
    default:
      return false;
    }
  }

 
  /**
   * make a zoom wheel
   * @param x
   * @param y
   * @param zoomIn
   */
  protected void wheel(int x,int y, boolean zoomIn){
    DiagramParameters param = selection.getElementContainer().getComponent().getParameters();
   
    x1 = (int) ((double) x / param.scale) - param.xmargin;
    y1 = (int) ((double) y / param.scale) - param.ymargin;
    plot1=getSelectedPlot(x1,y1);
   
    if(plot1==null){
      abort();
      return;
    }

    CompoundEdit ce=null;

    //  simple zoom, all the axes are taken into account
    HashMap plot1OldValues=plot1.getAxesProperties(null, -1);
    plot1.zoomWheel(x1, y1, PlotZoom.zoomWheelFactor, zoomIn);
    ce=plot1.new PlotCompoundEdit(plot1OldValues);
    plot1.repaintDiagram(plot1.getBounds());

    // store undoable event
    selection.getElementContainer().getComponent().fireUndoableEditUpdate(new UndoableEditEvent(selection.getElementContainer().getComponent(), ce));
    selection.getElementContainer().getComponent().repaint();

    // end of drawing
    plot1=null;
    twoPoints = false;
    selection.getElementContainer().getComponent().setContextualDrawing(null); // end
  }
 
  /**
   * Abort the zoom
   */
  public void abort(){
    plot1=null;
    twoPoints = false;
 
    // end of drawing
    selection.getElementContainer().getComponent().setContextualDrawing(null); // end
  }
 
  /**
   * Start the zoom at the mouse pressed location
   * @param x mouse location X coordinate
   * @param y mouse location Y coordinate
   */
  public void press(int x, int y){
    DiagramParameters param = selection.getElementContainer().getComponent()
            .getParameters();
    x1 = (int) ((double) x / param.scale) - param.xmargin;
    y1 = (int) ((double) y / param.scale) - param.ymargin;
    plot1=getSelectedPlot(x1,y1);
   
    if (kindOfZoom== PlotZoom.ZOOM_BOX)
      twoPoints = false;
   
    if (kindOfZoom== PlotZoom.TRANSLATION)
      firstTranslation=true;
  }
 
  /**
   * Extends the zoom area according to dragged mouse location
   * @param x mouse location X coordinate
   * @param y mouse location Y coordinate
   */
  public void drag(int x,int y){
    displayCrossLocation(x,y);
    DiagramParameters param = selection.getElementContainer().getComponent()
    .getParameters();
    x2 = (int) ((double) x / param.scale) - param.xmargin;
    y2 = (int) ((double) y / param.scale) - param.ymargin;
   
    if (kindOfZoom==PlotZoom.ZOOM_BOX){
      selection.getElementContainer().getComponent().repaint();
      twoPoints = true;
    }
    else if (kindOfZoom==PlotZoom.TRANSLATION){
      translate();
    }
  }
 
  /**
   * When the mouse is released, do the zoom according to zoom
   * area definition
   * @param x mouse location X coordinate
   * @param y mouse location Y coordinate
   */
  public void release(int x, int y){
    if (kindOfZoom==PlotZoom.ZOOM_BOX){
      DiagramParameters param = selection.getElementContainer().getComponent()
      .getParameters();
      x2 = (int) ((double) x / param.scale) - param.xmargin;
      y2 = (int) ((double) y / param.scale) - param.ymargin;

      // 1) look for the first shape with
      // an overlap with zoom rectangle
      Plot plot2 = getSelectedPlot(x2,y2);
      if(plot1==null && plot2!=null){
        plot1=plot2;
      }
      if(plot1==null){
        abort();
        return;
      }
      // 1 check if a collective zoom on primary or secondary
      // axes has to be performed
      // The criterion is same variable name (but not same data source)
      HashSet collectivePlots=new HashSet();
      for (int i = 0; i < selection.getShapeCount(); i++) {
          Shape s = selection.getShape(i);
          if (s instanceof Plot && s != plot1) {
              Plot plot=(Plot)s;

              collectivePlots.add(plot);     
          }
      }

      // do the zoom
      CompoundEdit ce=null;
      if(collectivePlots.isEmpty()){
        // a simple zoom, all the exes are taken into account
        HashMap plot1OldValues=plot1.getAxesProperties(null, -1);
        plot1.zoom(x1, x2, y1, y2, false);
        ce=plot1.new PlotCompoundEdit(plot1OldValues);
        plot1.repaintDiagram(plot1.getBounds());
      }
      else{
        // a collective zoom
        ce = new CompoundEdit();
        HashMap plot1OldValues=plot1.getAxesProperties(null, Plot.PX);
        if(plot1.secondaryX!=null){
          plot1.getAxesProperties(plot1OldValues, Plot.SX);
        }
        // X axes zoom only
        plot1.zoom(x1, x2, 0., 0., true);
        PlotCompoundEdit ce1=plot1.new PlotCompoundEdit(plot1OldValues);
        plot1.repaintDiagram(plot1.getBounds());
        ce.addEdit(ce1);
        // apply plot1 X axes properties to the other compliants plots
        Iterator it=collectivePlots.iterator();
        while(it.hasNext()){
          Plot plot=(Plot)it.next();
          HashMap oldValues=plot.getAxesProperties(null, Plot.PX);
          if(plot.secondaryX!=null){
            plot.getAxesProperties(oldValues, Plot.SX);
          }
          Iterator vit=oldValues.keySet().iterator();
          while(vit.hasNext()){
            String k=(String)vit.next();
            plot.setPropertyValue(k,plot1.getPropertyValue(k));
          }
          PlotCompoundEdit ce2=plot.new PlotCompoundEdit(oldValues);
          plot.repaintDiagram(plot.getBounds());
          ce.addEdit(ce2);
        }
        ce.end();
      }
      // store undoable event
      selection.getElementContainer().getComponent().fireUndoableEditUpdate(new UndoableEditEvent(selection.getElementContainer().getComponent(), ce));
      selection.getElementContainer().getComponent().repaint();


    }
    // end of drawing
    plot1=null;
    twoPoints = false;
    selection.getElementContainer().getComponent().setContextualDrawing(null); // end
  }


 
  /**
   * When the mouse is released, do the translation according to the vector (x1,y1) (x2,y2)
   * @param x mouse location X coordinate
   * @param y mouse location Y coordinate
   */
  public void translate(){
 
    // look for the first shape with an overlap with zoom rectangle
    Plot plot2 = getSelectedPlot(x2,y2);
    if(plot1==null && plot2!=null){
      plot1=plot2;
    }
    if(plot1==null){
      abort();
      return;
    }
    // collective translation
    HashSet collectivePlots=new HashSet();
    for (int i = 0; i < selection.getShapeCount(); i++) {
      Shape s = selection.getShape(i);
      if (s instanceof Plot && s != plot1) {
        collectivePlots.add(s);
      }
    }
   
    // Make the translation
    CompoundEdit ce=null;
    if(collectivePlots.isEmpty()){
      // a simple translation, all the exes are taken into account
      if (firstTranslation){
        HashMap plot1OldValues=plot1.getAxesProperties(null, -1);
        ce=plot1.new PlotCompoundEdit(plot1OldValues);
      }
      plot1.translate(x1, x2, y1, y2);
      plot1.repaintDiagram(plot1.getBounds());
     

    }
    else{
      // collective translation
      ce = new CompoundEdit();
     
      if (firstTranslation){
        HashMap plot1OldValues=plot1.getAxesProperties(null, -1);
        PlotCompoundEdit ce1=plot1.new PlotCompoundEdit(plot1OldValues);
        ce.addEdit(ce1);
      }
      plot1.translate(x1, x2, y1, y2);
      plot1.repaintDiagram(plot1.getBounds());
     
      // apply plot1 X axes properties to the other compliants plots
      Iterator it=collectivePlots.iterator();
      while(it.hasNext()){
        Plot plot=(Plot)it.next();

        if (firstTranslation){
          HashMap oldValues=plot.getAxesProperties(null,-1);
          PlotCompoundEdit ce2=plot.new PlotCompoundEdit(oldValues);
          ce.addEdit(ce2);
        }
        plot.translate(x1, x2, y1, y2);
            plot.repaintDiagram(plot.getBounds());
      }
      ce.end();
    }
   
    // store undoable event
    if (firstTranslation){
      selection.getElementContainer().getComponent().fireUndoableEditUpdate(new UndoableEditEvent(selection.getElementContainer().getComponent(), ce));
      firstTranslation = false;
    }
    selection.getElementContainer().getComponent().repaint();
     
    // end of drawing
    plot1=null;
   
    // For next translation
    x1=x2;
    y1=y2;
  }

 
 
  /**
   * Get the first plot part of selection which contains this point
   * @param x X coordinate location wrt diagram frame
   * @param y Y coordinate location wrt diagram frame
   * @return a plot
   */
  protected Plot getSelectedPlot(double x, double y){
    for (int i = 0; i < selection.getShapeCount(); i++) {
      Shape s = selection.getShape(i);
      if (s instanceof Plot
          && s.contains(x,y)) {
        return (Plot)s;
      }
    }
    return null;
  }
 
  /**
   * Display the plot coordinates for this point
   * @param x X coordinate location wrt diagram frame
   * @param y Y coordinate location wrt diagram frame
   */
  protected void displayCrossLocation(int x, int y){
    DiagramParameters param = selection.getElementContainer().getComponent().getParameters();
    double selX=(x/param.scale)-param.xmargin;
    double selY=(y/param.scale)-param.ymargin;
    Plot p=plot1;
    if(p==null){
      p=getSelectedPlot(selX,selY);
    }
    if(p!=null){
      p.displayCursorLocation(selX,selY);
    }
    selection.getElementContainer().getComponent().setCursor(
        Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
  }
 
  /* (non-Javadoc)
   * @see simtools.diagram.DiagramSelection.ContextualDrawing#draw(java.awt.Graphics2D, java.awt.Point)
   */
  public void draw(Graphics2D g2, Point pMax) {
    if (twoPoints && (kindOfZoom==PlotZoom.ZOOM_BOX)) {
        Color oldColor = g2.getColor();
        Stroke oldStroke = g2.getStroke();
       
      g2.setColor(zoomColor);
      g2.setStroke(dashStroke);
      zoomArea.x = Math.min(x1, x2);
      zoomArea.y = Math.min(y1, y2);
      zoomArea.width = Math.abs(x2 - x1);
      zoomArea.height = Math.abs(y2 - y1);
      g2.draw(zoomArea);
   
      // update drawing size
      if (Math.max(x1, x2) > pMax.x) {
        pMax.x = Math.max(x1, x2);
      }
      if (Math.max(y1, y2) > pMax.y) {
        pMax.y = Math.max(y1, y2);
      }
     
      g2.setColor(oldColor);
      g2.setStroke(oldStroke);
     
    }
  }

  /* (non-Javadoc)
   * @see simtools.diagram.DiagramSelectionListener#selectionChanged(simtools.diagram.DiagramSelection)
   */
  public void selectionChanged(DiagramSelection sel) {
    for (int i = 0; i < selection.getShapeCount(); i++) {
      Shape s = selection.getShape(i);
      if (s instanceof Plot){
        return; // there is at least on plot selected
      }
    }
    // no more plot in the selection => end of mode
    selection.getElementContainer().getComponent().setContextualDrawing(null); // end
  }
}
TOP

Related Classes of jsynoptic.builtin.PlotZoom

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.