Package simtools.shapes

Source Code of simtools.shapes.ShapesContainer

/* ==============================================
* Simtools : The tools library used in JSynoptic
* ==============================================
*
* Project Info:  http://jsynoptic.sourceforge.net/index.html
*
* This library 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 library 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
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 1999-2003, by :
*     Corporate:
*         Astrium SAS
*         EADS CRC
*     Individual:
*         Claude Cazenave
*     Nicolas Brodu
*
*
* $Id: ShapesContainer.java,v 1.34 2009/01/09 09:56:56 ogor Exp $
*
* Changes
* -------
* 25-Sep-2003 : Initial public release (NB);
*
*/

package simtools.shapes;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.print.PageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import javax.swing.event.UndoableEditEvent;
import javax.swing.undo.CompoundEdit;

import simtools.diagram.DiagramClipboard;
import simtools.diagram.DiagramComponent;
import simtools.diagram.Element;
import simtools.diagram.ElementsContainer;
import simtools.diagram.DiagramParameters;
import simtools.diagram.ElementSelection;
import simtools.diagram.DiagramSelection;
import simtools.diagram.gate.Connection;
import simtools.diagram.gate.Gate;
import simtools.diagram.gate.GatedComponent;
import simtools.diagram.undo.CreateEdit;
import simtools.diagram.undo.DepthChangedEdit;
import simtools.diagram.undo.GateConnectEdit;
import simtools.diagram.undo.TranslateEdit;
import simtools.shapes.undo.GroupEdit;
import simtools.shapes.undo.ReGroupEdit;
import simtools.shapes.undo.UnGroupEdit;

/**
* This class is a container to display shapes. It contains a DiagramComponent to
* be layout in other swing containers and with edition functionalities. Internalization
* is used to save and restore this container into/from a file
*
* @author Claude Cazenave
*
* @version 1.0 2001
*/
public class ShapesContainer extends Vector implements java.io.Serializable, ElementsContainer {

  static final long serialVersionUID = 4552602745191436089L;

  protected DiagramParameters _diagParam;

  protected static Font _sFont=new Font("TimesRoman",Font.PLAIN,10);

  /**
   * The transient shape diagram component
   */
  protected transient ShapesDiagramComponent _comp;


  /**
   * The transient shape diagram selection
   */
  protected transient ShapeDiagramSelection _selection;
 
 

  protected Vector _oldCompounds;


  public ShapesContainer(String name) {
      super();
     
      _diagParam=new DiagramParameters();
      _diagParam.name=name;
      _oldCompounds=new Vector();
     
      createSelectionAndComponent();
  }

 
    /**
     * Create the diagram selection and the JComponent related to this shape container
     */
    private void createSelectionAndComponent() {
        // 1- Create the shape diagram c selection
        _selection = createShapeSelection();
       
        // 2- Create the shape diagram component
        _comp = createShapesComponent();
    }
 
    /* (non-Javadoc)
     * @see simtools.diagram.ElementsContainer#setComponent(simtools.diagram.DiagramComponent)
     */
    public void setComponent(DiagramComponent dc) {
        _comp = (ShapesDiagramComponent)dc;
    }
   
    /* (non-Javadoc)
     * @see simtools.diagram.ElementsContainer#getComponent()
     */
    public DiagramComponent getComponent() {
        return _comp;
    }


    /* (non-Javadoc)
     * @see simtools.diagram.ElementsContainer#getSelection()
     */
    public DiagramSelection getSelection() {
        return _selection;
    }

    /* (non-Javadoc)
     * @see simtools.diagram.ElementsContainer#setSelection(simtools.diagram.DiagramSelection)
     */
    public void setSelection(DiagramSelection ds) {
        _selection = (ShapeDiagramSelection)ds;
    }


    public DiagramParameters getDiagramParameters(){
        return _diagParam;
    }
   
   
  public class ShapesDiagramComponent extends DiagramComponent implements ShapeListener {
   
    /**
     * This timer is used to gather shape changed events
     * and send them at a reasonable rate to Swing.
     */
    protected Timer timer=null;
    protected final Object timerLock=new Object();

    /**
     * An hash table to gather the shape changed events
     */
    protected HashMap paintedAreas=new HashMap();
   
    public ShapesDiagramComponent(DiagramParameters param, ShapesContainer sc){
      super(param, sc);
    }

    /**
     * Override finalize to make sure we stop thread and remove all listeners
     */
    protected void finalize() throws Throwable {
      synchronized(timerLock){
        if (timer!=null) {
          timer.cancel();
          timer = null;
        }
      }
      super.finalize();
    }
   
    public ShapesContainer getContainer() {
      return ShapesContainer.this;
    }


    // methods to deal with group,ungroup,regroup operations
    public boolean canGroup(){
      return getElementContainer().getSelection().getShapeCount() > 1;
    }

    public boolean canUnGroup(){
      for(int i=0;i<getElementContainer().getSelection().getShapeCount();i++){
        AbstractShape as=(AbstractShape)getElementContainer().getSelection().getShape(i);
        if(as instanceof CompoundShape){
          return true;
        }
      }
      return false;
    }

