Package com.cburch.logisim.std.wiring

Source Code of com.cburch.logisim.std.wiring.Probe$StateData

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

import com.cburch.logisim.circuit.RadixOption;
import com.cburch.logisim.comp.TextField;
import com.cburch.logisim.data.Attribute;
import com.cburch.logisim.data.AttributeSet;
import com.cburch.logisim.data.BitWidth;
import com.cburch.logisim.data.Bounds;
import com.cburch.logisim.data.Direction;
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.InstanceLogger;
import com.cburch.logisim.instance.InstancePainter;
import com.cburch.logisim.instance.InstanceState;
import com.cburch.logisim.instance.Port;
import com.cburch.logisim.instance.StdAttr;
import com.cburch.logisim.util.GraphicsUtil;

public class Probe extends InstanceFactory {
  public static final Probe FACTORY = new Probe();

  private static class StateData implements InstanceData, Cloneable {
    Value curValue = Value.NIL;
   
    @Override
    public Object clone() {
      try {
        return super.clone();
      } catch (CloneNotSupportedException e) {
        return null;
      }
    }
  }

  public static class ProbeLogger extends InstanceLogger {
    public ProbeLogger() { }
   
    @Override
    public String getLogName(InstanceState state, Object option) {
      String ret = state.getAttributeValue(StdAttr.LABEL);
      return ret != null && !ret.equals("") ? ret : null;
    }

    @Override
    public Value getLogValue(InstanceState state, Object option) {
      return getValue(state);
    }
  }

  public Probe() {
    super("Probe", Strings.getter("probeComponent"));
    setIconName("probe.gif");
    setFacingAttribute(StdAttr.FACING);
    setInstanceLogger(ProbeLogger.class);
  }

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

  @Override
  public Bounds getOffsetBounds(AttributeSet attrsBase) {
    ProbeAttributes attrs = (ProbeAttributes) attrsBase;
    return getOffsetBounds(attrs.facing, attrs.width, attrs.radix);
  }
 
  //
  // graphics methods
  //
  @Override
  public void paintGhost(InstancePainter painter) {
    Graphics g = painter.getGraphics();
    Bounds bds = painter.getOffsetBounds();
    g.drawOval(bds.getX() + 1, bds.getY() + 1,
      bds.getWidth() - 1, bds.getHeight() - 1);
  }

  @Override
  public void paintInstance(InstancePainter painter) {
    Value value = getValue(painter);
   
    Graphics g = painter.getGraphics();
    Bounds bds = painter.getBounds(); // intentionally with no graphics object - we don't want label included
    int x = bds.getX();
    int y = bds.getY();
    g.setColor(Color.WHITE);
    g.fillRect(x + 5, y + 5, bds.getWidth() - 10, bds.getHeight() - 10);
    g.setColor(Color.GRAY);
    if (value.getWidth() <= 1) {
      g.drawOval(x + 1, y + 1,
        bds.getWidth() - 2, bds.getHeight() - 2);
    } else {
      g.drawRoundRect(x + 1, y + 1,
        bds.getWidth() - 2, bds.getHeight() - 2, 6, 6);
    }

    g.setColor(Color.BLACK);
    painter.drawLabel();

    if (!painter.getShowState()) {
      if (value.getWidth() > 0) {
        GraphicsUtil.drawCenteredText(g, "x" + value.getWidth(),
          bds.getX() + bds.getWidth() / 2, bds.getY() + bds.getHeight() / 2);
      }
    } else {
      paintValue(painter, value);
    }

    painter.drawPorts();
  }
 
  static void paintValue(InstancePainter painter, Value value) {
    Graphics g = painter.getGraphics();
    Bounds bds = painter.getBounds(); // intentionally with no graphics object - we don't want label included

    RadixOption radix = painter.getAttributeValue(RadixOption.ATTRIBUTE);
    if (radix == null || radix == RadixOption.RADIX_2) {
      int x = bds.getX();
      int y = bds.getY();
      int wid = value.getWidth();
      if (wid == 0) {
        x += bds.getWidth() / 2;
        y += bds.getHeight() / 2;
        GraphicsUtil.switchToWidth(g, 2);
        g.drawLine(x - 4, y, x + 4, y);
        return;
      }
      int x0 = bds.getX() + bds.getWidth() - 5;
      int compWidth = wid * 10;
      if (compWidth < bds.getWidth() - 3) {
        x0 = bds.getX() + (bds.getWidth() + compWidth) / 2 - 5;
      }
      int cx = x0;
      int cy = bds.getY() + bds.getHeight() - 12;
      int cur = 0;
      for (int k = 0; k < wid; k++) {
        GraphicsUtil.drawCenteredText(g,
          value.get(k).toDisplayString(), cx, cy);
        ++cur;
        if (cur == 8) {
          cur = 0;
          cx = x0;
          cy -= 20;
        } else {
          cx -= 10;
        }
      }
    } else {
      String text = radix.toString(value);
      GraphicsUtil.drawCenteredText(g, text,
          bds.getX() + bds.getWidth() / 2,
          bds.getY() + bds.getHeight() / 2);
    }
  }
 
