Package com.cburch.logisim.std.wiring

Source Code of com.cburch.logisim.std.wiring.Clock$ClockPoker

/* 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 java.awt.event.MouseEvent;

import javax.swing.Icon;

import com.cburch.logisim.circuit.CircuitState;
import com.cburch.logisim.circuit.RadixOption;
import com.cburch.logisim.comp.Component;
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.InstancePoker;
import com.cburch.logisim.instance.InstanceState;
import com.cburch.logisim.instance.Port;
import com.cburch.logisim.instance.StdAttr;
import com.cburch.logisim.util.GraphicsUtil;
import com.cburch.logisim.util.Icons;

public class Clock extends InstanceFactory {
  public static final Attribute<Integer> ATTR_HIGH
    = new DurationAttribute("highDuration", Strings.getter("clockHighAttr"),
        1, Integer.MAX_VALUE);

  public static final Attribute<Integer> ATTR_LOW
    = new DurationAttribute("lowDuration", Strings.getter("clockLowAttr"),
        1, Integer.MAX_VALUE);
 
  public static final Clock FACTORY = new Clock();

  private static final Icon toolIcon = Icons.getIcon("clock.gif");
 
  private static class ClockState implements InstanceData, Cloneable {
    Value sending = Value.FALSE;
    int clicks = 0;
   
    @Override
    public ClockState clone() {
      try { return (ClockState) super.clone(); }
      catch (CloneNotSupportedException e) { return null; }
    }
  }

  public static class ClockLogger extends InstanceLogger {
    @Override
    public String getLogName(InstanceState state, Object option) {
      return state.getAttributeValue(StdAttr.LABEL);
    }

    @Override
    public Value getLogValue(InstanceState state, Object option) {
      ClockState s = getState(state);
      return s.sending;
    }
  }
 
  public static class ClockPoker extends InstancePoker {
    boolean isPressed = true;

    @Override
    public void mousePressed(InstanceState state, MouseEvent e) {
      isPressed = isInside(state, e);
    }
   
    @Override
    public void mouseReleased(InstanceState state, MouseEvent e) {
      if (isPressed && isInside(state, e)) {
        ClockState myState = (ClockState) state.getData();
        myState.sending = myState.sending.not();
        myState.clicks++;
        state.fireInvalidated();
      }
      isPressed = false;
    }

    private boolean isInside(InstanceState state, MouseEvent e) {
      Bounds bds = state.getInstance().getBounds();
      return bds.contains(e.getX(), e.getY());
    }
  }

  public Clock() {
    super("Clock", Strings.getter("clockComponent"));
    setAttributes(new Attribute[] {
          StdAttr.FACING, ATTR_HIGH, ATTR_LOW,
          StdAttr.LABEL, Pin.ATTR_LABEL_LOC, StdAttr.LABEL_FONT
        }, new Object[] {
          Direction.EAST, Integer.valueOf(1), Integer.valueOf(1),
          "", Direction.WEST, StdAttr.DEFAULT_LABEL_FONT
        });
    setFacingAttribute(StdAttr.FACING);
    setInstanceLogger(ClockLogger.class);
    setInstancePoker(ClockPoker.class);
  }

  @Override
  public Bounds getOffsetBounds(AttributeSet attrs) {
    return Probe.getOffsetBounds(
        attrs.getValue(StdAttr.FACING),
        BitWidth.ONE, RadixOption.RADIX_2);
  }

  //
  // graphics methods
  //
  @Override
  public void paintIcon(InstancePainter painter) {
    Graphics g = painter.getGraphics();
    if (toolIcon != null) {
      toolIcon.paintIcon(painter.getDestination(), g, 2, 2);
    } else {
      g.drawRect(4, 4, 13, 13);
      g.setColor(Value.FALSE.getColor());
      g.drawPolyline(new int[] { 6, 6, 10, 10, 14, 14 },
          new int[] { 10, 6, 6, 14, 14, 10 }, 6);
    }

    Direction dir = painter.getAttributeValue(StdAttr.FACING);
    int pinx = 15; int piny = 8;
    if (dir == Direction.EAST) { // keep defaults
    } else if (dir == Direction.WEST) { pinx = 3;
    } else if (dir == Direction.NORTH) { pinx = 8; piny = 3;
    } else if (dir == Direction.SOUTH) { pinx = 8; piny = 15;
    }
    g.setColor(Value.TRUE.getColor());
    g.fillOval(pinx, piny, 3, 3);
  }

  @Override
  public void paintInstance(InstancePainter painter) {
    java.awt.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);
    g.drawRect(x, y, bds.getWidth(), bds.getHeight());

    painter.drawLabel();

    boolean drawUp;
    if (painter.getShowState()) {
      ClockState state = getState(painter);
      g.setColor(state.sending.getColor());
      drawUp = state.sending == Value.TRUE;
    } else {
      g.setColor(Color.BLACK);
      drawUp = true;
    }
    x += 10;
    y += 10;
    int[] xs = { x - 6, x - 6, x, x, x + 6, x + 6 };
    int[] ys;
    if (drawUp) {
      ys = new int[] { y, y - 4, y - 4, y + 4, y + 4, y };
    } else {
      ys = new int[] { y, y + 4, y + 4, y - 4, y - 4, y };
    }
    g.drawPolyline(xs, ys, xs.length);

    painter.drawPorts();
  }

  //
  // methods for instances
  //
  @Override
  protected void configureNewInstance(Instance instance) {
    instance.addAttributeListener();
    instance.setPorts(new Port[] { new Port(0, 0, Port.OUTPUT, BitWidth.ONE) });
    configureLabel(instance);
  }
 
  @Override
  protected void instanceAttributeChanged(Instance instance, Attribute<?> attr) {
    if (attr == Pin.ATTR_LABEL_LOC) {
      configureLabel(instance);
    } else if (attr == StdAttr.FACING) {
      instance.recomputeBounds();
      configureLabel(instance);
    }
  }

  @Override
  public void propagate(InstanceState state) {
    Value val = state.getPort(0);
    ClockState q = getState(state);
    if (!val.equals(q.sending)) { // ignore if no change
      state.setPort(0, q.sending, 1);
    }
  }

  //
  // package methods
  //
  public static boolean tick(CircuitState circState, int ticks, Component comp) {
    AttributeSet attrs = comp.getAttributeSet();
    int durationHigh = attrs.getValue(ATTR_HIGH).intValue();
    int durationLow = attrs.getValue(ATTR_LOW).intValue();
    ClockState state = (ClockState) circState.getData(comp);
    if (state == null) {
      state = new ClockState();
      circState.setData(comp, state);
    }
    boolean curValue = ticks % (durationHigh + durationLow) < durationLow;
    if (state.clicks % 2 == 1) curValue = !curValue;
    Value desired = (curValue ? Value.FALSE : Value.TRUE);
    if (!state.sending.equals(desired)) {
      state.sending = desired;
      Instance.getInstanceFor(comp).fireInvalidated();
      return true;
    } else {
      return false;
    }
  }

  //
  // private methods
  //
  private void configureLabel(Instance instance) {
    Direction facing = instance.getAttributeValue(StdAttr.FACING);
    Direction labelLoc = instance.getAttributeValue(Pin.ATTR_LABEL_LOC);
    Probe.configureLabel(instance, labelLoc, facing);
  }

  private static ClockState getState(InstanceState state) {
    ClockState ret = (ClockState) state.getData();
    if (ret == null) {
      ret = new ClockState();
      state.setData(ret);
    }
    return ret;
  }
}
TOP

Related Classes of com.cburch.logisim.std.wiring.Clock$ClockPoker

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.