/*
* funCKit - functional Circuit Kit
* Copyright (C) 2013 Lukas Elsner <open@mindrunner.de>
* Copyright (C) 2013 Peter Dahlberg <catdog2@tuxzone.org>
* Copyright (C) 2013 Julian Stier <mail@julian-stier.de>
* Copyright (C) 2013 Sebastian Vetter <mail@b4sti.eu>
* Copyright (C) 2013 Thomas Poxrucker <poxrucker_t@web.de>
* Copyright (C) 2013 Alexander Treml <alex.treml@directbox.com>
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*/
package de.sep2011.funckit.view.projecttreemodel;
import de.sep2011.funckit.model.graphmodel.Brick;
import static com.google.common.base.Preconditions.*;
import de.sep2011.funckit.model.graphmodel.Circuit;
import de.sep2011.funckit.model.graphmodel.Component;
import de.sep2011.funckit.model.graphmodel.Element;
import de.sep2011.funckit.model.graphmodel.ElementDispatcher;
import de.sep2011.funckit.model.graphmodel.Switch;
import de.sep2011.funckit.model.graphmodel.Wire;
import de.sep2011.funckit.model.graphmodel.implementations.And;
import de.sep2011.funckit.model.graphmodel.implementations.IdPoint;
import de.sep2011.funckit.model.graphmodel.implementations.Light;
import de.sep2011.funckit.model.graphmodel.implementations.Not;
import de.sep2011.funckit.model.graphmodel.implementations.Or;
import de.sep2011.funckit.model.sessionmodel.Project;
import de.sep2011.funckit.observer.GraphModelInfo;
import de.sep2011.funckit.observer.GraphModelObserver;
import de.sep2011.funckit.observer.ProjectInfo;
import de.sep2011.funckit.observer.ProjectObserver;
import de.sep2011.funckit.util.Log;
import de.sep2011.funckit.util.Pair;
import java.util.ArrayList;
import java.util.Arrays;
/**
* This tree node has {@link Project}s as content. It has
* {@link ProjectTreeBrickNode}s coming from the {@link Project}'s
* {@link Circuit} as children. It observes the {@link Project} and the
* corresponding {@link Circuit} after expansion..
*/
public class ProjectTreeProjectNode extends ProjectTreeNode<Project> implements
ProjectObserver, GraphModelObserver {
/* keep this reference so we can be sure that we can unregister on dispose() */
private Circuit observedCircuit;
/**
* Create a new {@link ProjectTreeProjectNode}.
*
* @param tm
* the corresponding {@link ProjectTreeModel}, not null.
* @param pro
* the project which is the content of this node, not null.
* @param parent
* the parent of this node, not null.
*/
public ProjectTreeProjectNode(ProjectTreeModel tm, Project pro,
ProjectTreeNode<?> parent) {
checkNotNull(tm);
checkNotNull(pro);
checkNotNull(parent);
this.treeModel = tm;
this.nodeContent = pro;
this.parent = parent;
pro.addObserver(this);
}
@Override
public void graphModelChanged(Circuit source, GraphModelInfo i) {
if (children == null) {
Log.gl().warn("children is null but should not be");
return;
}
if (!i.getAddedBricks().isEmpty()) {
int startIdx = children.size();
for (Brick brick : i.getAddedBricks()) {
if (!(brick instanceof IdPoint) && !childContainsContent(brick)) {
children.add(new ProjectTreeBrickNode(treeModel, brick,
this));
}
}
int[] idxes = new int[children.size() - startIdx];
ProjectTreeNode<?>[] added = new ProjectTreeNode<?>[children.size()
- startIdx];
for (int j = 0; j < idxes.length; j++) {
idxes[j] = startIdx + j;
added[j] = children.get(startIdx + j);
}
treeModel.fireTreeNodesInserted(getAbsolutePath(), idxes, added);
}
if (!i.getRemovedBricks().isEmpty()) {
Pair<int[], Object[]> rmpair = removeChildrenByContent(i
.getRemovedBricks().toArray());
treeModel.fireTreeNodesRemoved(getAbsolutePath(), rmpair.getLeft(),
rmpair.getRight());
}
if (!i.getChangedBricks().isEmpty()) {
Pair<int[], Object[]> chpair = getChildNodesByContent(i
.getChangedBricks());
Log.gl().debug(
Arrays.toString(chpair.getLeft()) + "~~"
+ Arrays.toString(chpair.getRight()));
treeModel.fireTreeNodesChanged(getAbsolutePath(), chpair.getLeft(),
chpair.getRight());
}
}
@Override
public void projectChanged(Project source, ProjectInfo i) {
if (i.isCircuitChanged()) {
treeModel.fireTreeStructureChanged(getAbsolutePath());
}
if (i.isNameChanged()) {
int[] idxes = { parent.getIndexOfChild(this) };
ProjectTreeNode<?>[] chch = { this };
treeModel.fireTreeNodesChanged(parent.getAbsolutePath(), idxes, chch);
}
}
@Override
public boolean isLeaf() {
return nodeContent.getCircuit() == null;
}
@Override
public boolean generateChildren() {
if (nodeContent.getCircuit() == null
|| nodeContent.getCircuit().getElements().isEmpty()) {
return false;
}
if (children == null) {
children = new ArrayList<ProjectTreeNode<?>>();
new ElementDispatcher() {
{
for (Element elem : nodeContent.getCircuit().getElements()) {
elem.dispatch(this);
}
}
@Override
public void visit(IdPoint idPoint) {
}
@Override
public void visit(Not not) {
addBrick(not);
}
@Override
public void visit(Or or) {
addBrick(or);
}
@Override
public void visit(And and) {
addBrick(and);
}
@Override
public void visit(Light light) {
addBrick(light);
}
@Override
public void visit(Switch s) {
addBrick(s);
}
@Override
public void visit(Component component) {
addBrick(component);
}
@Override
public void visit(Wire wire) {
}
@Override
public void visit(Element element) {
}
private void addBrick(Brick b) {
children.add(new ProjectTreeBrickNode(treeModel, b,
ProjectTreeProjectNode.this));
}
};
observedCircuit = nodeContent.getCircuit();
observedCircuit.addObserver(this);
treeModel.fireTreeStructureChanged(getAbsolutePath());
} else {
Log.gl().debug("Children already generated!");
}
return true;
}
@Override
public void dispose() {
nodeContent.deleteObserver(this);
if (observedCircuit != null) {
observedCircuit.deleteObserver(this);
observedCircuit = null;
}
}
@Override
public String toString() {
return nodeContent.getName();
}
@Override
public void accept(ProjectTreeNodeVisitor visitor) {
visitor.visit(this);
}
}