    /**
     * Regroup action is possible when one of the selected shapes is contained into
     * one of the recorded compound shapes
     * @return
     */
    public boolean canReGroup(){
   
      // Check if it is possible to regroup some shapes
      for(int i=0;i<_oldCompounds.size();i++){
        CompoundShape cs=(CompoundShape)_oldCompounds.elementAt(i);
        for(int j=0;j<getElementContainer().getSelection().getShapeCount();j++){
          if((cs.contains((AbstractShape)getElementContainer().getSelection().getShape(j))) && (cs.size()>1)){
            return true;
          }
        }
      }
      return false;
    }

    public void group(){
      if(getElementContainer().getSelection().getShapeCount()<2){
        return;
      }
      Vector shapesDeletedInCompoundShapes = new Vector();
      Vector deletedFromOldCompounds = new Vector();

      // update the old compound shapes
      for(int j=0;j<_oldCompounds.size();j++){
        CompoundShape cs=(CompoundShape)_oldCompounds.get(j);
        // Reminds that some shapes have been deleted for undo group operation
        Vector shapesRetained = cs.retainShapes(ShapesContainer.this);
        if (shapesRetained.size()!=0){
          Object[] shapesDeletedInCompoundShape = new Object[2];
          shapesDeletedInCompoundShape[0] = cs;
          shapesDeletedInCompoundShape[1] = shapesRetained;
          shapesDeletedInCompoundShapes.add(shapesDeletedInCompoundShape);
        }
        if ((cs.size()==0) && !deletedFromOldCompounds.contains(cs)){
          deletedFromOldCompounds.add(cs);
        }
       
      }
      // create a new CompoundShape
      int maxShapeDephtPosition=0;
      CompoundShape cs=new CompoundShape();
      for(int k=0;k<getElementContainer().getSelection().getShapeCount();k++){
        AbstractShape as=(AbstractShape)getElementContainer().getSelection().getShape(k);
       
        // check if it was in a old compound shape and mark it
        for(int j=0;j<_oldCompounds.size();j++){
          CompoundShape oc=(CompoundShape)_oldCompounds.get(j);
          if(oc.contains(as)){
            oc.removeShape(as);

            // Reminds that this shape has been deleted for undo group operation
            Object[] shapesDeletedInCompoundShape = new Object[2];
            Vector shapesRemoved = new Vector();
            shapesRemoved.add(as);
            shapesDeletedInCompoundShape[0] = oc;
            shapesDeletedInCompoundShape[1] = shapesRemoved;
            shapesDeletedInCompoundShapes.add(shapesDeletedInCompoundShape);

            if ( (oc.size()==0) && !deletedFromOldCompounds.contains(oc)){
              deletedFromOldCompounds.add(oc);
            }
          }
        }
        // add it
        cs.addShape(as);

        int shapeDephtPosition = ShapesContainer.this.indexOf(as);
        if (shapeDephtPosition>maxShapeDephtPosition)
          maxShapeDephtPosition = shapeDephtPosition;
       
      }
     
      for(int j=0;j<deletedFromOldCompounds.size();j++){
        _oldCompounds.remove((CompoundShape)deletedFromOldCompounds.get(j));
      }
     
      // add the compoundshape to the container
      Vector res  = new Vector();
      res.add(cs);
      ShapesContainer.this.addAll(maxShapeDephtPosition, res);
 
      // Then   remove selection from the container
      for(int k=0;k<getElementContainer().getSelection().getShapeCount();k++){
        ShapesContainer.this.removeElement((AbstractShape)getElementContainer().getSelection().getShape(k));
      }
     
      // update the selection
      ((ShapeDiagramSelection)getElementContainer().getSelection()).setToShape(cs);

      // Update undoable operations
      fireUndoableEditUpdate(new UndoableEditEvent(this, new GroupEdit(this, cs, shapesDeletedInCompoundShapes, deletedFromOldCompounds)));
     
      // repaint
      repaint();
    }
   
    /**
     * undo group operation
     * @param shapes
     */
    public void undoGroup(CompoundShape cs, Vector shapesDeletedInCompoundShapes, Vector deletedFromOldCompounds){
      // First undo group operation
     
      // remove it from the container
      ShapesContainer.this.removeElement(cs);

      // restore the shapes
      Vector selection = new Vector();
      for(int i=0;i<cs.size();i++){
        AbstractShape as = cs.getShape(i);
        ShapesContainer.this.add(as);
        selection.add(as);
      }
     
      // update the selection
      ((ShapeDiagramSelection)getElementContainer().getSelection()).setToShapes(selection)
      repaint();
     
      // Finally, undo modifications on other compoundShapes and on oldShapes
      for(int i=0;i<deletedFromOldCompounds.size();i++){
        _oldCompounds.add(deletedFromOldCompounds.get(i));
      }
      for(int i=0;i<shapesDeletedInCompoundShapes.size();i++){
        CompoundShape co = (CompoundShape)(((Object[])shapesDeletedInCompoundShapes.get(i))[0]);
        Vector v = (Vector)(((Object[])shapesDeletedInCompoundShapes.get(i))[1]);
        for(int j=0;j<v.size();j++){
          co.addShape( (AbstractShape)v.get(j));
        }
      }
    }
   
   
    /**
     * redo group operation
     * @param shapes
     */
    public void redoGroup(CompoundShape cs, Vector shapesDeletedInCompoundShapes, Vector deletedFromOldCompounds){
      //  First, redo modification on other compoundShapes and on oldShapes
      for(int i=0;i<deletedFromOldCompounds.size();i++){
        _oldCompounds.remove(deletedFromOldCompounds.get(i));
      }
      for(int i=0;i<shapesDeletedInCompoundShapes.size();i++){
        CompoundShape co = (CompoundShape)(((Object[])shapesDeletedInCompoundShapes.get(i))[0]);
        Vector v = (Vector)(((Object[])shapesDeletedInCompoundShapes.get(i))[1]);
        for(int j=0;j<v.size();j++){
          co.removeShape( (AbstractShape)v.get(j));
        }
      }
      // Then redo group operation
      for(int i=0;i<cs.size();i++){
        // remove it from the container
        ShapesContainer.this.removeElement(cs.getShape(i));
      }
      // add the compoundshape to the container
      Vector res  = new Vector();
      res.add(cs);
      ShapesContainer.this.addAll(res);

      // update the selection
      ((ShapeDiagramSelection)getElementContainer().getSelection()).setToShape(cs);

      repaint();
    }
   
