/*******************************************************************************
* This file is part of logisim-evolution.
*
* logisim-evolution is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* logisim-evolution is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with logisim-evolution. If not, see <http://www.gnu.org/licenses/>.
*
* Original code by Carl Burch (http://www.cburch.com), 2011.
* Subsequent modifications by :
* + Haute École Spécialisée Bernoise
* http://www.bfh.ch
* + Haute École du paysage, d'ingénierie et d'architecture de Genève
* http://hepia.hesge.ch/
* + Haute École d'Ingénierie et de Gestion du Canton de Vaud
* http://www.heig-vd.ch/
* The project is currently maintained by :
* + REDS Institute - HEIG-VD
* Yverdon-les-Bains, Switzerland
* http://reds.heig-vd.ch
*******************************************************************************/
package com.cburch.logisim.gui.main;
import java.util.Comparator;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.swing.JOptionPane;
import com.cburch.logisim.circuit.Circuit;
import com.cburch.logisim.circuit.CircuitAttributes;
import com.cburch.logisim.circuit.CircuitException;
import com.cburch.logisim.circuit.CircuitMutation;
import com.cburch.logisim.circuit.SubcircuitFactory;
import com.cburch.logisim.circuit.Wire;
import com.cburch.logisim.comp.Component;
import com.cburch.logisim.comp.ComponentFactory;
import com.cburch.logisim.data.Attribute;
import com.cburch.logisim.data.Location;
import com.cburch.logisim.gui.generic.AttrTableSetException;
import com.cburch.logisim.gui.generic.AttributeSetTableModel;
import com.cburch.logisim.gui.main.Selection.Event;
import com.cburch.logisim.instance.StdAttr;
import com.cburch.logisim.proj.Action;
import com.cburch.logisim.proj.Project;
import com.cburch.logisim.tools.SetAttributeAction;
import com.cburch.logisim.util.AutoLabel;
class AttrTableSelectionModel extends AttributeSetTableModel implements
Selection.Listener {
private Project project;
private Frame frame;
public AttrTableSelectionModel(Project project, Frame frame) {
super(frame.getCanvas().getSelection().getAttributeSet());
this.project = project;
this.frame = frame;
frame.getCanvas().getSelection().addListener(this);
}
@Override
public String getTitle() {
ComponentFactory wireFactory = null;
ComponentFactory factory = null;
int factoryCount = 0;
int totalCount = 0;
boolean variousFound = false;
Selection selection = frame.getCanvas().getSelection();
for (Component comp : selection.getComponents()) {
ComponentFactory fact = comp.getFactory();
if (fact.equals(factory)) {
factoryCount++;
} else if (comp instanceof Wire) {
wireFactory = fact;
if (factory == null) {
factoryCount++;
}
} else if (factory == null) {
factory = fact;
factoryCount = 1;
} else {
variousFound = true;
}
if (!(comp instanceof Wire)) {
totalCount++;
}
}
if (factory == null) {
factory = wireFactory;
}
if (variousFound) {
SetInstance(factory);
return Strings.get("selectionVarious", "" + totalCount);
} else if (factoryCount == 0) {
String circName = frame.getCanvas().getCircuit().getName();
SetInstance(frame.getCanvas().getCircuit().getSubcircuitFactory());
return Strings.get("circuitAttrTitle", circName);
} else if (factoryCount == 1) {
SetInstance(factory);
return Strings.get("selectionOne", factory.getDisplayName());
} else {
SetInstance(factory);
return Strings.get("selectionMultiple", factory.getDisplayName(),
"" + factoryCount);
}
}
//
// Selection.Listener methods
public void selectionChanged(Event event) {
fireTitleChanged();
if (frame.getEditorView().equals(Frame.EDIT_LAYOUT)) {
frame.setAttrTableModel(this);
}
}
private class PositionComparator implements Comparator<Component> {
@Override
public int compare(Component o1, Component o2) {
if (o1==o2)
return 0;
Location l1 = o1.getLocation();
Location l2 = o2.getLocation();
if (l2.getY() != l1.getY())
return l1.getY()-l2.getY();
if (l2.getX() != l1.getX())
return l1.getX()-l2.getX();
return -1;
}
}
@Override
public void setValueRequested(Attribute<Object> attr, Object value)
throws AttrTableSetException {
Selection selection = frame.getCanvas().getSelection();
Circuit circuit = frame.getCanvas().getCircuit();
if (selection.isEmpty() && circuit != null) {
AttrTableCircuitModel circuitModel = new AttrTableCircuitModel(
project, circuit);
circuitModel.setValueRequested(attr, value);
} else {
SetAttributeAction act = new SetAttributeAction(circuit,
Strings.getter("selectionAttributeAction"));
AutoLabel labler = null;
if (attr.equals(StdAttr.LABEL)) {
labler = new AutoLabel((String)value,circuit);
}
SortedSet<Component> comps = new TreeSet<Component>(new PositionComparator());
comps.addAll(selection.getComponents());
for (Component comp : comps) {
if (!(comp instanceof Wire)) {
if (comp.getFactory() instanceof SubcircuitFactory) {
SubcircuitFactory fac = (SubcircuitFactory) comp.getFactory();
if (attr.equals(CircuitAttributes.NAMED_CIRCUIT_BOX)||
attr.equals(CircuitAttributes.NAME_ATTR)) {
try {
CircuitMutation mutation = new CircuitMutation(fac.getSubcircuit());
mutation.setForCircuit(attr, value);
Action action = mutation.toAction(null);
project.doAction(action);
} catch (CircuitException ex) {
JOptionPane.showMessageDialog(project.getFrame(),
ex.getMessage());
}
return;
}
}
if (attr.equals(StdAttr.LABEL)) {
if (labler.hasNext(circuit)) {
if (comps.size()>1) {
act.set(comp, attr , labler.GetNext(circuit, comp.getFactory()));
} else {
if (getAttributeSet().getValue(StdAttr.LABEL).equals((String)value))
return;
else
act.set(comp, attr, labler.GetCurrent(circuit, comp.getFactory()));
}
} else act.set(comp, attr, "");
} else
act.set(comp, attr, value);
}
}
project.doAction(act);
}
}
}