Package jsynoptic.builtin

Source Code of jsynoptic.builtin.AutomatonShape$Cell

/* ========================
* 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-2003, by :
*     Corporate:
*         Astrium SAS
*         EADS CRC
*     Individual:
*         Nicolas Brodu
*
* $Id: AutomatonShape.java,v 1.21 2008/09/05 12:23:22 ogor Exp $
*
* Changes
* -------
* 26-Nov-2003 : Initial version (NB);
*
*/
package jsynoptic.builtin;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.geom.AffineTransform;
import java.io.Serializable;
import java.text.NumberFormat;
import java.util.Iterator;
import java.util.ResourceBundle;
import java.util.Vector;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.undo.CompoundEdit;

import jsynoptic.base.ContextualActionProvider;
import jsynoptic.base.Linkable;
import jsynoptic.ui.JSynoptic;
import jsynoptic.ui.LongAction;
import simtools.data.DataException;
import simtools.data.DataInfo;
import simtools.data.DataSource;
import simtools.data.DataSourceListener;
import simtools.data.DataSourcePool;
import simtools.data.EndNotificationListener;
import simtools.data.UnsupportedOperation;
import simtools.shapes.AbstractShape;
import simtools.ui.NumberField;
import simtools.ui.ResourceFinder;
import simtools.ui.SourceTree;

/**
* A 2D automaton, driven by a data source. It consists in a grid which cells have configurable
* background and label.
* Actions are associated to data source values or ranges. They are processed dynamically
* when data arrives.
*/
public class AutomatonShape extends AbstractShape implements simtools.diagram.Resizable, DataSourceListener, ContextualActionProvider, Linkable, EndNotificationListener {

  static final long serialVersionUID = -2166910190999229946L;

  // Reuse resources from Abstract 1D shape.
  // Even if this class does not extends it, it uses common text
  public static ResourceBundle resources = ResourceFinder.get(AutomatonShape.class, Abstract1DShape.resources);

  public static int MIN_CELL_WIDTH = 5;
  public static int MIN_CELL_HEIGHT = 5;

  protected AutomatonActionMapper mapper;
  protected transient DataSource source;
  protected transient long index;

  protected boolean allowResize;
  protected boolean fixedRatio;
  protected double ratio;

  protected int activeX, activeY;

  /** Reference font and dimensions used to compute sizes when resizing */
  protected static int referenceHeight = -1;
  protected static int referenceWidth = -1;
  protected static int referenceBaseline = -1;
  protected static Font referenceFont = null;

  static{
    // "Monospaced" is guaranteed to exist by the JVM, see javadoc
    referenceFont = Font.decode("Monospaced");
    // Use a big font to minimize rounding errors dramatic effect when scaling size > referenceFont.size
    referenceFont = referenceFont.deriveFont(100.0f);
    FontMetrics fm = TextShape.referenceGraphics.getFontMetrics(referenceFont);
    referenceBaseline = fm.getDescent();
    referenceHeight = fm.getAscent() + referenceBaseline;
    // As this is a monospaced font, all characters have same width => use one of them to compute width
    // As I'm paranoid, I use the largest one...
    referenceWidth = fm.stringWidth("W");
  }

  // Linkable shape
  protected String link;

  public String getLink() {
    return link;
  }

  public void setLink(String link) {
    this.link = link;
  }

  public static class Cell implements Serializable {

    public Color frameColor, backgroundColor, textColor;
    public String text;

    Cell() {
      frameColor = Color.black;
      textColor = Color.black;
    }
  }

  protected Cell[][] cells;

  protected transient boolean dirtyState = false;

  public AutomatonShape(int ox, int oy) {
    this(ox, oy, 5, 5);
  }

  public AutomatonShape(int ox, int oy, int nx, int ny) {
    this(ox, oy, nx, ny, nx * MIN_CELL_WIDTH, ny * MIN_CELL_HEIGHT);
  }