    /**
     * unGroup operation
     */
    public void unGroup(){
      Vector undoUngroup =new Vector();
      Vector selection = new Vector();
      for(int i=0;i<getElementContainer().getSelection().getShapeCount();i++){
        AbstractShape as=(AbstractShape)getElementContainer().getSelection().getShape(i);
        if(as instanceof CompoundShape){
          CompoundShape cs=(CompoundShape)as;
          undoUngroup.add(cs);
         
          Vector res = new Vector();
          for(int j=0;j<cs.size();j++){
            res.add(cs.getShape(j));
          }
          selection.addAll(res);
          // When ungrouping, add coumpoundShape into the list of old compounds, used for regroup action
          _oldCompounds.add(cs);
         
          ShapesContainer.this.addAll( ShapesContainer.this.indexOf(as), res);
         
          // remove it from the container
          ShapesContainer.this.removeElement(as);
        }
      }
      // update the selection
      ((ShapeDiagramSelection)getElementContainer().getSelection()).setToShapes(selection);

      // Update undoable operations
      fireUndoableEditUpdate(new UndoableEditEvent(this, new UnGroupEdit(this, undoUngroup)));
     
      repaint();
    }

   
    /**
     * Undo ungroup operation
     * @param old compound shape to restore
     */
    public void undoUngroup(CompoundShape compoundShape){ 
      // First undo ungroup operation
      for(int k=0;k<compoundShape.size();k++){
        AbstractShape as= compoundShape.getShape(k);
        ShapesContainer.this.removeElement(as);
      }

      // add the compoundshape to the container
      Vector res  = new Vector();
      res.add(compoundShape);
      ShapesContainer.this.addAll(res);

      // update the selection
      ((ShapeDiagramSelection)getElementContainer().getSelection()).setToShape(compoundShape);
     
      // repaint
      repaint();
     
      // Finally, restore oldCompounds
      _oldCompounds.remove(compoundShape);   
    }

    /**
     * redo ungroup operation
     * @param old compound shape to restore
     */
    public void redoUngroup(CompoundShape compoundShape){
      // Fisrt update oldCompounds
      _oldCompounds.add(compoundShape);
     
      // Then redo ungroup operation
      Vector res=new Vector();
      for(int i=0;i<compoundShape.size();i++){
        AbstractShape as= compoundShape.getShape(i);
        res.add(as);
      }
     
      // remove it from the container
      ShapesContainer.this.removeElement(compoundShape);

      // restore the shapes
      ShapesContainer.this.addAll(res);

      // update the selection
      ((ShapeDiagramSelection)getElementContainer().getSelection()).setToShapes(res);
 
      repaint();
    }

   
    public void reGroup(){
      // loop on the old compound shapes
      Vector deletedFromOldCompounds = new Vector();
      Vector shapesDeletedInCompoundShapes = new Vector();
     
      for(int i=0;i<_oldCompounds.size();i++){
        CompoundShape cs=(CompoundShape)_oldCompounds.get(i);
        // update it
        // Reminds that some shapes have been deleted for undo group operation
        Vector shapesRetained = cs.retainShapes(ShapesContainer.this);
        if (shapesRetained.size()!=0){
          Object[] shapesDeletedInCompoundShape = new Object[2];
          shapesDeletedInCompoundShape[0] = cs;
          shapesDeletedInCompoundShape[1] = shapesRetained;
          shapesDeletedInCompoundShapes.add(shapesDeletedInCompoundShape);
        }
        if ( (cs.size()==0) && !deletedFromOldCompounds.contains(cs)) {
          deletedFromOldCompounds.add(cs);
        }
        // look for selelected elements member of the
        // current old compound shape
        for(int k=0;k<getElementContainer().getSelection().getShapeCount();k++){
          AbstractShape as=(AbstractShape)getElementContainer().getSelection().getShape(k);
          if(cs.contains(as)){
            // remove form the selection and from the
            // container all the shapes that belong
            // to this compound shape
            Vector v=new Vector();
           
            int maxShapeDepthPosition=0;
            for(int j=0;j<cs.size();j++){
              v.add(cs.getShape(j));
              int shapeDepthPosition =  ShapesContainer.this.indexOf(cs.getShape(j));
              if (shapeDepthPosition>maxShapeDepthPosition)
                maxShapeDepthPosition = shapeDepthPosition;
            }
            ((ShapeDiagramSelection)getElementContainer().getSelection()).replaceShapes(v,cs);
           
            cs.computeBounds();
            cs.synchroSizes();
            ShapesContainer.this.add(maxShapeDepthPosition, cs);
           
            ShapesContainer.this.removeAll(v);

            // This is no more an old one
            deletedFromOldCompounds.add(cs);
         
            // go to next compound shape
            break;
          }
        }
      }
      for(int i=0;i<deletedFromOldCompounds.size();i++)
        _oldCompounds.remove(deletedFromOldCompounds.get(i));
     
//      Update undoable operations
      fireUndoableEditUpdate(new UndoableEditEvent(this, new ReGroupEdit(this,shapesDeletedInCompoundShapes, deletedFromOldCompounds)));
      repaint();
    }

   
    /**
     * undo regroup operation
     * @param shapes
     */
    public void undoReGroup(Vector compoundShapes, Vector shapesDeletedInCompoundShapes){
      // First, undo regroup operation for all compound shapes
      for(int i=0;i<compoundShapes.size();i++){
        CompoundShape cs = (CompoundShape)compoundShapes.get(i);
        _oldCompounds.add(cs);

        // remove it from the container
        ShapesContainer.this.removeElement(cs);

        Vector res=new Vector();
        for(int j=0;j<cs.size();j++){
          res.add(cs.getShape(j));
        }
        // restore the shapes
        ShapesContainer.this.addAll(res);

        // update the selection
        ((ShapeDiagramSelection)getElementContainer().getSelection()).setToShapes(res);
      }
      repaint();
     
      // Finally, undo modification on other compoundShapes and on oldShapes
      for(int i=0;i<shapesDeletedInCompoundShapes.size();i++){
        CompoundShape co = (CompoundShape)(((Object[])shapesDeletedInCompoundShapes.get(i))[0]);
        Vector v = (Vector)(((Object[])shapesDeletedInCompoundShapes.get(i))[1]);
        for(int j=0;j<v.size();j++){
          co.addShape( (AbstractShape)v.get(j));
        }
      }
    }

