Package com.cburch.logisim.circuit

Source Code of com.cburch.logisim.circuit.SplitterAttributes

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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.cburch.logisim.circuit.Strings;
import com.cburch.logisim.data.AbstractAttributeSet;
import com.cburch.logisim.data.Attribute;
import com.cburch.logisim.data.AttributeOption;
import com.cburch.logisim.data.Attributes;
import com.cburch.logisim.data.BitWidth;
import com.cburch.logisim.data.Direction;
import com.cburch.logisim.instance.StdAttr;

class SplitterAttributes extends AbstractAttributeSet {
  public static final AttributeOption APPEAR_LEGACY
    = new AttributeOption("legacy", Strings.getter("splitterAppearanceLegacy"));
  public static final AttributeOption APPEAR_LEFT
    = new AttributeOption("left", Strings.getter("splitterAppearanceLeft"));
  public static final AttributeOption APPEAR_RIGHT
    = new AttributeOption("right", Strings.getter("splitterAppearanceRight"));
  public static final AttributeOption APPEAR_CENTER
    = new AttributeOption("center", Strings.getter("splitterAppearanceCenter"));
 
  public static final Attribute<AttributeOption> ATTR_APPEARANCE
    = Attributes.forOption("appear", Strings.getter("splitterAppearanceAttr"),
        new AttributeOption[] { APPEAR_LEFT, APPEAR_RIGHT, APPEAR_CENTER,
          APPEAR_LEGACY});
 
  public static final Attribute<BitWidth> ATTR_WIDTH
    = Attributes.forBitWidth("incoming", Strings.getter("splitterBitWidthAttr"));
  public static final Attribute<Integer> ATTR_FANOUT
    = Attributes.forIntegerRange("fanout", Strings.getter("splitterFanOutAttr"), 1, 32);

  private static final List<Attribute<?>> INIT_ATTRIBUTES
    = Arrays.asList(new Attribute<?>[] {
      StdAttr.FACING, ATTR_FANOUT, ATTR_WIDTH, ATTR_APPEARANCE,
    });

  private static final String unchosen_val = "none";

  private static class BitOutOption {
    int value;
    boolean isVertical;
    boolean isLast;

    BitOutOption(int value, boolean isVertical, boolean isLast) {
      this.value = value;
      this.isVertical = isVertical;
      this.isLast = isLast;
    }

    @Override
    public String toString() {
      if (value < 0) {
        return Strings.get("splitterBitNone");
      } else {
        String ret = "" + value;
        Direction noteDir;
        if (value == 0) {
          noteDir = isVertical ? Direction.NORTH : Direction.EAST;
        } else if (isLast) {
          noteDir = isVertical ? Direction.SOUTH : Direction.WEST;
        } else {
          noteDir = null;
        }
        if (noteDir != null) {
          ret += " (" + noteDir.toVerticalDisplayString() + ")";
        }
        return ret;
      }
    }
  }

  static class BitOutAttribute extends Attribute<Integer> {
    int which;
    BitOutOption[] options;

    private BitOutAttribute(int which, BitOutOption[] options) {
      super("bit" + which, Strings.getter("splitterBitAttr", "" + which));
      this.which = which;
      this.options = options;
    }
   
    private BitOutAttribute createCopy() {
      return new BitOutAttribute(which, options);
    }
   
    public Object getDefault() {
      return Integer.valueOf(which + 1);
    }

    @Override
    public Integer parse(String value) {
      if (value.equals(unchosen_val)) {
        return Integer.valueOf(0);
      } else {
        return Integer.valueOf(1 + Integer.parseInt(value));
      }
    }

    @Override
    public String toDisplayString(Integer value) {
      int index = value.intValue();
      return options[index].toString();
    }

    @Override
    public String toStandardString(Integer value) {
      int index = value.intValue();
      if (index == 0) {
        return unchosen_val;
      } else {
        return "" + (index - 1);
      }
    }

    @Override
    public java.awt.Component getCellEditor(Integer value) {
      int index = value.intValue();
      javax.swing.JComboBox combo = new javax.swing.JComboBox(options);
      combo.setSelectedIndex(index);
      return combo;
    }
  }

  private ArrayList<Attribute<?>> attrs = new ArrayList<Attribute<?>>(INIT_ATTRIBUTES);
  private SplitterParameters parameters;
  AttributeOption appear = APPEAR_LEFT;
  Direction facing = Direction.EAST;
  byte fanout = 2;                 // number of ends this splits into
  byte[] bit_end = new byte[2];    // how each bit maps to an end (0 if nowhere);
                   //   other values will be between 1 and fanout
  BitOutOption[] options = null;

  SplitterAttributes() {
    configureOptions();
    configureDefaults();
    parameters = new SplitterParameters(this);
  }
 
  Attribute<?> getBitOutAttribute(int index) {
    return attrs.get(INIT_ATTRIBUTES.size() + index);
  }

  @Override
  protected void copyInto(AbstractAttributeSet destObj) {
    SplitterAttributes dest = (SplitterAttributes) destObj;
    dest.parameters = this.parameters;
    dest.attrs = new ArrayList<Attribute<?>>(this.attrs.size());
    dest.attrs.addAll(INIT_ATTRIBUTES);
    for (int i = INIT_ATTRIBUTES.size(), n = this.attrs.size(); i < n; i++) {
      BitOutAttribute attr = (BitOutAttribute) this.attrs.get(i);
      dest.attrs.add(attr.createCopy());
    }

    dest.facing = this.facing;
    dest.fanout = this.fanout;
    dest.appear = this.appear;
    dest.bit_end = this.bit_end.clone();
    dest.options = this.options;
  }
 