  //
  // methods for instances
  //
  @Override
  protected void configureNewInstance(Instance instance) {
    instance.setPorts(new Port[] { new Port(0, 0, Port.INPUT, BitWidth.UNKNOWN) });
    instance.addAttributeListener();
    configureLabel(instance);
  }

  @Override
  protected void instanceAttributeChanged(Instance instance, Attribute<?> attr) {
    if (attr == Pin.ATTR_LABEL_LOC) {
      configureLabel(instance);
    } else if (attr == StdAttr.FACING || attr == RadixOption.ATTRIBUTE) {
      instance.recomputeBounds();
      configureLabel(instance);
    }
  }

  @Override
  public void propagate(InstanceState state) {
    StateData oldData = (StateData) state.getData();
    Value oldValue = oldData == null ? Value.NIL : oldData.curValue;
    Value newValue = state.getPort(0);
    boolean same = oldValue == null ? newValue == null : oldValue.equals(newValue);
    if (!same) {
      if (oldData == null) {
        oldData = new StateData();
        oldData.curValue = newValue;
        state.setData(oldData);
      } else {
        oldData.curValue = newValue;
      }
      int oldWidth = oldValue == null ? 1 : oldValue.getBitWidth().getWidth();
      int newWidth = newValue.getBitWidth().getWidth();
      if (oldWidth != newWidth) {
        ProbeAttributes attrs = (ProbeAttributes) state.getAttributeSet();
        attrs.width = newValue.getBitWidth();
        state.getInstance().recomputeBounds();
        configureLabel(state.getInstance());
      }
      state.fireInvalidated();
    }
  }

  private static Value getValue(InstanceState state) {
    StateData data = (StateData) state.getData();
    return data == null ? Value.NIL : data.curValue;
  }
 
  void configureLabel(Instance instance) {
    ProbeAttributes attrs = (ProbeAttributes) instance.getAttributeSet();
    Probe.configureLabel(instance, attrs.labelloc, attrs.facing);
  }