    /**
     * redo  regroup operation
     * @param shapes
     */
    public void redoReGroup(Vector compoundShapes, Vector shapesDeletedInCompoundShapes){
      //  First, redo modification on other compoundShapes and on oldShapes
      for(int i=0;i<shapesDeletedInCompoundShapes.size();i++){
        CompoundShape co = (CompoundShape)(((Object[])shapesDeletedInCompoundShapes.get(i))[0]);
        Vector v = (Vector)(((Object[])shapesDeletedInCompoundShapes.get(i))[1]);
        for(int j=0;j<v.size();j++){
          co.removeShape( (AbstractShape)v.get(j));
        }
      }
      // Then, redo regroup operation for all compound shapes
      for(int i=0;i<compoundShapes.size();i++){
        CompoundShape cs = (CompoundShape)compoundShapes.get(i);
        _oldCompounds.remove(cs);
        // remove form the selection and from the
        // container all the shapes that belong
        // to this compound shape
        Vector v=new Vector();
        for(int j=0;j<cs.size();j++){
          v.add(cs.getShape(j));
        }
        ((ShapeDiagramSelection)getElementContainer().getSelection()).replaceShapes(v,cs);
        ShapesContainer.this.removeAll(v);
        cs.computeBounds();
        cs.synchroSizes();
        ShapesContainer.this.add(cs);
      }
      repaint();
    }

   
    // Implementation of the abstract methods
    protected void translate(int x, int y){
      CompoundEdit ce = new CompoundEdit();
      for(int i=0;i<ShapesContainer.this.size();i++){
        AbstractShape s=(AbstractShape)elementAt(i);
        s.translate(x,y);
        ce.addEdit(new TranslateEdit(x, y, s));
      }
      ce.end();
      fireUndoableEditUpdate(new UndoableEditEvent(this, ce));
    }

    protected void getMin(Point p){
      for(int i=0;i<ShapesContainer.this.size();i++){
        AbstractShape s=(AbstractShape)elementAt(i);
        s.getMin(p);
      }
    }

    /* (non-Javadoc)
     * @see simtools.diagram.DiagramComponent#copyAt(java.util.Vector, int, int)
     */
    protected void copyAt(Vector v, int x, int y){
        CompoundEdit compoundEdit = new CompoundEdit();

        List selectedConnectors = new ArrayList();
        List selectedGatedComponent = new ArrayList();
       
        Hashtable clonedGates = new Hashtable();

        for(int i=0;i<v.size();i++){
            Object o=v.elementAt(i);

        if (o instanceof Connection){
            selectedConnectors.add(o);
           
        } else if (o instanceof AbstractShape){
            AbstractShape as=((AbstractShape)o).cloneShape();

            if (o instanceof GatedComponent){
                selectedGatedComponent.add(o);
               
             // Kept the relation between the existing and the new gate
                List oldGates = new ArrayList(((GatedComponent)o).getGates());
                    List newGates = new ArrayList(((GatedComponent)as).getGates());
                   
                    for(int j=0;j<oldGates.size(); j++){
                        clonedGates.put(oldGates.get(j), newGates.get(j));
                    }
                  }
           
          as.translate(x,y);
          ShapesContainer.this.add(as);
          compoundEdit.addEdit(new CreateEdit(ShapesContainer.this,as));
        }
        }

        // Now Copy the connectors
        for (int i = 0; i < selectedConnectors.size(); i++) {
            Connection connection = (Connection) selectedConnectors.get(i);

            if (connection instanceof AbstractShape){
                Gate fisrtGate = (Gate) connection.getFirstEndGate();
                Gate lastGate = (Gate) connection.getLastEndGate();
               
                Gate newFg = null;
                Gate newLg = null;

                if ((fisrtGate!=null) && selectedGatedComponent.contains(fisrtGate.getOwner())){
                    newFg = (Gate) clonedGates.get(fisrtGate);
                }
                if ((lastGate!=null) && selectedGatedComponent.contains(lastGate.getOwner())){
                    newLg = (Gate) clonedGates.get(lastGate);
                }

                AbstractShape newConnector = ((AbstractShape)connection).cloneShape();
                newConnector.translate(x,y);
               
                if (newFg != null){
                    ((Connection)newConnector).connect(newFg, true);
                    compoundEdit.addEdit(new GateConnectEdit( (Connection)newConnector, newFg, true));
                }

                if (newLg != null){
                    ((Connection)newConnector).connect(newLg, false);
                    compoundEdit.addEdit(new GateConnectEdit( (Connection)newConnector, newLg, false));
                }

                // Add it ton container
                ShapesContainer.this.add(newConnector);
               
                compoundEdit.addEdit(new CreateEdit(ShapesContainer.this,newConnector));
            }
        }

        compoundEdit.end();
        fireUndoableEditUpdate(new UndoableEditEvent(this, compoundEdit));
    }
   
