Package com.cburch.logisim.instance

Source Code of com.cburch.logisim.instance.InstanceFactory

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

import java.awt.Color;
import java.awt.Graphics;
import java.util.Collections;
import java.util.List;

import javax.swing.Icon;

import com.cburch.logisim.LogisimVersion;
import com.cburch.logisim.circuit.CircuitState;
import com.cburch.logisim.comp.AbstractComponentFactory;
import com.cburch.logisim.comp.Component;
import com.cburch.logisim.comp.ComponentDrawContext;
import com.cburch.logisim.data.Attribute;
import com.cburch.logisim.data.AttributeSet;
import com.cburch.logisim.data.AttributeSets;
import com.cburch.logisim.data.Bounds;
import com.cburch.logisim.data.Direction;
import com.cburch.logisim.data.Location;
import com.cburch.logisim.gui.log.Loggable;
import com.cburch.logisim.tools.Pokable;
import com.cburch.logisim.tools.key.KeyConfigurator;
import com.cburch.logisim.util.Icons;
import com.cburch.logisim.util.StringGetter;
import com.cburch.logisim.util.StringUtil;
import com.cburch.logisim.util.UnmodifiableList;

/**
* Represents a category of components that appear in a circuit. This class
* and <code>Component</code> share the same sort of relationship as the
* relation between <em>classes</em> and <em>instances</em> in Java. Normally,
* there is only one ComponentFactory created for any particular category.
*/
public abstract class InstanceFactory extends AbstractComponentFactory {
  private String name;
  private StringGetter displayName;
  private StringGetter defaultToolTip;
  private String iconName;
  private Icon icon;
  private Attribute<?>[] attrs;
  private Object[] defaults;
  private AttributeSet defaultSet;
  private Bounds bounds;
  private List<Port> portList;
  private Attribute<Direction> facingAttribute;
  private Boolean shouldSnap;
  private KeyConfigurator keyConfigurator;
  private Class<? extends InstancePoker> pokerClass;
  private Class<? extends InstanceLogger> loggerClass;
 
  public InstanceFactory(String name) {
    this(name, StringUtil.constantGetter(name));
  }
 
  public InstanceFactory(String name, StringGetter displayName) {
    this.name = name;
    this.displayName = displayName;
    this.iconName = null;
    this.icon = null;
    this.attrs = null;
    this.defaults = null;
    this.bounds = Bounds.EMPTY_BOUNDS;
    this.portList = Collections.emptyList();
    this.keyConfigurator = null;
    this.facingAttribute = null;
    this.shouldSnap = Boolean.TRUE;
  }
 
  @Override
  public String getName() {
    return name;
  }
 
  @Override
  public String getDisplayName() {
    return getDisplayGetter().get();
  }
 
  @Override
  public StringGetter getDisplayGetter() {
    return displayName;
  }
 
  public void setIconName(String value) {
    iconName = value;
    icon = null;
  }
 
  public void setIcon(Icon value) {
    iconName = "";
    icon = value;
  }
 
  @Override
  public final void paintIcon(ComponentDrawContext context,
      int x, int y, AttributeSet attrs) {
    InstancePainter painter = context.getInstancePainter();
    painter.setFactory(this, attrs);
    Graphics g = painter.getGraphics();
    g.translate(x, y);
    paintIcon(painter);
    g.translate(-x, -y);
   
    if (painter.getFactory() == null) {
      Icon i = icon;
      if (i == null) {
        String n = iconName;
        if (n != null) {
          i = Icons.getIcon(n);
          if (i == null) n = null;
        }
      }
      if (i != null) {
        i.paintIcon(context.getDestination(), g, x + 2, y + 2);
      } else {
        super.paintIcon(context, x, y, attrs);
      }
    }
  }
 
  @Override
  public final Component createComponent(Location loc, AttributeSet attrs) {
    InstanceComponent ret = new InstanceComponent(this, loc, attrs);
    configureNewInstance(ret.getInstance());
    return ret;
  }
 
  public void setOffsetBounds(Bounds value) {
    bounds = value;
  }

  @Override
  public Bounds getOffsetBounds(AttributeSet attrs) {
    Bounds ret = bounds;
    if (ret == null) {
      throw new RuntimeException("offset bounds unknown: "
          + "use setOffsetBounds or override getOffsetBounds");
    }
    return ret;
  }
 
  public boolean contains(Location loc, AttributeSet attrs) {
    Bounds bds = getOffsetBounds(attrs);
    if (bds == null) return false;
    return bds.contains(loc, 1);
  }

 
  public Attribute<Direction> getFacingAttribute() {
    return facingAttribute;
  }
 
  public void setFacingAttribute(Attribute<Direction> value) {
    facingAttribute = value;
  }
 