  public SplitterParameters getParameters() {
    SplitterParameters ret = parameters;
    if (ret == null) {
      ret = new SplitterParameters(this);
      parameters = ret;
    }
    return ret;
  }

  @Override
  public List<Attribute<?>> getAttributes() {
    return attrs;
  }

  @Override
  @SuppressWarnings("unchecked")
  public <V> V getValue(Attribute<V> attr) {
    if (attr == StdAttr.FACING) {
      return (V) facing;
    } else if (attr == ATTR_FANOUT) {
      return (V) Integer.valueOf(fanout);
    } else if (attr == ATTR_WIDTH) {
      return (V) BitWidth.create(bit_end.length);
    } else if (attr == ATTR_APPEARANCE) {
      return (V) appear;
    } else if (attr instanceof BitOutAttribute) {
      BitOutAttribute bitOut = (BitOutAttribute) attr;
      return (V) Integer.valueOf(bit_end[bitOut.which]);
    } else {
      return null;
    }
  }

  @Override
  public <V> void setValue(Attribute<V> attr, V value) {
    if (attr == StdAttr.FACING) {
      facing = (Direction) value;
      configureOptions();
      parameters = null;
    } else if (attr == ATTR_FANOUT) {
      int newValue = ((Integer) value).intValue();
      byte[] bits = bit_end;
      for (int i = 0; i < bits.length; i++) {
        if (bits[i] >= newValue) bits[i] = (byte) (newValue - 1);
      }
      fanout = (byte) newValue;
      configureOptions();
      configureDefaults();
      parameters = null;
    } else if (attr == ATTR_WIDTH) {
      BitWidth width = (BitWidth) value;
      bit_end = new byte[width.getWidth()];
      configureOptions();
      configureDefaults();
    } else if (attr == ATTR_APPEARANCE) {
      appear = (AttributeOption) value;
      parameters = null;
    } else if (attr instanceof BitOutAttribute) {
      BitOutAttribute bitOutAttr = (BitOutAttribute) attr;
      int val;
      if (value instanceof Integer) {
        val = ((Integer) value).intValue();
      } else {
        val= ((BitOutOption) value).value + 1;
      }
      if (val >= 0 && val <= fanout) {
        bit_end[bitOutAttr.which] = (byte) val;
      }
    } else {
      throw new IllegalArgumentException("unknown attribute " + attr);
    }
    fireAttributeValueChanged(attr, value);
  }

  private void configureOptions() {
    // compute the set of options for BitOutAttributes
    options = new BitOutOption[fanout + 1];
    boolean isVertical = facing == Direction.EAST || facing == Direction.WEST;
    for (int i = -1; i < fanout; i++) {
      options[i + 1] = new BitOutOption(i, isVertical, i == fanout - 1);
    }

    // go ahead and set the options for the existing attributes
    int offs = INIT_ATTRIBUTES.size();
    int curNum = attrs.size() - offs;
    for (int i = 0; i < curNum; i++) {
      BitOutAttribute attr = (BitOutAttribute) attrs.get(offs + i);
      attr.options = options;
    }
  }
 
  private void configureDefaults() {
    int offs = INIT_ATTRIBUTES.size();
    int curNum = attrs.size() - offs;

    // compute default values
    byte[] dflt = computeDistribution(fanout, bit_end.length, 1);

    boolean changed = curNum != bit_end.length;
   
    // remove excess attributes
    while (curNum > bit_end.length) {
      curNum--;
      attrs.remove(offs + curNum);
    }

    // set existing attributes
    for (int i = 0; i < curNum; i++) {
      if (bit_end[i] != dflt[i]) {
        BitOutAttribute attr = (BitOutAttribute) attrs.get(offs + i);
        bit_end[i] = dflt[i];
        fireAttributeValueChanged(attr, Integer.valueOf(bit_end[i]));
      }
    }

    // add new attributes
    for (int i = curNum; i < bit_end.length; i++) {
      BitOutAttribute attr = new BitOutAttribute(i, options);
      bit_end[i] = dflt[i];
      attrs.add(attr);
    }
   
    if (changed) fireAttributeListChanged();
  }
 
  static byte[] computeDistribution(int fanout, int bits, int order) {
    byte[] ret = new byte[bits];
    if (order >= 0) {
      if (fanout >= bits) {
        for (int i = 0; i < bits; i++) ret[i] = (byte) (i + 1);
      } else {
        int threads_per_end = bits / fanout;
        int ends_with_extra = bits % fanout;
        int cur_end = -1; // immediately increments
        int left_in_end = 0;
        for (int i = 0; i < bits; i++) {
          if (left_in_end == 0) {
            ++cur_end;
            left_in_end = threads_per_end;
            if (ends_with_extra > 0) {
              ++left_in_end;
              --ends_with_extra;
            }
          }
          ret[i] = (byte) (1 + cur_end);
          --left_in_end;
        }
      }
    } else {
      if (fanout >= bits) {
        for (int i = 0; i < bits; i++) ret[i] = (byte) (fanout - i);
      } else {
        int threads_per_end = bits / fanout;
        int ends_with_extra = bits % fanout;
        int cur_end = -1;
        int left_in_end = 0;
        for (int i = bits - 1; i >= 0; i--) {
          if (left_in_end == 0) {
            ++cur_end;
            left_in_end = threads_per_end;
            if (ends_with_extra > 0) {
              ++left_in_end;
              --ends_with_extra;
            }
          }
          ret[i] = (byte) (1 + cur_end);
          --left_in_end;
        }
      }
    }
    return ret;
  }
}
TOP

Related Classes of com.cburch.logisim.circuit.SplitterAttributes

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.