/*******************************************************************************
* 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
*******************************************************************************/
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package com.cburch.logisim.gui.generic;
import java.awt.Color;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.util.Arrays;
import java.util.HashMap;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import com.cburch.logisim.circuit.Circuit;
import com.cburch.logisim.circuit.CircuitState;
import com.cburch.logisim.circuit.SimulatorEvent;
import com.cburch.logisim.circuit.SimulatorListener;
import com.cburch.logisim.comp.Component;
import com.cburch.logisim.data.Location;
import com.cburch.logisim.data.Value;
import com.cburch.logisim.file.LoadedLibrary;
import com.cburch.logisim.file.LogisimFile;
import com.cburch.logisim.gui.main.Frame;
import com.cburch.logisim.instance.StdAttr;
import com.cburch.logisim.proj.Project;
import com.cburch.logisim.std.memory.Register;
import com.cburch.logisim.util.LocaleListener;
/**
*
* @author YSY
*/
public class RegTabContent extends JScrollPane implements LocaleListener,
SimulatorListener {
private class MyLabel extends JLabel {
private static final long serialVersionUID = 1L;
private MyLabel(String text) {
super(text);
}
private MyLabel(String text, int style) {
super(text);
setFont(getFont().deriveFont(style));
}
private MyLabel(String text, int style, boolean small) {
super(text);
setFont(getFont().deriveFont(style));
setFont(getFont().deriveFont(getFont().getSize2D() - 2));
}
private void setColor(Color color) {
setBackground(color);
setOpaque(true);
}
}
private static final long serialVersionUID = 1L;
private JPanel panel = new JPanel(new GridBagLayout());
private GridBagConstraints c = new GridBagConstraints();
private Project proj;
private static HashMap<String, Component> registers = new HashMap<String, Component>();
public RegTabContent(Frame frame) {
super();
setViewportView(panel);
proj = frame.getProject();
getVerticalScrollBar().setUnitIncrement(16);
proj.getSimulator().addSimulatorListener(this);
fillArray();
}
/**
* This function will clear and fill the registers tab and refresh their
* value. It will start by iterate over all circuits of the current project
* to register all the "Register" components (providing their attributes are
* correctly set). It will then fill the panel with each register found,
* including their current value.
*/
private void fillArray() {
int y = 0;
MyLabel col1 = new MyLabel("Circuit", Font.ITALIC | Font.BOLD);
MyLabel col2 = new MyLabel("Reg name", Font.BOLD);
MyLabel col3 = new MyLabel("Value", Font.BOLD);
registers.clear();
panel.removeAll();
for (Circuit circ : proj.getLogisimFile().getCircuits()) {
getAllRegisters(circ);
}
if (proj.getLogisimFile().getLibrary("prodis_v1.3") instanceof LoadedLibrary) {
if (((LoadedLibrary) proj.getLogisimFile()
.getLibrary("prodis_v1.3")).getBase() instanceof LogisimFile) {
for (Circuit circ : ((LogisimFile) ((LoadedLibrary) proj
.getLogisimFile().getLibrary("prodis_v1.3")).getBase())
.getCircuits()) {
getAllRegisters(circ);
}
}
}
col1.setColor(Color.LIGHT_GRAY);
col2.setColor(Color.LIGHT_GRAY);
col3.setColor(Color.LIGHT_GRAY);
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.FIRST_LINE_START;
c.ipady = 2;
c.weighty = 0;
c.gridy = y;
c.gridx = 0;
c.weightx = 0.3;
panel.add(col1, c);
c.gridx++;
c.weightx = 0.5;
panel.add(col2, c);
c.gridx++;
c.weightx = 0.2;
panel.add(col3, c);
y++;
if (!registers.isEmpty()) {
Object[] objArr = registers.keySet().toArray();
Arrays.sort(objArr);
for (Object name : objArr) {
c.gridy = y;
c.gridx = 0;
String circuitName = name.toString().split("/")[0];
panel.add(new MyLabel(circuitName, Font.ITALIC, true), c);
c.gridx++;
String registerName = name.toString().split("/")[1];
panel.add(new MyLabel(registerName), c);
c.gridx++;
Component selReg = registers.get(name.toString());
CircuitState mainCircState = proj.getCircuitState();
while (mainCircState.getParentState() != null) { // Get the main
// circuit
mainCircState = mainCircState.getParentState();
}
Value val = findVal(mainCircState, circuitName, selReg
.getEnd(0).getLocation()); // Get Q port location
if (val != null) {
panel.add(new MyLabel(val.toHexString()), c);
} else {
panel.add(new MyLabel("-"), c);
}
y++;
}
}
c.weighty = 1;
c.gridy++;
c.gridx = 0;
c.weightx = 1;
panel.add(new MyLabel(""), c);
panel.validate();
}
/**
* This function will search for the value at a given location in a circuit
* with the given name. The function will search iteratively in all
* sub-circuits of the given circuit if it cannot be found directly, and
* will return null if the value cannot be found.
*
* @param cs
* The state of the circuit in which the value is searched.
* @param cn
* The name of the circuit in which the value must be found.
* @param loc
* The location of the value in the circuit.
* @return The value, or null if it cannot be found.
*/
private synchronized Value findVal(CircuitState cs, String cn, Location loc) {
if (cs.containsKey(loc) && cs.getCircuit().getName().equals(cn)) {
return cs.getValue(loc);
} else {
if (cs.getSubstates() != null && cs.getSubstates().size() > 0) {
for (CircuitState cst : cs.getSubstates()) {
Value ret;
if ((ret = findVal(cst, cn, loc)) != null) {
return ret;
}
}
}
return null;
}
}
/**
* This function will register all the components of type "Register" contain
* in the given circuit. The registers will only be registered if their
* ATTR_SHOW_IN_TAB is set to true, and if their label is not empty.
*
* @param circuit
* The circuit in which the registers are searched.
*/
private synchronized void getAllRegisters(Circuit circuit) {
for (Component comp : circuit.getNonWires()) {
if (comp.getFactory().getName().equals("Register")) {
if (comp.getAttributeSet().getValue(Register.ATTR_SHOW_IN_TAB)
&& !comp.getAttributeSet().getValue(StdAttr.LABEL)
.equals("")) {
registers.put(circuit.getName() + "/"
+ comp.getAttributeSet().getValue(StdAttr.LABEL),
comp);
}
}
}
}
@Override
public void localeChanged() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void propagationCompleted(SimulatorEvent e) {
// throw new UnsupportedOperationException("Not supported yet.");
fillArray();
}
@Override
public void simulatorStateChanged(SimulatorEvent e) {
// throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void tickCompleted(SimulatorEvent e) {
// throw new UnsupportedOperationException("Not supported yet.");
}
}