  public KeyConfigurator getKeyConfigurator() {
    return keyConfigurator;
  }
 
  public void setKeyConfigurator(KeyConfigurator value) {
    keyConfigurator = value;
  }
 
  public void setAttributes(Attribute<?>[] attrs, Object[] defaults) {
    this.attrs = attrs;
    this.defaults = defaults;
  }
 
  @Override
  public AttributeSet createAttributeSet() {
    Attribute<?>[] as = attrs;
    AttributeSet ret = as == null ? AttributeSets.EMPTY : AttributeSets.fixedSet(as, defaults);
    return ret;
  }

  @Override
  public Object getDefaultAttributeValue(Attribute<?> attr, LogisimVersion ver) {
    Attribute<?>[] as = attrs;
    if (as != null) {
      for (int i = 0; i < as.length; i++) {
        if (as[i] == attr) {
          return defaults[i];
        }
      }
      return null;
    } else {
      AttributeSet dfltSet = defaultSet;
      if (dfltSet == null) {
        dfltSet = createAttributeSet();
        defaultSet = dfltSet;
      }
      return dfltSet.getValue(attr);
    }
  }

 
  public void setPorts(Port[] ports) {
    portList = new UnmodifiableList<Port>(ports);
  }
 
  public void setPorts(List<Port> ports) {
    portList = Collections.unmodifiableList(ports);
  }
 
  public List<Port> getPorts() {
    return portList;
  }

  public void setDefaultToolTip(StringGetter value) {
    defaultToolTip = value;
  }
 
  public StringGetter getDefaultToolTip() {
    return defaultToolTip;
  }
 
  public void setInstancePoker(Class<? extends InstancePoker> pokerClass) {
    if (isClassOk(pokerClass, InstancePoker.class)) {
      this.pokerClass = pokerClass;
    }
  }
 
  public void setInstanceLogger(Class<? extends InstanceLogger> loggerClass) {
    if (isClassOk(loggerClass, InstanceLogger.class)) {
      this.loggerClass = loggerClass;
    }
  }
 
  public void setShouldSnap(boolean value) {
    shouldSnap = Boolean.valueOf(value);
  }
 
  private boolean isClassOk(Class<?> sub, Class<?> sup) {
    boolean isSub = sup.isAssignableFrom(sub);
    if (!isSub) {
      System.err.println(sub.getName() + " must be a subclass of " + sup.getName()); //OK
      return false;
    }
    try {
      sub.getConstructor(new Class[0]);
      return true;
    } catch (SecurityException e) {
      System.err.println(sub.getName() + " needs its no-args constructor to be public"); //OK
    } catch (NoSuchMethodException e) {
      System.err.println(sub.getName() + " is missing a no-arguments constructor"); //OK
    }
    return true;
  }
 
  @Override
  public final Object getFeature(Object key, AttributeSet attrs) {
    if (key == FACING_ATTRIBUTE_KEY) return facingAttribute;
    if (key == KeyConfigurator.class) return keyConfigurator;
    if (key == SHOULD_SNAP) return shouldSnap;
    return super.getFeature(key, attrs);
  }
 
  @Override
  public final void drawGhost(ComponentDrawContext context, Color color,
      int x, int y, AttributeSet attrs) {
    InstancePainter painter = context.getInstancePainter();
    Graphics g = painter.getGraphics();
    g.setColor(color);
    g.translate(x, y);
    painter.setFactory(this, attrs);
    paintGhost(painter);
    g.translate(-x, -y);
    if (painter.getFactory() == null) {
      super.drawGhost(context, color, x, y, attrs);
    }
  }
 
  public void paintIcon(InstancePainter painter) {
    painter.setFactory(null, null);
  }
 
  public void paintGhost(InstancePainter painter) {
    painter.setFactory(null, null);
  }
 
  public abstract void paintInstance(InstancePainter painter);
  public abstract void propagate(InstanceState state);
 
  // event methods
  protected void configureNewInstance(Instance instance) { }
  protected void instanceAttributeChanged(Instance instance, Attribute<?> attr) { }
  protected Object getInstanceFeature(Instance instance, Object key) {
    if (key == Pokable.class && pokerClass != null) {
      return new InstancePokerAdapter(instance.getComponent(), pokerClass);
    } else if (key == Loggable.class && loggerClass != null) {
      return new InstanceLoggerAdapter(instance.getComponent(), loggerClass);
    } else {
      return null;
    }
  }
 
  public InstanceState createInstanceState(CircuitState state, Instance instance) {
    return new InstanceStateImpl(state, instance.getComponent());
  }
 
  public final InstanceState createInstanceState(CircuitState state, Component comp) {
    return createInstanceState(state, ((InstanceComponent) comp).getInstance());
  }
}
TOP

Related Classes of com.cburch.logisim.instance.InstanceFactory

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.