  //
  // static methods
  //
  static Bounds getOffsetBounds(Direction dir, BitWidth width,
      RadixOption radix) {
    Bounds ret = null;
    int len = radix == null || radix == RadixOption.RADIX_2 ? width.getWidth() : radix.getMaxLength(width);
    if (dir == Direction.EAST) {
      switch (len) {
      case 0:
      case 1: ret = Bounds.create(-20, -10, 20, 20); break;
      case 2: ret = Bounds.create(-20, -10, 20, 20); break;
      case 3: ret = Bounds.create(-30, -10, 30, 20); break;
      case 4: ret = Bounds.create(-40, -10, 40, 20); break;
      case 5: ret = Bounds.create(-50, -10, 50, 20); break;
      case 6: ret = Bounds.create(-60, -10, 60, 20); break;
      case 7: ret = Bounds.create(-70, -10, 70, 20); break;
      case 8: ret = Bounds.create(-80, -10, 80, 20); break;
      case  9: case 10: case 11: case 12:
      case 13: case 14: case 15: case 16:
        ret = Bounds.create(-80, -20, 80, 40); break;
      case 17: case 18: case 19: case 20:
      case 21: case 22: case 23: case 24:
        ret = Bounds.create(-80, -30, 80, 60); break;
      case 25: case 26: case 27: case 28:
      case 29: case 30: case 31: case 32:
        ret = Bounds.create(-80, -40, 80, 80); break;
      }
    } else if (dir == Direction.WEST) {
      switch (len) {
      case 0:
      case 1: ret = Bounds.create(0, -10, 20, 20); break;
      case 2: ret = Bounds.create(0, -10, 20, 20); break;
      case 3: ret = Bounds.create(0, -10, 30, 20); break;
      case 4: ret = Bounds.create(0, -10, 40, 20); break;
      case 5: ret = Bounds.create(0, -10, 50, 20); break;
      case 6: ret = Bounds.create(0, -10, 60, 20); break;
      case 7: ret = Bounds.create(0, -10, 70, 20); break;
      case 8: ret = Bounds.create(0, -10, 80, 20); break;
      case  9: case 10: case 11: case 12:
      case 13: case 14: case 15: case 16:
        ret = Bounds.create(0, -20, 80, 40); break;
      case 17: case 18: case 19: case 20:
      case 21: case 22: case 23: case 24:
        ret = Bounds.create(0, -30, 80, 60); break;
      case 25: case 26: case 27: case 28:
      case 29: case 30: case 31: case 32:
        ret = Bounds.create(0, -40, 80, 80); break;
      }
    } else if (dir == Direction.SOUTH) {
      switch (len) {
      case 0:
      case 1: ret = Bounds.create(-10, -20, 20, 20); break;
      case 2: ret = Bounds.create(-10, -20, 20, 20); break;
      case 3: ret = Bounds.create(-15, -20, 30, 20); break;
      case 4: ret = Bounds.create(-20, -20, 40, 20); break;
      case 5: ret = Bounds.create(-25, -20, 50, 20); break;
      case 6: ret = Bounds.create(-30, -20, 60, 20); break;
      case 7: ret = Bounds.create(-35, -20, 70, 20); break;
      case 8: ret = Bounds.create(-40, -20, 80, 20); break;
      case  9: case 10: case 11: case 12:
      case 13: case 14: case 15: case 16:
        ret = Bounds.create(-40, -40, 80, 40); break;
      case 17: case 18: case 19: case 20:
      case 21: case 22: case 23: case 24:
        ret = Bounds.create(-40, -60, 80, 60); break;
      case 25: case 26: case 27: case 28:
      case 29: case 30: case 31: case 32:
        ret = Bounds.create(-40, -80, 80, 80); break;
      }
    } else if (dir == Direction.NORTH) {
      switch (len) {
      case 0:
      case 1: ret = Bounds.create(-10, 0, 20, 20); break;
      case 2: ret = Bounds.create(-10, 0, 20, 20); break;
      case 3: ret = Bounds.create(-15, 0, 30, 20); break;
      case 4: ret = Bounds.create(-20, 0, 40, 20); break;
      case 5: ret = Bounds.create(-25, 0, 50, 20); break;
      case 6: ret = Bounds.create(-30, 0, 60, 20); break;
      case 7: ret = Bounds.create(-35, 0, 70, 20); break;
      case 8: ret = Bounds.create(-40, 0, 80, 20); break;
      case  9: case 10: case 11: case 12:
      case 13: case 14: case 15: case 16:
        ret = Bounds.create(-40, 0, 80, 40); break;
      case 17: case 18: case 19: case 20:
      case 21: case 22: case 23: case 24:
        ret = Bounds.create(-40, 0, 80, 60); break;
      case 25: case 26: case 27: case 28:
      case 29: case 30: case 31: case 32:
        ret = Bounds.create(-40, 0, 80, 80); break;
      }
    }
    if (ret == null) {
      ret = Bounds.create(0, -10, 20, 20); // should never happen
    }
    return ret;
  }

  static void configureLabel(Instance instance, Direction labelLoc,
      Direction facing) {
    Bounds bds = instance.getBounds();
    int x;
    int y;
    int halign;
    int valign;
    if (labelLoc == Direction.NORTH) {
      halign = TextField.H_CENTER;
      valign = TextField.V_BOTTOM;
      x = bds.getX() + bds.getWidth() / 2;
      y = bds.getY() - 2;
      if (facing == labelLoc) {
        halign = TextField.H_LEFT;
        x += 2;
      }
    } else if (labelLoc == Direction.SOUTH) {
      halign = TextField.H_CENTER;
      valign = TextField.V_TOP;
      x = bds.getX() + bds.getWidth() / 2;
      y = bds.getY() + bds.getHeight() + 2;
      if (facing == labelLoc) {
        halign = TextField.H_LEFT;
        x += 2;
      }
    } else if (labelLoc == Direction.EAST) {
      halign = TextField.H_LEFT;
      valign = TextField.V_CENTER;
      x = bds.getX() + bds.getWidth() + 2;
      y = bds.getY() + bds.getHeight() / 2;
      if (facing == labelLoc) {
        valign = TextField.V_BOTTOM;
        y -= 2;
      }
    } else { // WEST
      halign = TextField.H_RIGHT;
      valign = TextField.V_CENTER;
      x = bds.getX() - 2;
      y = bds.getY() + bds.getHeight() / 2;
      if (facing == labelLoc) {
        valign = TextField.V_BOTTOM;
        y -= 2;
      }
    }

    instance.setTextField(StdAttr.LABEL, StdAttr.LABEL_FONT,
        x, y, halign, valign);
  }
}
TOP

Related Classes of com.cburch.logisim.std.wiring.Probe$StateData

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.