Package com.cburch.logisim.std.wiring

Source Code of com.cburch.logisim.std.wiring.Pin$PinLogger

/* 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.wiring;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;

import javax.swing.Icon;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;

import com.cburch.logisim.circuit.CircuitState;
import com.cburch.logisim.circuit.RadixOption;
import com.cburch.logisim.comp.EndData;
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.BitWidth;
import com.cburch.logisim.data.Bounds;
import com.cburch.logisim.data.Direction;
import com.cburch.logisim.data.Location;
import com.cburch.logisim.data.Value;
import com.cburch.logisim.gui.main.Canvas;
import com.cburch.logisim.instance.Instance;
import com.cburch.logisim.instance.InstanceData;
import com.cburch.logisim.instance.InstanceFactory;
import com.cburch.logisim.instance.InstanceLogger;
import com.cburch.logisim.instance.InstancePainter;
import com.cburch.logisim.instance.InstancePoker;
import com.cburch.logisim.instance.InstanceState;
import com.cburch.logisim.instance.Port;
import com.cburch.logisim.instance.StdAttr;
import com.cburch.logisim.tools.key.BitWidthConfigurator;
import com.cburch.logisim.tools.key.DirectionConfigurator;
import com.cburch.logisim.tools.key.JoinedConfigurator;
import com.cburch.logisim.util.GraphicsUtil;
import com.cburch.logisim.util.Icons;

public class Pin extends InstanceFactory {
  public static final Attribute<Boolean> ATTR_TRISTATE
    = Attributes.forBoolean("tristate", Strings.getter("pinThreeStateAttr"));
  public static final Attribute<Boolean> ATTR_TYPE
    = Attributes.forBoolean("output", Strings.getter("pinOutputAttr"));
  public static final Attribute<Direction> ATTR_LABEL_LOC
    = Attributes.forDirection("labelloc", Strings.getter("pinLabelLocAttr"));
 
  public static final AttributeOption PULL_NONE
    = new AttributeOption("none", Strings.getter("pinPullNoneOption"));
  public static final AttributeOption PULL_UP
    = new AttributeOption("up", Strings.getter("pinPullUpOption"));
  public static final AttributeOption PULL_DOWN
    = new AttributeOption("down", Strings.getter("pinPullDownOption"));
  public static final Attribute<AttributeOption> ATTR_PULL
    = Attributes.forOption("pull", Strings.getter("pinPullAttr"),
        new AttributeOption[] { PULL_NONE, PULL_UP, PULL_DOWN });
 
  public static final Pin FACTORY = new Pin();

  private static final Icon ICON_IN = Icons.getIcon("pinInput.gif");
  private static final Icon ICON_OUT = Icons.getIcon("pinOutput.gif");
  private static final Font ICON_WIDTH_FONT = new Font("SansSerif", Font.BOLD, 9);
  private static final Color ICON_WIDTH_COLOR = Value.WIDTH_ERROR_COLOR.darker();

  public Pin() {
    super("Pin", Strings.getter("pinComponent"));
    setFacingAttribute(StdAttr.FACING);
    setKeyConfigurator(JoinedConfigurator.create(
      new BitWidthConfigurator(StdAttr.WIDTH),
      new DirectionConfigurator(ATTR_LABEL_LOC, KeyEvent.ALT_DOWN_MASK)));
    setInstanceLogger(PinLogger.class);
    setInstancePoker(PinPoker.class);
  }

  @Override
  public AttributeSet createAttributeSet() {
    return new PinAttributes();
  }

  @Override
  public Bounds getOffsetBounds(AttributeSet attrs) {
    Direction facing = attrs.getValue(StdAttr.FACING);
    BitWidth width = attrs.getValue(StdAttr.WIDTH);
    return Probe.getOffsetBounds(facing, width, RadixOption.RADIX_2);
  }
 
  //
  // graphics methods
  //
  @Override
  public void paintIcon(InstancePainter painter) {
    paintIconBase(painter);
    BitWidth w = painter.getAttributeValue(StdAttr.WIDTH);
    if (!w.equals(BitWidth.ONE)) {
      Graphics g = painter.getGraphics();
      g.setColor(ICON_WIDTH_COLOR);
      g.setFont(ICON_WIDTH_FONT);
      GraphicsUtil.drawCenteredText(g, "" + w.getWidth(), 10, 9);
      g.setColor(Color.BLACK);
    }
  }

  private void paintIconBase(InstancePainter painter) {
    PinAttributes attrs = (PinAttributes) painter.getAttributeSet();
    Direction dir = attrs.facing;
    boolean output = attrs.isOutput();
    Graphics g = painter.getGraphics();
    if (output) {
      if (ICON_OUT != null) {
        Icons.paintRotated(g, 2, 2, dir, ICON_OUT,
            painter.getDestination());
        return;
      }
    } else {
      if (ICON_IN != null) {
        Icons.paintRotated(g, 2, 2, dir, ICON_IN,
            painter.getDestination());
        return;
      }
    }
    int pinx = 16; int piny = 9;
    if (dir == Direction.EAST) { // keep defaults
    } else if (dir == Direction.WEST) { pinx = 4;
    } else if (dir == Direction.NORTH) { pinx = 9; piny = 4;
    } else if (dir == Direction.SOUTH) { pinx = 9; piny = 16;
    }

    g.setColor(Color.black);
    if (output) {
      g.drawOval(4, 4, 13, 13);
    } else {
      g.drawRect(4, 4, 13, 13);
    }
    g.setColor(Value.TRUE.getColor());
    g.fillOval(7, 788);
    g.fillOval(pinx, piny, 3, 3);
  }

  @Override
  public void paintGhost(InstancePainter painter) {
    PinAttributes attrs = (PinAttributes) painter.getAttributeSet();
    Location loc = painter.getLocation();
    Bounds bds = painter.getOffsetBounds();
    int x = loc.getX();
    int y = loc.getY();
    Graphics g = painter.getGraphics();
    GraphicsUtil.switchToWidth(g, 2);
    boolean output = attrs.isOutput();
    if (output) {
      BitWidth width = attrs.getValue(StdAttr.WIDTH);
      if (width == BitWidth.ONE) {
        g.drawOval(x + bds.getX() + 1, y + bds.getY() + 1,
          bds.getWidth() - 1, bds.getHeight() - 1);
      } else {
        g.drawRoundRect(x + bds.getX() + 1, y + bds.getY() + 1,
          bds.getWidth() - 1, bds.getHeight() - 1, 6, 6);
      }
    } else {
      g.drawRect(x + bds.getX() + 1, y + bds.getY() + 1,
        bds.getWidth() - 1, bds.getHeight() - 1);
    }
  }

  @Override
  public void paintInstance(InstancePainter painter) {
    PinAttributes attrs = (PinAttributes) painter.getAttributeSet();
    Graphics g = painter.getGraphics();
    Bounds bds = painter.getInstance().getBounds(); // intentionally with no graphics object - we don't want label included
    int x = bds.getX();
    int y = bds.getY();
    GraphicsUtil.switchToWidth(g, 2);
    g.setColor(Color.black);
    if (attrs.type == EndData.OUTPUT_ONLY) {
      if (attrs.width.getWidth() == 1) {
        g.drawOval(x + 1, y + 1,
          bds.getWidth() - 1, bds.getHeight() - 1);
      } else {
        g.drawRoundRect(x + 1, y + 1,
          bds.getWidth() - 1, bds.getHeight() - 1, 6, 6);
      }
    } else {
      g.drawRect(x + 1, y + 1,
        bds.getWidth() - 1, bds.getHeight() - 1);
    }
 
    painter.drawLabel();
 
    if (!painter.getShowState()) {
      g.setColor(Color.BLACK);
      GraphicsUtil.drawCenteredText(g, "x" + attrs.width.getWidth(),
          bds.getX() + bds.getWidth() / 2, bds.getY() + bds.getHeight() / 2);
    } else {
      PinState state = getState(painter);
      if (attrs.width.getWidth() <= 1) {
        Value receiving = state.receiving;
        g.setColor(receiving.getColor());
        g.fillOval(x + 4, y + 4, 13, 13);
 
        if (attrs.width.getWidth() == 1) {
          g.setColor(Color.WHITE);
          GraphicsUtil.drawCenteredText(g,
            state.sending.toDisplayString(), x + 11, y + 9);
        }
      } else {
        Probe.paintValue(painter, state.sending);
      }
    }
 
    painter.drawPorts();
  }
 
  //
  // methods for instances
  //
  @Override
  protected void configureNewInstance(Instance instance) {
    PinAttributes attrs = (PinAttributes) instance.getAttributeSet();
    instance.addAttributeListener();
    configurePorts(instance);
    Probe.configureLabel(instance, attrs.labelloc, attrs.facing);
  }
 
  @Override
  protected void instanceAttributeChanged(Instance instance, Attribute<?> attr) {
    if (attr == ATTR_TYPE) {
      configurePorts(instance);
    } else if (attr == StdAttr.WIDTH || attr == StdAttr.FACING
        || attr == Pin.ATTR_LABEL_LOC) {
      instance.recomputeBounds();
      PinAttributes attrs = (PinAttributes) instance.getAttributeSet();
      Probe.configureLabel(instance, attrs.labelloc, attrs.facing);
    }
  }
 
  private void configurePorts(Instance instance) {
    PinAttributes attrs = (PinAttributes) instance.getAttributeSet();
    String endType = attrs.isOutput() ? Port.INPUT : Port.OUTPUT;
    Port port = new Port(0, 0, endType, StdAttr.WIDTH);
    if (attrs.isOutput()) {
      port.setToolTip(Strings.getter("pinOutputToolTip"));
    } else {
      port.setToolTip(Strings.getter("pinInputToolTip"));
    }
    instance.setPorts(new Port[] { port });
  }
 
  @Override
  public void propagate(InstanceState state) {
    PinAttributes attrs = (PinAttributes) state.getAttributeSet();
    Value val = state.getPort(0);
 
    PinState q = getState(state);
    if (attrs.type == EndData.OUTPUT_ONLY) {
      q.sending = val;
      q.receiving = val;
      state.setPort(0, Value.createUnknown(attrs.width), 1);
    } else {
      if (!val.isFullyDefined() && !attrs.threeState
          && state.isCircuitRoot()) {
        q.sending = pull2(q.sending, attrs.width);
        q.receiving = pull2(val, attrs.width);
        state.setPort(0, q.sending, 1);
      } else {
        q.receiving = val;
        if (!val.equals(q.sending)) { // ignore if no change
          state.setPort(0, q.sending, 1);
        }
      }
    }
  }

  private static Value pull2(Value mod, BitWidth expectedWidth) {
    if (mod.getWidth() == expectedWidth.getWidth()) {
      Value[] vs = mod.getAll();
      for (int i = 0; i < vs.length; i++) {
        if (vs[i] == Value.UNKNOWN) vs[i] = Value.FALSE;
      }
      return Value.create(vs);
    } else {
      return Value.createKnown(expectedWidth, 0);
    }
  }
 
  //
  // basic information methods
  //
  public BitWidth getWidth(Instance instance) {
    PinAttributes attrs = (PinAttributes) instance.getAttributeSet();
    return attrs.width;
  }

  public int getType(Instance instance) {
    PinAttributes attrs = (PinAttributes) instance.getAttributeSet();
    return attrs.type;
  }

  public boolean isInputPin(Instance instance) {
    PinAttributes attrs = (PinAttributes) instance.getAttributeSet();
    return attrs.type != EndData.OUTPUT_ONLY;
  }
 
  //
  // state information methods
  //
  public Value getValue(InstanceState state) {
    return getState(state).sending;
  }
 
  public void setValue(InstanceState state, Value value) {
    PinAttributes attrs = (PinAttributes) state.getAttributeSet();
    Object pull = attrs.pull;
    if (pull != PULL_NONE && pull != null && !value.isFullyDefined()) {
      Value[] bits = value.getAll();
      if (pull == PULL_UP) {
        for (int i = 0; i < bits.length; i++) {
          if (bits[i] != Value.FALSE) bits[i] = Value.TRUE;
        }
      } else if (pull == PULL_DOWN) {
        for (int i = 0; i < bits.length; i++) {
          if (bits[i] != Value.TRUE) bits[i] = Value.FALSE;
        }
      }
      value = Value.create(bits);
    }
   
    PinState myState = getState(state);
    if (value == Value.NIL) {
      myState.sending = Value.createUnknown(attrs.width);
    } else {
      myState.sending = value;
    }
  }
 
  private static PinState getState(InstanceState state) {
    PinAttributes attrs = (PinAttributes) state.getAttributeSet();
    BitWidth width = attrs.width;
    PinState ret = (PinState) state.getData();
    if (ret == null) {
      Value val = attrs.threeState ? Value.UNKNOWN : Value.FALSE;
      if (width.getWidth() > 1) {
        Value[] arr = new Value[width.getWidth()];
        java.util.Arrays.fill(arr, val);
        val = Value.create(arr);
      }
      ret = new PinState(val, val);
      state.setData(ret);
    }
    if (ret.sending.getWidth() != width.getWidth()) {
      ret.sending = ret.sending.extendWidth(width.getWidth(),
          attrs.threeState ? Value.UNKNOWN : Value.FALSE);
    }
    if (ret.receiving.getWidth() != width.getWidth()) {
      ret.receiving = ret.receiving.extendWidth(width.getWidth(), Value.UNKNOWN);
    }
    return ret;
  }

  private static class PinState implements InstanceData, Cloneable {
    Value sending;
    Value receiving;
   
    public PinState(Value sending, Value receiving) {
      this.sending = sending;
      this.receiving = receiving;
    }
   
    @Override
    public Object clone() {
      try { return super.clone(); }
      catch (CloneNotSupportedException e) { return null; }
    }
  }
 
  public static class PinPoker extends InstancePoker {
    int bitPressed = -1;

    @Override
    public void mousePressed(InstanceState state, MouseEvent e) {
      bitPressed = getBit(state, e);
    }
   
    @Override
    public void mouseReleased(InstanceState state, MouseEvent e) {
      int bit = getBit(state, e);
      if (bit == bitPressed && bit >= 0) {
        handleBitPress(state, bit, e);
      }
      bitPressed = -1;
    }
   
    private void handleBitPress(InstanceState state, int bit, MouseEvent e) {
      PinAttributes attrs = (PinAttributes) state.getAttributeSet();
      if (!attrs.isInput()) return;
 
      java.awt.Component sourceComp = e.getComponent();
      if (sourceComp instanceof Canvas && !state.isCircuitRoot()) {
        Canvas canvas = (Canvas) e.getComponent();
        CircuitState circState = canvas.getCircuitState();
        java.awt.Component frame = SwingUtilities.getRoot(canvas);
        int choice = JOptionPane.showConfirmDialog(frame,
            Strings.get("pinFrozenQuestion"),
            Strings.get("pinFrozenTitle"),
            JOptionPane.OK_CANCEL_OPTION,
            JOptionPane.WARNING_MESSAGE);
        if (choice == JOptionPane.OK_OPTION) {
          circState = circState.cloneState();
          canvas.getProject().setCircuitState(circState);
          state = circState.getInstanceState(state.getInstance());
        } else {
          return;
        }
      }
 
      PinState pinState = getState(state);
      Value val = pinState.sending.get(bit);
      if (val == Value.FALSE) {
        val = Value.TRUE;
      } else if (val == Value.TRUE) {
        val = attrs.threeState ? Value.UNKNOWN : Value.FALSE;
      } else {
        val = Value.FALSE;
      }
      pinState.sending = pinState.sending.set(bit, val);
      state.fireInvalidated();
    }
 
    private int getBit(InstanceState state, MouseEvent e) {
      BitWidth width = state.getAttributeValue(StdAttr.WIDTH);
      if (width.getWidth() == 1) {
        return 0;
      } else {
        Bounds bds = state.getInstance().getBounds(); // intentionally with no graphics object - we don't want label included
        int i = (bds.getX() + bds.getWidth() - e.getX()) / 10;
        int j = (bds.getY() + bds.getHeight() - e.getY()) / 20;
        int bit = 8 * j + i;
        if (bit < 0 || bit >= width.getWidth()) {
          return -1;
        } else {
          return bit;
        }
      }
    }
  }
   
  public static class PinLogger extends InstanceLogger {
    @Override
    public String getLogName(InstanceState state, Object option) {
      PinAttributes attrs = (PinAttributes) state.getAttributeSet();
      String ret = attrs.label;
      if (ret == null || ret.equals("")) {
        String type = attrs.type == EndData.INPUT_ONLY
          ? Strings.get("pinInputName") : Strings.get("pinOutputName");
        return type + state.getInstance().getLocation();
      } else {
        return ret;
      }
    }
   
    @Override
    public Value getLogValue(InstanceState state, Object option) {
      PinState s = getState(state);
      return s.sending;
    }
  }
}
TOP

Related Classes of com.cburch.logisim.std.wiring.Pin$PinLogger

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.