    public Shape getShapeAt(int ox, int oy){
      for(int i=(ShapesContainer.this.size()-1); i>=0; i--){
        Shape s=(Shape)elementAt(i);
        if(s.contains(ox,oy)){
          return s;
        }
      }
      return null;
    }

    protected void drawDiagramElements(Graphics2D g2, Point pMax){
        Stroke oldStrocke = g2.getStroke();
        Color oldColor = g2.getColor();
        Font olfFont = g2.getFont();

        g2.setFont(_sFont);
        if(_diagParam.backgr!=null){
            g2.setColor(_diagParam.forgr);
            g2.setBackground(_diagParam.backgr);
        }
        else{
            g2.setColor(Color.black);
            g2.setBackground(DiagramParameters.DEFAULT_COLOR);
        }
        g2.setStroke(new BasicStroke(0));

        // loop on objects to be displayed
        //--------------------------------
        for(int i=0;i<ShapesContainer.this.size();i++){
            AbstractShape r=(AbstractShape)elementAt(i);
            r.draw(g2);

            ElementSelection dss=getElementContainer().getSelection().getSelectedShape(r);
            if(dss!=null){
                drawBounds(g2,dss);
            }

            // update drawing size
            r.getMax(pMax);
        }

        g2.setFont(olfFont);
        g2.setColor(oldColor);
        g2.setStroke(oldStrocke);
    }

     
    protected void drawBounds(Graphics2D g2, ElementSelection dss){
        dss.drawBounds(g2);
    }


    protected void drawClipboardElements(Graphics2D g2, Point pMax){
      int dx=_dragPoint.x;
      int dy=_dragPoint.y;

      g2.translate(dx,dy);
     
      DiagramClipboard dc=DiagramClipboard.get();

      // loop on objects to be displayed
      //--------------------------------
      g2.setColor(Color.green);
      for(int i=0;i<dc.size();i++){
        // connectors are not connected to connections
        // can't call getConnections() on
        // connections are connected to connectors
        // and have been copied to clipboard
        Object o=dc.elementAt(i);
        if(o instanceof AbstractShape){
          AbstractShape r=(AbstractShape)o;
          r.draw(g2);
          // update drawing size
          r.getMax(pMax);
        }
      }
      g2.translate(-dx,-dy);
         }

    protected void printDiagramElements(Graphics2D g2, Point pMax) {
      g2.setFont(_sFont);
      g2.setColor(Color.black);

      // Loop on objects to be displayed
      // Print only the selection if requested, or all if there is no selection
      boolean hasSelection = false;
      if (_printSelectionOnly) for (int i=0; i<ShapesContainer.this.size(); i++) {
        AbstractShape as = (AbstractShape)elementAt(i);
        if (getElementContainer().getSelection().isSelected(as)) {
          as.draw(g2);
          // update drawing size
          as.getMax(pMax);
          hasSelection = true;
        }
      }

      // If there is no selection, then print everything
      if (!hasSelection) for (int i=0; i<ShapesContainer.this.size(); i++) {
        AbstractShape as = (AbstractShape)elementAt(i);
        as.draw(g2);
        as.getMax(pMax);
      }

    }

    protected double computePrintScaleFactor(PageFormat pf) {
      if (!_printSelectionOnly) return super.computePrintScaleFactor(pf);
      Point max = new Point();
      boolean hasSelection = false;
      for (int i=0; i<ShapesContainer.this.size(); i++) {
        AbstractShape as = (AbstractShape)elementAt(i);
        if (getElementContainer().getSelection().isSelected(as)) {
          as.getMax(max);
          hasSelection = true;
        }
      }
      if (!hasSelection) return super.computePrintScaleFactor(pf);
      double sx = pf.getImageableWidth()/(double)max.x;
      double totalHeight = (double)max.y;
      if (hasHeader()) totalHeight += (double)(_param.headerHeight + DiagramParameters.HEADER_MARGIN);
      double sy = pf.getImageableHeight() / totalHeight;
      double s = Math.min(sx,sy);
      return s;
    }

