Package com.cburch.logisim.std.io

Source Code of com.cburch.logisim.std.io.DotMatrix$State

/* Copyright (c) 2010, Carl Burch. License information is located in the
* com.cburch.logisim.Main source code and at www.cburch.com/logisim/. */

package com.cburch.logisim.std.io;

import java.awt.Color;
import java.awt.Graphics;
import java.util.Arrays;

import com.cburch.logisim.data.Attribute;
import com.cburch.logisim.data.AttributeOption;
import com.cburch.logisim.data.AttributeSet;
import com.cburch.logisim.data.Attributes;
import com.cburch.logisim.data.Bounds;
import com.cburch.logisim.data.Value;
import com.cburch.logisim.instance.Instance;
import com.cburch.logisim.instance.InstanceData;
import com.cburch.logisim.instance.InstanceFactory;
import com.cburch.logisim.instance.InstancePainter;
import com.cburch.logisim.instance.InstanceState;
import com.cburch.logisim.instance.Port;
import com.cburch.logisim.std.wiring.DurationAttribute;
import com.cburch.logisim.util.GraphicsUtil;

// TODO repropagate when rows/cols change

public class DotMatrix extends InstanceFactory {
  static final AttributeOption INPUT_SELECT
    = new AttributeOption("select", Strings.getter("ioInputSelect"));
  static final AttributeOption INPUT_COLUMN
    = new AttributeOption("column", Strings.getter("ioInputColumn"));
  static final AttributeOption INPUT_ROW
    = new AttributeOption("row", Strings.getter("ioInputRow"));

  static final AttributeOption SHAPE_CIRCLE
    = new AttributeOption("circle", Strings.getter("ioShapeCircle"));
  static final AttributeOption SHAPE_SQUARE
    = new AttributeOption("square", Strings.getter("ioShapeSquare"));
 
  static final Attribute<AttributeOption> ATTR_INPUT_TYPE
    = Attributes.forOption("inputtype", Strings.getter("ioMatrixInput"),
      new AttributeOption[] { INPUT_COLUMN, INPUT_ROW, INPUT_SELECT });
  static final Attribute<Integer> ATTR_MATRIX_COLS
    = Attributes.forIntegerRange("matrixcols",
        Strings.getter("ioMatrixCols"), 1, Value.MAX_WIDTH);
  static final Attribute<Integer> ATTR_MATRIX_ROWS
    = Attributes.forIntegerRange("matrixrows",
        Strings.getter("ioMatrixRows"), 1, Value.MAX_WIDTH);
  static final Attribute<AttributeOption> ATTR_DOT_SHAPE
    = Attributes.forOption("dotshape", Strings.getter("ioMatrixShape"),
      new AttributeOption[] { SHAPE_CIRCLE, SHAPE_SQUARE });
  static final Attribute<Integer> ATTR_PERSIST = new DurationAttribute("persist",
      Strings.getter("ioMatrixPersistenceAttr"), 0, Integer.MAX_VALUE);

  public DotMatrix() {
    super("DotMatrix", Strings.getter("dotMatrixComponent"));
    setAttributes(new Attribute<?>[] {
        ATTR_INPUT_TYPE, ATTR_MATRIX_COLS, ATTR_MATRIX_ROWS,
        Io.ATTR_ON_COLOR, Io.ATTR_OFF_COLOR,
        ATTR_PERSIST, ATTR_DOT_SHAPE
      }, new Object[] {
        INPUT_COLUMN, Integer.valueOf(5), Integer.valueOf(7),
        Color.GREEN, Color.DARK_GRAY, Integer.valueOf(0), SHAPE_SQUARE
      });
    setIconName("dotmat.gif");
  }

  @Override
  public Bounds getOffsetBounds(AttributeSet attrs) {
    Object input = attrs.getValue(ATTR_INPUT_TYPE);
    int cols = attrs.getValue(ATTR_MATRIX_COLS).intValue();
    int rows = attrs.getValue(ATTR_MATRIX_ROWS).intValue();
    if (input == INPUT_COLUMN) {
      return Bounds.create(-5, -10 * rows, 10 * cols, 10 * rows);
    } else if (input == INPUT_ROW) {
      return Bounds.create(0, -5, 10 * cols, 10 * rows);
    } else { // input == INPUT_SELECT
      if (rows == 1) {
        return Bounds.create(0, -5, 10 * cols, 10 * rows);
      } else {
        return Bounds.create(0, -5 * rows + 5, 10 * cols, 10 * rows);
      }
    }
  }