  public AutomatonShape(int ox, int oy, int nx, int ny, int width, int height) {
    super(ox, oy);
    _w = width;
    _h = height;
    cells = new Cell[ny][nx];
    for (int y=0; y<cells.length; ++y) for (int x=0; x<cells[y].length; ++x) {
      cells[y][x] = new Cell();
    }
    // Our own mapper
    mapper = new AutomatonActionMapper();
    allowResize = true;
  }


  /* (non-Javadoc)
   * @see simtools.shapes.AbstractShape#draw(java.awt.Graphics2D)
   */
  public void draw(Graphics2D g) {
    Color oldColor = g.getColor();
    Color oldBackground = g.getBackground();

    Object antialiasHint = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
        AbstractShape.ANTI_ALIASING
        ? RenderingHints.VALUE_ANTIALIAS_ON
            : RenderingHints.VALUE_ANTIALIAS_OFF);

    int lenx = _w / cells[0].length;
    int leny = _h / cells.length;

    // Prevent the text to get out of bounds
    Rectangle oldclip = g.getClipBounds();   
    Font saveFont = g.getFont();

    // Draw each cell
    for (int y=0; y<cells.length; ++y) for (int x=0; x<cells[y].length; ++x) {
      Cell cell = cells[y][x];
      if (cell==null) continue;

      // Compute coordinates
      int x0 =_ox + x * lenx;
      int y0 = _oy - _h + y * leny;

      // Fill background, if any
      if (cell.backgroundColor!=null) {
        g.setColor(cell.backgroundColor);
        g.fillRect(x0,y0,lenx, leny);
      }

      // Write text, if any
      if ((cell.textColor!=null) && (cell.text!=null) && (!cell.text.equals(""))) {
        g.setColor(cell.textColor);
        g.setClip(x0, y0, lenx, leny);
        Font f = getFontToFitText(cell.text, lenx, leny);
        if (f!=null) {
          g.setFont(f);
          g.drawString(cell.text, x0 + TextShape.MARGINX, y0 + leny - TextShape.MARGINY - g.getFontMetrics(f).getDescent());
        }
        g.setClip(oldclip);
      }

      // Draw frame, if any
      if (cell.frameColor!=null) {
        g.setColor(cell.frameColor);
        g.drawRect(x0,y0,lenx-1,leny-1);
      }

    }

    g.setFont(saveFont);
    g.setClip(oldclip);