     /**
      * A cyclic task ensures that repainted requests are not performed
      * faster than an configurable parameter
      * In addition, if several updates on a given shapes are performed
      * during this configurable period then the painted area of that shape
      * is growing if different rectangles of painting are required
      * but the shape will be painted one time only
      *
     * @see simtools.shapes.ShapeListener#shapeChanged(simtools.shapes.AbstractShape, java.awt.Rectangle)
     */
    public void shapeChanged(AbstractShape shape, Rectangle changedArea) {
      Rectangle r=(Rectangle)paintedAreas.get(shape);
      if(r==null){
        synchronized(paintedAreas){
          paintedAreas.put(shape,changedArea);
        }
      }
      else{
        r.add(changedArea);
      }
      synchronized(timerLock){
        if(timer!=null){
          return; // there is a timer let it do its job
        }
        timer = new Timer(true); // do not block the application on exit 
        timer.schedule(new TimerTask() {
        public void run() {
          int n=0;
          synchronized(paintedAreas){
            Iterator it=paintedAreas.keySet().iterator();
            if(!it.hasNext()){
              synchronized(timerLock){
                timer.cancel();
                timer=null;
              }
              return;
            }
            while(it.hasNext()){
              AbstractShape as=(AbstractShape)it.next();
              Rectangle area=(Rectangle)paintedAreas.get(as);
              repaint(area);
              it.remove(); // this remove the shape from the hastable
              n++;
            }
          }
        }
      },0,AbstractShape.REFRESH_PERIOD);
      }
    }

    public void repaint(){
      // clear the hastable, everything is going to pe painted
      // also a lazy way to remove shapes that are no more used
      synchronized(paintedAreas){
        paintedAreas.clear();
      }
      super.repaint();
    }
   
   
    /**
         * Overridden in order to handle Undo/Redo on translation events.
         */
        public void pointTranslationEnd() {
            // _compoundEdit has been
            _compoundEdit.end();
            fireUndoableEditUpdate(
                    new UndoableEditEvent(
                            this, _compoundEdit
                    )
                );
            super.pointTranslationEnd();
        }

    /**
     * Overridden in order to handle Undo/Redo on translation events.
     */
    public void translationEnd() {
      // _compoundEdit has been
      _compoundEdit.end();
      fireUndoableEditUpdate(
          new UndoableEditEvent(
              this, _compoundEdit
          )
        );
      super.translationEnd();
    }

    /**
     * Overridden in order to handle Undo/Redo on resize events.
     */
    public void resizeEnd() {
      _compoundEdit.end();
      fireUndoableEditUpdate(
        new UndoableEditEvent(
            this, _compoundEdit
        )
      );
      super.resizeEnd();
    }
   
    public void performCreate(AbstractShape shape) {
      fireUndoableEditUpdate(
          new UndoableEditEvent(this, new CreateEdit(ShapesContainer.this, shape))
      );
    }
   
    public void fireUndoableEditUpdate(UndoableEditEvent _e) {
      super.fireUndoableEditUpdate(_e);
    }
  }

  /**
   *
   * A selection of shapes on a DiagramComponentElements
   * @author zxpletran007
   *
   */
  public class ShapeDiagramSelection extends DiagramSelection {

      ShapeDiagramSelection(ShapesContainer sc){
          super(sc);
      }

    public Point getShapeOrigin(Shape s, Point p){
      Point res= ((p==null) ? (new Point()) : p );
      if(s instanceof AbstractShape){
        AbstractShape r=(AbstractShape)s;
        res.x=r._ox;
        res.y=r._oy;
        return res;
      }
      return super.getShapeOrigin(s,res);
    }


    /* (non-Javadoc)
     * @see simtools.diagram.DiagramSelection#addAllShapes()
     */
    protected boolean addAllShapes(){ 
        int selectionOldCount = getShapeCount();

        for(int i = size()-1; i>=0; i--){
            Element s = (Element)elementAt(i);
            add(createShapeSelection(s));
        }
        return selectionOldCount != getShapeCount();
    }
   
    /* (non-Javadoc)
     * @see simtools.diagram.DiagramSelection#addShapeAt(int, int)
     */
    protected boolean addShapeAt(int ox, int oy){
        int selectionOldCount = getShapeCount();

        boolean hasBeenAdd = false;
        for(int i=size()-1; i>=0 && !hasBeenAdd; i--){
            Element s=(Element)elementAt(i);

            if(s.contains(ox,oy)){
                add(createShapeSelection(s));
                hasBeenAdd = true;
            }
        }
        return selectionOldCount != getShapeCount();
    }

    protected void setToShape(AbstractShape as){
        super.clear();
        selectAreaEnd();
        width=-1;
        add(createShapeSelection(as));

        propagate();
    }

    protected void setToShapes(Vector v){
        super.clear();
        for(int i=0;i<v.size();i++){
            AbstractShape as=(AbstractShape)v.elementAt(i);
            add(createShapeSelection(as));
        }
        propagate();
    }

    protected void addShapes(Vector v){
        for(int i=0;i<v.size();i++){
            AbstractShape as=(AbstractShape)v.elementAt(i);
            add(createShapeSelection(as));

        }
        propagate();
      }