  @Override
  protected void configureNewInstance(Instance instance) {
    instance.addAttributeListener();
    updatePorts(instance);
  }

  @Override
  protected void instanceAttributeChanged(Instance instance, Attribute<?> attr) {
    if (attr == ATTR_MATRIX_ROWS || attr == ATTR_MATRIX_COLS
        || attr == ATTR_INPUT_TYPE) {
      instance.recomputeBounds();
      updatePorts(instance);
    }
  }
 
  private void updatePorts(Instance instance) {
    Object input = instance.getAttributeValue(ATTR_INPUT_TYPE);
    int rows = instance.getAttributeValue(ATTR_MATRIX_ROWS).intValue();
    int cols = instance.getAttributeValue(ATTR_MATRIX_COLS).intValue();
    Port[] ps;
    if (input == INPUT_COLUMN) {
      ps = new Port[cols];
      for (int i = 0; i < cols; i++) {
        ps[i] = new Port(10 * i, 0, Port.INPUT, rows);
      }
    } else if (input == INPUT_ROW) {
      ps = new Port[rows];
      for (int i = 0; i < rows; i++) {
        ps[i] = new Port(0, 10 * i, Port.INPUT, cols);
      }
    } else {
      if (rows <= 1) {
        ps = new Port[] { new Port(0, 0, Port.INPUT, cols) };
      } else if (cols <= 1) {
        ps = new Port[] { new Port(0, 0, Port.INPUT, rows) };
      } else {
        ps = new Port[] {
            new Port(0, 0, Port.INPUT, cols),
            new Port(0, 10, Port.INPUT, rows)
        };
      }
    }
    instance.setPorts(ps);
  }
 
  private State getState(InstanceState state) {
    int rows = state.getAttributeValue(ATTR_MATRIX_ROWS).intValue();
    int cols = state.getAttributeValue(ATTR_MATRIX_COLS).intValue();
    long clock = state.getTickCount();
   
    State data = (State) state.getData();
    if (data == null) {
      data = new State(rows, cols, clock);
      state.setData(data);
    } else {
      data.updateSize(rows, cols, clock);
    }
    return data;
  }

  @Override
  public void propagate(InstanceState state) {
    Object type = state.getAttributeValue(ATTR_INPUT_TYPE);
    int rows = state.getAttributeValue(ATTR_MATRIX_ROWS).intValue();
    int cols = state.getAttributeValue(ATTR_MATRIX_COLS).intValue();
    long clock = state.getTickCount();
    long persist = clock + state.getAttributeValue(ATTR_PERSIST).intValue();
   
    State data = getState(state);
    if (type == INPUT_ROW) {
      for (int i = 0; i < rows; i++) {
        data.setRow(i, state.getPort(i), persist);
      }
    } else if (type == INPUT_COLUMN) {
      for (int i = 0; i < cols; i++) {
        data.setColumn(i, state.getPort(i), persist);
      }
    } else if (type == INPUT_SELECT) {
      data.setSelect(state.getPort(1), state.getPort(0), persist);
    } else {
      throw new RuntimeException("unexpected matrix type");
    }
  }

  @Override
  public void paintInstance(InstancePainter painter) {
    Color onColor = painter.getAttributeValue(Io.ATTR_ON_COLOR);
    Color offColor = painter.getAttributeValue(Io.ATTR_OFF_COLOR);
    boolean drawSquare = painter.getAttributeValue(ATTR_DOT_SHAPE) == SHAPE_SQUARE;

    State data = getState(painter);
    long ticks = painter.getTickCount();
    Bounds bds = painter.getBounds();
    boolean showState = painter.getShowState();
    Graphics g = painter.getGraphics();
    int rows = data.rows;
    int cols = data.cols;
    for (int j = 0; j < rows; j++) {
      for (int i = 0; i < cols; i++) {
        int x = bds.getX() + 10 * i;
        int y = bds.getY() + 10 * j;
        if (showState) {
          Value val = data.get(j, i, ticks);
          Color c;
          if (val == Value.TRUE) c = onColor;
          else if (val == Value.FALSE) c = offColor;
          else c = Value.ERROR_COLOR;
          g.setColor(c);
         
          if (drawSquare) g.fillRect(x, y, 10, 10);
          else g.fillOval(x + 1, y + 1, 8, 8);
        } else {
          g.setColor(Color.GRAY);
          g.fillOval(x + 1, y + 1, 8, 8);
        }
      }
    }
    g.setColor(Color.BLACK);
    GraphicsUtil.switchToWidth(g, 2);
    g.drawRect(bds.getX(), bds.getY(), bds.getWidth(), bds.getHeight());
    GraphicsUtil.switchToWidth(g, 1);
    painter.drawPorts();
  }
 
