/*******************************************************************************
* 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.ArrayList;
import javax.swing.event.TreeModelEvent;
import javax.swing.event.TreeModelListener;
import javax.swing.tree.TreeModel;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import com.cburch.logisim.circuit.CircuitState;
import com.cburch.logisim.comp.Component;
public class SimulationTreeModel implements TreeModel {
private ArrayList<TreeModelListener> listeners;
private SimulationTreeCircuitNode root;
private CircuitState currentView;
public SimulationTreeModel(CircuitState rootState) {
this.listeners = new ArrayList<TreeModelListener>();
this.root = new SimulationTreeCircuitNode(this, null, rootState, null);
this.currentView = null;
}
public void addTreeModelListener(TreeModelListener l) {
listeners.add(l);
}
private TreePath findPath(Object node) {
ArrayList<Object> path = new ArrayList<Object>();
Object current = node;
while (current instanceof TreeNode) {
path.add(0, current);
current = ((TreeNode) current).getParent();
}
if (current != null) {
path.add(0, current);
}
return new TreePath(path.toArray());
}
protected void fireNodeChanged(Object node) {
TreeModelEvent e = new TreeModelEvent(this, findPath(node));
for (TreeModelListener l : listeners) {
l.treeNodesChanged(e);
}
}
protected void fireStructureChanged(Object node) {
TreeModelEvent e = new TreeModelEvent(this, findPath(node));
for (TreeModelListener l : listeners) {
l.treeStructureChanged(e);
}
}
public Object getChild(Object parent, int index) {
if (parent instanceof TreeNode) {
return ((TreeNode) parent).getChildAt(index);
} else {
return null;
}
}
public int getChildCount(Object parent) {
if (parent instanceof TreeNode) {
return ((TreeNode) parent).getChildCount();
} else {
return 0;
}
}
public CircuitState getCurrentView() {
return currentView;
}
public int getIndexOfChild(Object parent, Object child) {
if (parent instanceof TreeNode && child instanceof TreeNode) {
return ((TreeNode) parent).getIndex((TreeNode) child);
} else {
return -1;
}
}
public Object getRoot() {
return root;
}
public CircuitState getRootState() {
return root.getCircuitState();
}
public boolean isLeaf(Object node) {
if (node instanceof TreeNode) {
return ((TreeNode) node).getChildCount() == 0;
} else {
return true;
}
}
protected SimulationTreeNode mapComponentToNode(Component comp) {
return null;
}
private SimulationTreeCircuitNode mapToNode(CircuitState state) {
TreePath path = mapToPath(state);
if (path == null) {
return null;
} else {
return (SimulationTreeCircuitNode) path.getLastPathComponent();
}
}
public TreePath mapToPath(CircuitState state) {
if (state == null)
return null;
ArrayList<CircuitState> path = new ArrayList<CircuitState>();
CircuitState current = state;
CircuitState parent = current.getParentState();
while (parent != null && parent != state) {
path.add(current);
current = parent;
parent = current.getParentState();
}
Object[] pathNodes = new Object[path.size() + 1];
pathNodes[0] = root;
int pathPos = 1;
SimulationTreeCircuitNode node = root;
for (int i = path.size() - 1; i >= 0; i--) {
current = path.get(i);
SimulationTreeCircuitNode oldNode = node;
for (int j = 0, n = node.getChildCount(); j < n; j++) {
Object child = node.getChildAt(j);
if (child instanceof SimulationTreeCircuitNode) {
SimulationTreeCircuitNode circNode = (SimulationTreeCircuitNode) child;
if (circNode.getCircuitState() == current) {
node = circNode;
break;
}
}
}
if (node == oldNode) {
return null;
}
pathNodes[pathPos] = node;
pathPos++;
}
return new TreePath(pathNodes);
}
public void removeTreeModelListener(TreeModelListener l) {
listeners.remove(l);
}
public void setCurrentView(CircuitState value) {
CircuitState oldView = currentView;
if (oldView != value) {
currentView = value;
SimulationTreeCircuitNode node1 = mapToNode(oldView);
if (node1 != null)
fireNodeChanged(node1);
SimulationTreeCircuitNode node2 = mapToNode(value);
if (node2 != null)
fireNodeChanged(node2);
}
}
public void valueForPathChanged(TreePath path, Object newValue) {
throw new UnsupportedOperationException();
}
}