    /**
     * Replace a list of shapes by a new one
     * @param v the shapes to delete
     * @param as the shape to add
     */
    protected void replaceShapes(Vector v, AbstractShape as){
        int k=getShapeCount()-1;
        for(int i=k;i>=0;i--){
            Shape s=getShape(i);
            if(v.contains(s)){
                removeShapeAt(i);
            }
        }
        add(createShapeSelection(as));

        propagate();
    }
   
   
    /* (non-Javadoc)
     * @see simtools.diagram.DiagramSelection#cloneElement(simtools.diagram.Element)
     */
    public Element cloneElement(Element e){
        Element res;
        if (e instanceof AbstractShape){
            res = ((AbstractShape)e).cloneShape();
        } else {
            res = super.cloneElement(e);
        }
        return res;
    }
    }

// Take care of serialisation. Diagram is transient

  private void readObject(java.io.ObjectInputStream in) throws java.lang.ClassNotFoundException, java.io.IOException {
    in.defaultReadObject();

    createSelectionAndComponent();
  }
 
  /**
     * @param param
     * @return
     */
    protected ShapeDiagramSelection createShapeSelection() {
        return new ShapeDiagramSelection(this);
    }
   
  /**
   * @param param
   * @return
   */
  protected ShapesDiagramComponent createShapesComponent() {
      return  new ShapesDiagramComponent(_diagParam, this);
  }
   /* (non-Javadoc)
   * @see java.util.Collection#add(java.lang.Object)
   */
  public synchronized boolean add(Object o) {
    if (o instanceof AbstractShape) ((AbstractShape)o).addListener(_comp);
    return super.add(o);
  }

  /* (non-Javadoc)
   * @see java.util.List#add(int, java.lang.Object)
   */
  public void add(int index, Object element) {
    if (element instanceof AbstractShape) ((AbstractShape)element).addListener(_comp);
    super.add(index, element);
  }

  /* (non-Javadoc)
   * @see java.util.Collection#addAll(java.util.Collection)
   */
  public synchronized boolean addAll(Collection c) {
    for (Iterator it = c.iterator(); it.hasNext(); ) {
      Object o = it.next();
      if (o instanceof AbstractShape) ((AbstractShape)o).addListener(_comp);
    }
    return super.addAll(c);
  }

  /* (non-Javadoc)
   * @see java.util.List#addAll(int, java.util.Collection)
   */
  public synchronized boolean addAll(int index, Collection c) {
    for (Iterator it = c.iterator(); it.hasNext(); ) {
      Object o = it.next();
      if (o instanceof AbstractShape) ((AbstractShape)o).addListener(_comp);
    }
    return super.addAll(index, c);
  }

  /* (non-Javadoc)
   * @see java.util.Vector#addElement(java.lang.Object)
   */
  public synchronized void addElement(Object obj) {
    if (obj instanceof AbstractShape) {
      ((AbstractShape)obj).addListener(_comp);
      _comp.performCreate((AbstractShape)obj);
    }
    super.addElement(obj);
  }

  /* (non-Javadoc)
   * @see java.util.Collection#clear()
   */
  public void clear() {
    for (Iterator it = iterator(); it.hasNext(); ) {
      Object o = it.next();
      if (o instanceof AbstractShape) ((AbstractShape)o).removeListener(_comp);
    }
    super.clear();
  }

  /* (non-Javadoc)
   * @see java.util.Vector#insertElementAt(java.lang.Object, int)
   */
  public synchronized void insertElementAt(Object obj, int index) {
    if (obj instanceof AbstractShape) ((AbstractShape)obj).addListener(_comp);
    super.insertElementAt(obj, index);
  }

  /* (non-Javadoc)
   * @see java.util.List#remove(int)
   */
  public synchronized Object remove(int index) {
    Object o = get(index);
    if (o instanceof AbstractShape) {
      ((AbstractShape)o).removeListener(_comp);
    }
    return super.remove(index);
  }

  /* (non-Javadoc)
   * @see java.util.Collection#remove(java.lang.Object)
   */
  public boolean remove(Object o) {
    if (o instanceof AbstractShape) {
      ((AbstractShape)o).removeListener(_comp);
    }
    return super.remove(o);
  }

  /* (non-Javadoc)
   * @see java.util.Collection#removeAll(java.util.Collection)
   */
  public synchronized boolean removeAll(Collection c) {
    for (Iterator it = c.iterator(); it.hasNext(); ) {
      Object o = it.next();
      if (o instanceof AbstractShape) {
        ((AbstractShape)o).removeListener(_comp);
      }
    }
    return super.removeAll(c);
  }

  /* (non-Javadoc)
   * @see java.util.Vector#removeAllElements()
   */
  public synchronized void removeAllElements() {
    for (Iterator it = iterator(); it.hasNext(); ) {
      Object o = it.next();
      if (o instanceof AbstractShape) {
          AbstractShape as = (AbstractShape)o;
        as.removeListener(_comp);
      }
    }
    super.removeAllElements();
  }

  /* (non-Javadoc)
   * @see java.util.Vector#removeElement(java.lang.Object)
   */
  public synchronized boolean removeElement(Object obj) {
      if (obj instanceof AbstractShape) {
          AbstractShape as = (AbstractShape)obj;
          as.removeListener(_comp);
      }
      return super.removeElement(obj);
  }

  /* (non-Javadoc)
   * @see java.util.Vector#removeElementAt(int)
   */
  public synchronized void removeElementAt(int index) {
    Object o = get(index);
    if (o instanceof AbstractShape) {
        AbstractShape as = (AbstractShape)o;
      as.removeListener(_comp);
    }
    super.removeElementAt(index);
  }