  private static class State implements InstanceData, Cloneable {
    private int rows;
    private int cols;
    private Value[] grid;
    private long[] persistTo;
   
    public State(int rows, int cols, long curClock) {
      this.rows = -1;
      this.cols = -1;
      updateSize(rows, cols, curClock);
    }
   
    @Override
    public Object clone() {
      try {
        State ret = (State) super.clone();
        ret.grid = this.grid.clone();
        ret.persistTo = this.persistTo.clone();
        return ret;
      } catch (CloneNotSupportedException e) {
        return null;
      }
    }
   
    private void updateSize(int rows, int cols, long curClock) {
      if (this.rows != rows || this.cols != cols) {
        this.rows = rows;
        this.cols = cols;
        int length = rows * cols;
        grid = new Value[length];
        persistTo = new long[length];
        Arrays.fill(grid, Value.UNKNOWN);
        Arrays.fill(persistTo, curClock - 1);
      }
    }
   
    private Value get(int row, int col, long curTick) {
      int index = row * cols + col;
      Value ret = grid[index];
      if (ret == Value.FALSE && persistTo[index] - curTick >= 0) {
        ret = Value.TRUE;
      }
      return ret;
    }
   
    private void setRow(int index, Value rowVector, long persist) {
      int gridloc = (index + 1) * cols - 1;
      int stride = -1;
      Value[] vals = rowVector.getAll();
      for (int i = 0; i < vals.length; i++, gridloc += stride) {
        Value val = vals[i];
        if (grid[gridloc] == Value.TRUE) {
          persistTo[gridloc] = persist - 1;
        }
        grid[gridloc] = vals[i];
        if (val == Value.TRUE) {
          persistTo[gridloc] = persist;
        }
      }
    }
   
    private void setColumn(int index, Value colVector, long persist) {
      int gridloc = (rows - 1) * cols + index;
      int stride = -cols;
      Value[] vals = colVector.getAll();
      for (int i = 0; i < vals.length; i++, gridloc += stride) {
        Value val = vals[i];
        if (grid[gridloc] == Value.TRUE) {
          persistTo[gridloc] = persist - 1;
        }
        grid[gridloc] = val;
        if (val == Value.TRUE) {
          persistTo[gridloc] = persist;
        }
      }
    }
   
    private void setSelect(Value rowVector, Value colVector, long persist) {
      Value[] rowVals = rowVector.getAll();
      Value[] colVals = colVector.getAll();
      int gridloc = 0;
      for (int i = rowVals.length - 1; i >= 0; i--) {
        Value wholeRow = rowVals[i];
        if (wholeRow == Value.TRUE) {
          for (int j = colVals.length - 1; j >= 0; j--, gridloc++) {
            Value val = colVals[colVals.length - 1 - j];
            if (grid[gridloc] == Value.TRUE) {
              persistTo[gridloc] = persist - 1;
            }
            grid[gridloc] = val;
            if (val == Value.TRUE) {
              persistTo[gridloc] = persist;
            }
          }
        } else {
          if (wholeRow != Value.FALSE) wholeRow = Value.ERROR;
          for (int j = colVals.length - 1; j >= 0; j--, gridloc++) {
            if (grid[gridloc] == Value.TRUE) {
              persistTo[gridloc] = persist - 1;
            }
            grid[gridloc] = wholeRow;
          }
        }
      }
    }
  }
}
TOP

Related Classes of com.cburch.logisim.std.io.DotMatrix$State

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.