    g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antialiasHint);
    g.setBackground(oldBackground);
    g.setColor(oldColor);
  }

  /** Utility method that returns a Font object, as would be used to draw the text
   * according to widht and height
   * May return null if the desired operation results in no visible text.
   */
  public static Font getFontToFitText(String text, int width, int height) {
    double innerw = width-2*TextShape.MARGINX;
    double innerh = height-2*TextShape.MARGINY;

    if ((innerw<=0) || (innerh<=0)) return null;

    double scaleX = innerw/(text.length() * referenceWidth);
    double scaleY = innerh/referenceHeight;
    return referenceFont.deriveFont(AffineTransform.getScaleInstance(scaleX, scaleY));
  }


  /* (non-Javadoc)
   * @see jsynoptic.base.ContextualActionProvider#getActions(double, double, java.lang.Object, int)
   */
  public String[] getActions(double x, double y, Object o, int context) {
    if (context==MOUSE_OVER_CONTEXT) {
      return null;
    }

    if (context==MOUSE_OUT_CONTEXT) {
      return null;
    }

    if (context==MOUSE_PRESSED_CONTEXT) {
      return null;
    }

    if (context==EDITOR_CONTEXT) {
    }

    Vector v = new Vector();
    v.add(resources.getString("properties"));

    return (String[])v.toArray(new String[v.size()]);
  }

  /* (non-Javadoc)
   * @see jsynoptic.base.ContextualActionProvider#doAction(double, double, java.lang.Object, java.lang.String)
   */
  public boolean doAction(double x, double y, Object o, String action, CompoundEdit undoableEdit) {
    if (action.equals(resources.getString("properties"))) {
      new LongAction(LongAction.LONG_ACTION_SHAPE, null, this) {
        protected void doAction() {
          PropertiesPanel panel = createPanel();
          int result = JOptionPane.showConfirmDialog(JSynoptic.gui.getOwner(), panel,
              panel.getShapeName() + resources.getString("propertiesTitle"), JOptionPane.OK_CANCEL_OPTION,
              JOptionPane.PLAIN_MESSAGE);
          if (result == JOptionPane.OK_OPTION) {
            Rectangle bounds = getBounds();
            panel.updateProperties();
            bounds.add(getBounds());
            notifyChange(bounds);
          }
        }
      }.start();
      return true;
    }
   
    return false;
  }

  /* (non-Javadoc)
   * @see jsynoptic.base.ContextualActionProvider#canDoAction(double, double, java.lang.Object, java.lang.String, int)
   */
  public boolean canDoAction(double x, double y, Object o, String action, int context) {
    return true;
  }


  /** A JPanel do display and change the properties of the SimpleShape
   */
  public class PropertiesPanel extends JPanel {

    protected JButton bdrawcolor;
    protected Color noColor;
    protected JCheckBox cbResize;
    protected JCheckBox cbRatio;
    protected JCheckBox cbdraw; // optional
    protected JLabel lwidth, lheight;
    protected NumberField nfWidth, nfHeight;
    protected transient DataSource sourceCopy;
    protected SourceTree dstree;
    protected AutomatonActionMapper mapperCopy;

    protected String _shapeName;

    private NumberField nfActiveX;
    private NumberField nfActiveY;
    private NumberField nfNumCellX;
    private NumberField nfNumCellY;

    public PropertiesPanel(String shapeName) {

      _shapeName = shapeName;
      // Initialize our copy fields (allow users to cancel changes)
      sourceCopy = source;
      try {
        mapperCopy = (AutomatonActionMapper)mapper.clone();
      } catch (CloneNotSupportedException e) {
        mapperCopy = mapper;
      }

      Box content = Box.createVerticalBox();

      Box topBox = Box.createHorizontalBox();

      JPanel gridPanel = new JPanel(new BorderLayout());
      gridPanel.setBorder(BorderFactory.createTitledBorder(resources.getString("GridArrayParameters")));
      JPanel colpane = new JPanel(new GridLayout(2,2));
      colpane.add(new JLabel(resources.getString("NumberOfColumns")));
      colpane.add(nfNumCellX = new NumberField(cells[0].length,5));
      colpane.add(new JLabel(resources.getString("ActiveColumn")));
      colpane.add(nfActiveX = new NumberField(activeX,5));
      gridPanel.add(colpane,BorderLayout.WEST);

      JPanel rowpane = new JPanel(new GridLayout(2,2));
      rowpane.add(new JLabel(resources.getString("NumberOfRows")));
      rowpane.add(nfNumCellY = new NumberField(cells.length,5));
      rowpane.add(new JLabel(resources.getString("ActiveRow")));
      rowpane.add(nfActiveY = new NumberField(activeY,5));
      gridPanel.add(rowpane,BorderLayout.EAST);
      topBox.add(gridPanel);

      JPanel dimensionsPanel = new JPanel(new BorderLayout());
      dimensionsPanel.setBorder(BorderFactory.createTitledBorder(resources.getString("Dimensions")));
      Box box = Box.createHorizontalBox();
      box.add(cbResize = new JCheckBox(resources.getString("AllowResize"),allowResize));
      box.add(Box.createHorizontalGlue());
      box.add(cbRatio = new JCheckBox(resources.getString("FixedRatio"),fixedRatio));
      dimensionsPanel.add(box,BorderLayout.NORTH);

      box = Box.createHorizontalBox();
      box.add(lwidth = new JLabel(resources.getString("Width")));
      box.add(nfWidth = new NumberField((long)_w));
      nfWidth.setHorizontalAlignment(JTextField.RIGHT);
      box.add(Box.createHorizontalGlue());
      box.add(lheight = new JLabel(resources.getString("Height")));
      box.add(nfHeight = new NumberField((long)_h));
      nfHeight.setHorizontalAlignment(JTextField.RIGHT);
      dimensionsPanel.add(box,BorderLayout.SOUTH);

      topBox.add(dimensionsPanel);

      content.add(topBox);

      box = Box.createHorizontalBox();
      JPanel panel = mapperCopy.createPanel(new JDialog(),null)// TODO refactoring on Automaton shape, do like
      // all other builtin shapes !
      panel.setBorder(BorderFactory.createTitledBorder(resources.getString("ActionMapper")));
      box.add(panel);

      panel = new JPanel(new BorderLayout());
      dstree = SourceTree.getFromPool("PropertiesPanel0");
      JScrollPane dslistScrollPane = new JScrollPane(dstree);
      panel.add(dslistScrollPane);
      panel.setBorder(BorderFactory.createTitledBorder(resources.getString("DataSource")));
      box.add(panel);
      dstree.setSelectedValue(sourceCopy);
      dstree.removeAllTreeSelectionListeners();
      dstree.addTreeSelectionListener(new TreeSelectionListener() {
        public void valueChanged(TreeSelectionEvent e) {
          if (!e.isAddedPath()) return;
          Object o = dstree.getSelectedSourceOrCollection();
          if (o instanceof DataSource) sourceCopy = (DataSource)o;
        }
      });

      content.add(box);

      add(content);
    }

    /**
     *
     */
    public void updateProperties() {

      int nx = (int)nfNumCellX.getLongValue();
      int ny = (int)nfNumCellY.getLongValue();
      int ax = (int)nfActiveX.getLongValue();
      int ay = (int)nfActiveY.getLongValue();

      if (nx<=0) nx = cells[0].length;
      if (ny<=0) ny = cells.length;
      if (ax<0) ax = 0; if (ax>=nx) ax = nx-1;
      if (ay<0) ay = 0; if (ay>=ny) ay = ny-1;
      activeX = ax;
      activeY = ay;

      // If the aray size was changed, update it
      if ((nx!=cells[0].length) || (ny!=cells.length)) {
        Cell[][] newCells = new Cell[ny][nx];
        int maxx = Math.min(nx,cells[0].length);
        int maxy = Math.min(ny,cells.length);
        // Copy the old array elements
        for (int j=0; j<maxy; ++j) {
          System.arraycopy(cells[j], 0, newCells[j], 0, maxx);
          // Initialize remaining cells on this row, if any
          for (int i=maxx; i<nx; ++i) newCells[j][i] = new Cell();
        }
        // Initialize remaining cells, if any
        for (int j=maxy; j<ny; ++j) for (int i=0; i<nx; ++i) newCells[j][i] = new Cell();
        cells = newCells;
      }

      allowResize = cbResize.isSelected();
      fixedRatio = cbRatio.isSelected();
      _w = (int)nfWidth.getLongValue();
      _h = (int)nfHeight.getLongValue();

      if (_w < nx * MIN_CELL_WIDTH) _w = nx * MIN_CELL_WIDTH;
      if (_h < ny * MIN_CELL_HEIGHT) _h = ny * MIN_CELL_HEIGHT;

      // round up to nearest multiple of number of cells
      _w = (int)(Math.ceil((double)_w / (double)nx) * nx);
      _h = (int)(Math.ceil((double)_h / (double)ny) * ny);

      ratio = (double)_w / (double)_h;

      if (source!=null) {
        source.removeListener(AutomatonShape.this);
        source.removeEndNotificationListener(AutomatonShape.this);
      }
      source = sourceCopy;
      if (source!=null) {
        try {
          index = source.getLastIndex();
        } catch (UnsupportedOperation e) {
          index = 0;
        }
        source.addListener(AutomatonShape.this);
        source.addEndNotificationListener(AutomatonShape.this);
      }

      mapper = mapperCopy;
    }

    public String getShapeName() {
      return _shapeName;
    }

  }

  /**
   * @return
   */
  public PropertiesPanel createPanel() {
    return new PropertiesPanel(Builtin.resources.getString("Automaton"));
  }

  /** Apply the automaton rules on the active cell */
  public void applyRules() {

    AutomatonActionList list = (AutomatonActionList)mapper.getMapping(source, index);
    if (list==null) return; // No rules, no change

    // Apply the actions in order
    for (Iterator it = list.iterator(); it.hasNext(); ) {
      AutomatonAction rule = (AutomatonAction)it.next();
      switch (rule.action) {
      case AutomatonAction.MOVE_UP:
        activeY--;
        if (activeY>=0) break; // OK
        if (AutomatonAction.OPTION_WRAP.equals(rule.option)) {
          activeY = cells.length-1;
          break;
        }
        if (AutomatonAction.OPTION_EXTEND.equals(rule.option)) {
          activeY = 0;
          Cell[][] newCells = new Cell[cells.length+1][cells[0].length];
          // Initialize first row
          for (int i=0; i<cells[0].length; ++i) newCells[0][i] = new Cell();
          // Copy the others
          for (int j=0; j<cells.length; ++j) newCells[j+1] = cells[j];
          cells = newCells;

          if (_h < cells.length * MIN_CELL_HEIGHT) _h = cells.length * MIN_CELL_HEIGHT;
          // round up to nearest multiple of number of cells
          _h = (int)(Math.ceil((double)_h / (double)cells.length) * cells.length);
          if (fixedRatio) {
            _w = (int)(Math.ceil((double)(_h*ratio) / (double)cells[0].length) * cells[0].length);
          }

          break;
        }
        // option null or set to resources.getString("DoNothing")
        activeY = 0;
        break;
      case AutomatonAction.MOVE_RIGHT:
        activeX++;
        if (activeX<cells[0].length) break; // OK
        if (AutomatonAction.OPTION_WRAP.equals(rule.option)) {
          activeX = 0;
          break;
        }
        if (AutomatonAction.OPTION_EXTEND.equals(rule.option)) {
          activeX = cells[0].length;
          Cell[][] newCells = new Cell[cells.length][cells[0].length+1];
          for (int j=0; j<cells.length; ++j) {
            // Copy existing cells
            System.arraycopy(cells[j],0,newCells[j],0,cells[0].length);
            // initialize the last one
            newCells[j][cells[0].length] = new Cell();
          }
          cells = newCells;

          if (_w < cells[0].length * MIN_CELL_WIDTH) _w = cells[0].length * MIN_CELL_WIDTH;
          // round up to nearest multiple of number of cells
          _w = (int)(Math.ceil((double)_w / (double)cells[0].length) * cells[0].length);
          if (fixedRatio) {
            _h = (int)(Math.ceil((double)(_w/ratio) / (double)cells.length) * cells.length);
          }

          break;
        }
        // option null or set to resources.getString("DoNothing")
        activeX = cells[0].length-1;
        break;
      case AutomatonAction.MOVE_DOWN:
        activeY++;
        if (activeY<cells.length) break; // OK
        if (AutomatonAction.OPTION_WRAP.equals(rule.option)) {
          activeY = 0;
          break;
        }
        if (AutomatonAction.OPTION_EXTEND.equals(rule.option)) {
          activeY = cells.length;
          Cell[][] newCells = new Cell[cells.length+1][cells[0].length];
          // Initialize last row
          for (int i=0; i<cells[0].length; ++i) newCells[cells.length][i] = new Cell();
          // Copy the others
          for (int j=0; j<cells.length; ++j) newCells[j] = cells[j];
          cells = newCells;

          if (_h < cells.length * MIN_CELL_HEIGHT) _h = cells.length * MIN_CELL_HEIGHT;
          // round up to nearest multiple of number of cells
          _h = (int)(Math.ceil((double)_h / (double)cells.length) * cells.length);
          if (fixedRatio) {
            _w = (int)(Math.ceil((double)(_h*ratio) / (double)cells[0].length) * cells[0].length);
          }

          break;
        }
        // option null or set to resources.getString("DoNothing")
        activeY = cells.length-1;
        break;
      case AutomatonAction.MOVE_LEFT:
        activeX--;
        if (activeX>=0) break; // OK
        if (AutomatonAction.OPTION_WRAP.equals(rule.option)) {
          activeX = cells[0].length-1;
          break;
        }
        if (AutomatonAction.OPTION_EXTEND.equals(rule.option)) {
          activeX = 0;
          Cell[][] newCells = new Cell[cells.length][cells[0].length+1];
          for (int j=0; j<cells.length; ++j) {
            // initialize the first one
            newCells[j][0] = new Cell();
            // Copy existing cells
            System.arraycopy(cells[j],0,newCells[j],1,cells[0].length);
          }
          cells = newCells;

          if (_w < cells[0].length * MIN_CELL_WIDTH) _w = cells[0].length * MIN_CELL_WIDTH;
          // round up to nearest multiple of number of cells
          _w = (int)(Math.ceil((double)_w / (double)cells[0].length) * cells[0].length);
          if (fixedRatio) {
            _h = (int)(Math.ceil((double)(_w/ratio) / (double)cells.length) * cells.length);
          }

          break;
        }
        // option null or set to resources.getString("DoNothing")
        activeX = 0;
        break;
      case AutomatonAction.SET_BACKGROUND_COLOR:
        if ((rule.option==null) || (!(rule.option instanceof Color))) break;
        cells[activeY][activeX].backgroundColor = (Color)rule.option;
        break;
      case AutomatonAction.SET_FRAME_COLOR:
        if ((rule.option==null) || (!(rule.option instanceof Color))) break;
        cells[activeY][activeX].frameColor = (Color)rule.option;
        break;
      case AutomatonAction.SET_TEXT_COLOR:
        if ((rule.option==null) || (!(rule.option instanceof Color))) break;
        cells[activeY][activeX].textColor = (Color)rule.option;
        break;
      case AutomatonAction.SET_TEXT:
        if ((rule.option==null) || (!(rule.option instanceof Object[]))) break;
        Object[] opt = (Object[])rule.option;
        int format = ((Integer)opt[0]).intValue();
        if (format == TextShape.FORMAT_MAPPER) {
          cells[activeY][activeX].text = opt[1]==null ? null : opt[1].toString();
          break;
        }
        Object o;
        try {
          o = source.getValue(index);
        } catch (DataException e) {
          cells[activeY][activeX].text = null;
          break;
        }
        if (!(o instanceof Number)) {
          cells[activeY][activeX].text = o.toString();
          break;
        }
        Number n = (Number)o;
        switch(format) {
        case TextShape.FORMAT_DECIMAL:
        case TextShape.FORMAT_SCIENTIFIC:
          cells[activeY][activeX].text = ((NumberFormat)opt[1]).format(n);
          break;
        case TextShape.FORMAT_HEXADECIMAL:
          cells[activeY][activeX].text = "0x" + Long.toHexString(n.longValue()).toUpperCase();
          break;
        case TextShape.FORMAT_OCTAL:
          cells[activeY][activeX].text = "0" + Long.toOctalString(n.longValue());
          break;
        case TextShape.FORMAT_BINARY:
          cells[activeY][activeX].text = Long.toBinaryString(n.longValue());
          break;
        default:
        case TextShape.FORMAT_STRING:
          cells[activeY][activeX].text = o.toString();
        }
        break;
      }
    }
    notifyChange();
  }


  /* (non-Javadoc)
   * @see simtools.data.DataSourceListener#DataSourceIndexRangeChanged(simtools.data.DataSource, long, long)
   */
  public void DataSourceIndexRangeChanged(DataSource ds, long startIndex, long lastIndex) {

    if (!ds.equals(this.source)) return;
    index = lastIndex;
    dirtyState = true;

  }

  /* (non-Javadoc)
   * @see simtools.data.DataSourceListener#DataSourceInfoChanged(simtools.data.DataSource, simtools.data.DataInfo)
   */
  public void DataSourceInfoChanged(DataSource ds, DataInfo newInfo) {
    // don't care about this one
  }

  /* (non-Javadoc)
   * @see simtools.data.DataSourceListener#DataSourceOrderChanged(simtools.data.DataSource, int)
   */
  public void DataSourceOrderChanged(DataSource ds, int newOrder) {
    // don't care about this one
  }

  /* (non-Javadoc)
   * @see simtools.data.DataSourceListener#DataSourceValueChanged(simtools.data.DataSource, long, long)
   */
  public void DataSourceValueChanged(DataSource ds, long minIndex, long maxIndex) {

    if (!ds.equals(this.source)) return;
    // We care only about our index value change
    if ((index < minIndex) || (index > maxIndex)) return;
    dirtyState = true;
  }

  /* (non-Javadoc)
   * @see simtools.data.DataSourceListener#DataSourceValueRangeChanged(simtools.data.DataSource)
   */
  public void DataSourceValueRangeChanged(DataSource ds) {
    // don't care about this one
  }

  /* (non-Javadoc)
   * @see simtools.data.DataSourceListener#DataSourceReplaced(simtools.data.DataSource, simtools.data.DataSource)
   */
  public void DataSourceReplaced(DataSource oldData, DataSource newData) {
    if(oldData==source){
      source=newData;
      if (source!=null) try {
        source.addListener(this);
        source.addEndNotificationListener(this);
        index = source.getLastIndex();
      }
      catch (UnsupportedOperation uo1) {
        index = 0;
      }
      dirtyState=true;
    }
  }
 
 


    /* (non-Javadoc)
     * @see simtools.shapes.AbstractShape#subscribeToDataNotifications()
     */
    public void processShapeRestoring(){

        if (source!=null) {
            source.addListener(this);
            source.addEndNotificationListener(this);
            try {
                index = source.getLastIndex();
            } catch (UnsupportedOperation uo1) {
                index = 0;
            }
        }
       
        super.processShapeRestoring();
    }


    /* (non-Javadoc)
     * @see simtools.shapes.AbstractShape#unsubscribeToDataNotifications()
     */
    public void processShapeRemoving(){
        if (source != null) {
            source.removeListener(this);
            source.removeEndNotificationListener(this);
        }
        super.processShapeRemoving();
    }


  /* (non-Javadoc)
   * @see simtools.data.EndNotificationListener#notificationEnd(java.lang.Object)
   */
  public void notificationEnd(Object referer) {
    if (dirtyState) applyRules();
    dirtyState = false; // for next time
  }


  /* (non-Javadoc)
   * @see simtools.diagram.Resizable#resize(int, int)
   */
  public void resize(int dx, int dy) {
    if (!allowResize) return;

    _w += dx; _h += dy;
    if (fixedRatio) {
      double dw = Math.max((double)_w, _h*ratio);
      _w = (int) dw;
      _h = (int)(dw / ratio);
    }

    int nx = cells[0].length;
    int ny=cells.length;

    if (_w < nx * MIN_CELL_WIDTH) _w = nx * MIN_CELL_WIDTH;
    if (_h < ny * MIN_CELL_HEIGHT) _h = ny * MIN_CELL_HEIGHT;

    // round up to nearest multiple of number of cells
    if (dx>=0) _w = (int)(Math.ceil((double)_w / (double)nx) * nx);
    else _w = (int)(Math.floor((double)_w / (double)nx) * nx);
    if (dy>=0) _h = (int)(Math.ceil((double)_h / (double)ny) * ny);
    else _h = (int)(Math.floor((double)_h / (double)ny) * ny);

    if (!fixedRatio) ratio = (double)_w / (double)_h;

  }

//  Take care of serialisation. Special handling for datasources

  private void writeObject(java.io.ObjectOutputStream out) throws java.io.IOException {
    out.defaultWriteObject();
    DataSourcePool.global.writeDataSource(out, source);
  }

  private void readObject(java.io.ObjectInputStream in) throws java.lang.ClassNotFoundException, java.io.IOException {
    in.defaultReadObject();
    source = DataSourcePool.global.readDataSource(in);
    if (source!=null) try {
      source.addListener(this);
      source.addEndNotificationListener(this);
      index = source.getLastIndex();
    }
    catch (UnsupportedOperation uo1) {
      index = 0;
    }

  }

}
TOP

Related Classes of jsynoptic.builtin.AutomatonShape$Cell

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.