  /* (non-Javadoc)
   * @see java.util.AbstractList#removeRange(int, int)
   */
  protected void removeRange(int fromIndex, int toIndex) {
    for (int i=fromIndex; i<=toIndex; ++i) {
      Object o = get(i);
      if (o instanceof AbstractShape) {
          AbstractShape as = (AbstractShape)o;
        as.removeListener(_comp);
      }
    }
    super.removeRange(fromIndex, toIndex);
  }

  /* (non-Javadoc)
   * @see java.util.List#set(int, java.lang.Object)
   */
  public synchronized Object set(int index, Object element) {
    Object o = get(index);
    if (o instanceof AbstractShape) ((AbstractShape)o).removeListener(_comp);
    if (element instanceof AbstractShape) ((AbstractShape)element).addListener(_comp);
    return super.set(index, element);
  }

  /* (non-Javadoc)
   * @see java.util.Vector#setElementAt(java.lang.Object, int)
   */
  public synchronized void setElementAt(Object obj, int index) {
    Object o = get(index);
    if (o instanceof AbstractShape) ((AbstractShape)o).removeListener(_comp);
    if (obj instanceof AbstractShape) ((AbstractShape)obj).addListener(_comp);
    super.setElementAt(obj, index);
  }

  /**
   * Brings a set of selected shapes to the 'front' of the container, i.e at the
   * top in terms of depth
   * @param shapes The list of shapes to bring to front
   */
  public synchronized void bringToFront(Vector shapes) {

    int[] indices = new int[shapes.size()];
    int i;

    // Construct the list of indices
    for(i=0; i<indices.length; i++) {
      // The objects are necessarily shapes from this object
      indices[i]=this.indexOf(shapes.get(i));
    }
    // Sort the indices in order to preserve the depth inside of the selection
    Arrays.sort(indices);

    Object tmp;
    int indice;
    CompoundEdit ce = new CompoundEdit();
    for(i=0; i<indices.length; i++) {
      indice=indices[i]-i;
      tmp=this.elementAt(indice);
      this.removeElementAt(indice);
      this.add(tmp);
      ce.addEdit(new DepthChangedEdit(this, indice, size()-1));
    }
   
    ce.end();
    _comp.fireUndoableEditUpdate(new UndoableEditEvent(this, ce));
    _comp.repaint();
  }

  /**
   * Brings a set of shapes closer to the 'top' of the container
   * @param shape
   */
  public synchronized void bringForward(Vector shapes) {
    int[] indices = new int[shapes.size()];
    int i;

    // Construct the list of indices
    for(i=0; i<indices.length; i++) {
      // The objects are necessarily shapes from this object
      indices[i]=this.indexOf(shapes.get(i));
    }
    // Sort the indices in order to preserve the depth inside of the selection
    Arrays.sort(indices);
   
    Object tmp;
    int indice;
    CompoundEdit ce = new CompoundEdit();
    for(i=indices.length; i>0; i--) {
      indice=indices[i-1];
      if(indice < size()-1) {
        tmp=this.elementAt(indice);
        this.removeElementAt(indice);
        this.insertElementAt(tmp, indice+1);
        ce.addEdit(new DepthChangedEdit(this, indice, indice+1));
      }
    }
   
    ce.end();
    _comp.fireUndoableEditUpdate(new UndoableEditEvent(this, ce));
    _comp.repaint();
  }

  /**
   * Sends a set of selected shapes to the 'back' of the container, i.e at the
   * bottom in terms of depth
   * @param shapes The list of shapes to bring to front
   */
  public synchronized void sendToBack(Vector shapes) {

    int[] indices = new int[shapes.size()];
    int i;

    // Construct the list of indices
    for(i=0; i<indices.length; i++) {
      // The objects are necessarily shapes from this object
      indices[i]=this.indexOf(shapes.get(i));
    }
    // Sort the indices in order to preserve the depth inside of the selection
    Arrays.sort(indices);

    Object tmp;
    int indice;
    CompoundEdit ce = new CompoundEdit();
    for(i=0; i<indices.length; i++) {
      indice=indices[i];
      tmp=this.elementAt(indice);
      this.removeElementAt(indice);
      this.insertElementAt(tmp, i);
      ce.addEdit(new DepthChangedEdit(this, indice, i));
    }
   
    ce.end();
    _comp.fireUndoableEditUpdate(new UndoableEditEvent(this, ce));
    _comp.repaint();
  }

  /**
   * Brings a shape closer to the 'bottom' of the container
   * @param shape
   */
  public synchronized void sendBackward(Vector shapes) {
    int[] indices = new int[shapes.size()];
    int i;

    // Construct the list of indices
    for(i=0; i<indices.length; i++) {
      // The objects are necessarily shapes from this object
      indices[i]=this.indexOf(shapes.get(i));
    }
    // Sort the indices in order to preserve the depth inside of the selection
    Arrays.sort(indices);
   
    Object tmp;
    int indice;
    CompoundEdit ce = new CompoundEdit();
    for(i=0; i<indices.length; i++) {
      indice=indices[i];
      if(indice > 0) {
        tmp=this.elementAt(indice);
        this.removeElementAt(indice);
        this.insertElementAt(tmp, indice-1);
        ce.addEdit(new DepthChangedEdit(this, indice, indice-1));
      }
    }
   
    ce.end();
    _comp.fireUndoableEditUpdate(new UndoableEditEvent(this, ce));
    _comp.repaint();
  }
}

TOP

Related Classes of simtools.shapes.ShapesContainer

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.