AbstractGate.java :  » Science » logisim-2.3.4 » com » cburch » logisim » std » gates » Java Open Source

Java Open Source » Science » logisim 2.3.4 
logisim 2.3.4 » com » cburch » logisim » std » gates » AbstractGate.java
/* Copyright (c) 2006, 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.gates;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.util.Map;

import com.cburch.logisim.analyze.model.Expression;
import com.cburch.logisim.circuit.CircuitState;
import com.cburch.logisim.circuit.ExpressionComputer;
import com.cburch.logisim.comp.ComponentEvent;
import com.cburch.logisim.comp.ComponentFactory;
import com.cburch.logisim.comp.ComponentDrawContext;
import com.cburch.logisim.comp.EndData;
import com.cburch.logisim.comp.ManagedComponent;
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.Location;
import com.cburch.logisim.data.Value;
import com.cburch.logisim.file.Options;
import com.cburch.logisim.instance.StdAttr;
import com.cburch.logisim.proj.LogisimPreferences;
import com.cburch.logisim.tools.WireRepair;
import com.cburch.logisim.tools.WireRepairData;

class AbstractGate extends ManagedComponent
        implements WireRepair, ExpressionComputer {
    private AbstractGateFactory src;
    
    public AbstractGate(Location loc, AttributeSet attrs, AbstractGateFactory src) {
        super(loc, attrs, 4);
        this.src = src;
        
        if(attrs instanceof GateAttributes) {
            ((GateAttributes) attrs).gate = this;
        }
        setEnds();
    }
    
    public ComponentFactory getFactory() {
        return src;
    }

    void setEnds() {
        AttributeSet attrs = getAttributeSet();
        Direction facing = (Direction) attrs.getValue(StdAttr.FACING);
        int inputCount = ((Integer) attrs.getValue(GateAttributes.ATTR_INPUTS)).intValue();
        BitWidth w = (BitWidth) attrs.getValue(StdAttr.WIDTH);

        Bounds bounds = getBounds();
        Location pt = getLocation();
        EndData[] ends = new EndData[inputCount + 1];
        ends[0] = new EndData(pt, w, EndData.OUTPUT_ONLY);
        int wid;
        int ht;
        if(facing == Direction.NORTH || facing == Direction.SOUTH) {
            wid = bounds.getHeight();
            ht = bounds.getWidth();
        } else {
            wid = bounds.getWidth();
            ht = bounds.getHeight();
        }
        int dx = wid;
        int dy = -(ht / 2 - 5);
        int ddy = (ht - 10) / (inputCount - 1);
        if(facing == Direction.NORTH) {
            for(int i = 1; i <= inputCount; i++) {
                ends[i] = new EndData(pt.translate(dy,  dx), w, EndData.INPUT_ONLY);
                dy += ddy;
            }
        } else if(facing == Direction.SOUTH) {
            for(int i = 1; i <= inputCount; i++) {
                ends[i] = new EndData(pt.translate(dy, -dx), w, EndData.INPUT_ONLY);
                dy += ddy;
            }
        } else if(facing == Direction.WEST) {
            for(int i = 1; i <= inputCount; i++) {
                ends[i] = new EndData(pt.translate( dx, dy), w, EndData.INPUT_ONLY);
                dy += ddy;
            }
        } else {
            for(int i = 1; i <= inputCount; i++) {
                ends[i] = new EndData(pt.translate(-dx, dy), w, EndData.INPUT_ONLY);
                dy += ddy;
            }
        }
        setEnds(ends);
    }

    public void propagate(CircuitState state) {
        AttributeSet attrs = getAttributeSet();
        int inputCount = ((Integer) attrs.getValue(GateAttributes.ATTR_INPUTS)).intValue();
        AttributeSet opts = state.getProject().getOptions().getAttributeSet();
        boolean errorIfUndefined = opts.getValue(Options.ATTR_GATE_UNDEFINED)
                                    .equals(Options.GATE_UNDEFINED_ERROR);

        Value[] inputs = new Value[inputCount];
        int num_inputs = 0;
        int unknownMask = 0;
        for(int i = 1; i <= inputCount; i++) {
            Value v = state.getValue(getEndLocation(i));
            if(v == Value.NIL) {
                unknownMask = -1;
            } else {
                if(errorIfUndefined && !v.isFullyDefined()) {
                    for(int j = 0, w = v.getWidth(); j < w; j++) {
                        Value vj = v.get(j);
                        if(vj == Value.ERROR || vj == Value.UNKNOWN) {
                            unknownMask |= 1 << j;
                        }
                    }
                }
                inputs[num_inputs] = v;
                num_inputs++;
            }
        }
        Value out = null;
        if(errorIfUndefined && unknownMask != 0) {
            BitWidth width = (BitWidth) attrs.getValue(StdAttr.WIDTH);
            int mask = width.getMask();
            if((unknownMask & mask) == mask) {
                out = Value.createError(width);
                unknownMask = 0;
            } else {
                out = src.computeOutput(inputs, num_inputs, attrs);
                Value[] outv = out.getAll();
                for(int j = 0; j < outv.length; j++) {
                    if(((unknownMask >> j) & 1) != 0) outv[j] = Value.ERROR;
                }
                out = Value.create(outv);
            }
        } else {
            out = src.computeOutput(inputs, num_inputs, attrs);
        }
        state.setValue(getEndLocation(0), out, this, GateAttributes.DELAY);
    }

    //
    // user interface methods
    //

    public void draw(ComponentDrawContext context) {
        AttributeSet attrs = (AttributeSet) getAttributeSet();
        Location loc = getLocation();
        Bounds bds = getBounds();
        context.getGraphics().setColor(Color.BLACK);
        drawBase(context, src, this, attrs, loc.getX(), loc.getY(),
                bds.getWidth(), bds.getHeight());
        if(!context.isPrintView() || context.getGateShape() == LogisimPreferences.SHAPE_RECTANGULAR) {
            context.drawPins(this);
        }
    }
    
    static void drawBase(ComponentDrawContext context,
            AbstractGateFactory src, AbstractGate comp,
            AttributeSet attrs, int x, int y, int width, int height) {
        Direction facing = (Direction) attrs.getValue(StdAttr.FACING);
        Graphics oldG = context.getGraphics();
        if(facing != Direction.EAST && oldG instanceof Graphics2D) {
            Graphics2D g2 = (Graphics2D) oldG.create();
            g2.rotate(-facing.toRadians(), x, y);
            context.setGraphics(g2);
            if(facing == Direction.NORTH || facing == Direction.SOUTH) {
                int t = width; width = height; height = t;
            }
        }
        
        Integer inputs = (Integer) attrs.getValue(GateAttributes.ATTR_INPUTS);
        if(context.getGateShape() == LogisimPreferences.SHAPE_RECTANGULAR) {
            src.drawRectangular(context, comp, x, y, width, height);
        } else if(context.getGateShape() == LogisimPreferences.SHAPE_DIN40700) {
            src.drawDinShape(context, comp, x, y, width, height, inputs.intValue());
        } else { // SHAPE_SHAPED
            int don = src.hasDongle ? 10 : 0;
            if(comp != null) {
                src.drawInputLines(context, comp, inputs.intValue(),
                    x - width, y - (height - 10) / 2, width - don, height);
            }
            src.drawShape(context, comp, x - don, y, width - don, height);
            if(src.hasDongle) {
                context.drawDongle(x - 5, y);
            }
        }
        context.setGraphics(oldG);
    }
    
    public Object getFeature(Object key) {
        if(key == WireRepair.class) return this;
        if(key == ExpressionComputer.class) return this;
        return super.getFeature(key);
    }
    
    public boolean shouldRepairWire(WireRepairData data) {
        return src.shouldRepairWire(this, data);
    }

    public void computeExpression(Map expressionMap) {
        AttributeSet attrs = getAttributeSet();
        int inputCount = ((Integer) attrs.getValue(GateAttributes.ATTR_INPUTS)).intValue();

        Expression[] inputs = new Expression[inputCount];
        int numInputs = 0;
        for(int i = 1; i <= inputCount; i++) {
            Expression e = (Expression) expressionMap.get(getEndLocation(i));
            if(e != null) {
                inputs[numInputs] = e;
                ++numInputs;
            }
        }
        if(numInputs > 0) {
            Expression out = src.computeExpression(inputs, numInputs);
            expressionMap.put(getEndLocation(0), out);
        }
    }

    void attributeValueChanged(Attribute attr, Object value) {
        if(attr == StdAttr.WIDTH) {
            setEnds();
        } else if(attr == StdAttr.FACING || attr == GateAttributes.ATTR_SIZE
                || attr == GateAttributes.ATTR_INPUTS) {
            recomputeBounds();
            setEnds();
        } else if(attr == GateAttributes.ATTR_XOR) {
            fireComponentInvalidated(new ComponentEvent(this));
        }
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.