/*
* 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.model.sessionmodel;
import java.io.Serializable;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import de.sep2011.funckit.model.graphmodel.Circuit;
import de.sep2011.funckit.model.graphmodel.Element;
import de.sep2011.funckit.model.simulationmodel.Simulation;
import de.sep2011.funckit.observer.AbstractObservable;
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.command.Command;
import de.sep2011.funckit.util.command.CommandDispatcher;
import de.sep2011.funckit.validator.Result;
/**
* This class represents a project in this application. It has all the data that
* a belongs only to one project, such as the {@link Circuit}, the current
* {@link Simulation} of the {@link Circuit}, the opened views (
* {@link EditPanelModel}s) of the {@link Circuit}, the dispatchers for the
* {@link Command}s etc.
*/
public class Project extends AbstractObservable<ProjectObserver, ProjectInfo>
implements Serializable, GraphModelObserver {
/**
* Used for serialization.
*/
private static final long serialVersionUID = 3658148621266426656L;
/**
* Name of this project.
*/
private String name;
/**
* Path to project on hard disk for persisting circuit and project
* information.
*/
private String path;
/**
* The current active simulation for this project.
*/
transient private Simulation simulation;
/**
* The models for the currently opened EditPanels.
*/
transient private Set<EditPanelModel> openedEditPanelModels;
/**
* The currently selected {@link EditPanelModel}.
*/
transient private EditPanelModel selectedEditPanelModel;
/**
* The circuit belonging to this project.
*/
transient private Circuit circuit;
/**
* Set of results from a validator or set of checks to display information
* on GUI.
*/
transient private List<Result> checkResults;
/**
* Ghosts that should marked erroneous.
*/
transient private Set<Element> errorGhosts;
/**
* Command dispatcher object for dispatching or undoing commands performed
* on graph model.
*/
transient private CommandDispatcher graphCommandDispatcher;
/**
* Command dispatcher object to dispatch or undo simulation commands.
*/
transient private CommandDispatcher simulationCommandDispatcher;
/**
* Was the project modified since last save?
*/
transient private boolean modified;
/**
* Specifies the delay of the simulation timer in miliseconds for this
* project.
*/
private transient int timerDelay;
/**
* true if simulation is in paused state.
*/
private transient boolean simulationPaused;
/**
* Returns the timer delay.
*
* @return the timer delay
*/
public int getTimerDelay() {
return timerDelay;
}
/**
* Sets the delay of the simulation timer in milliseconds.
*
* @param timerDelay
* should be >= 0
*/
public void setTimerDelay(int timerDelay) {
assert timerDelay >= 0;
this.timerDelay = timerDelay;
setChanged();
getInfo().setSimulationControlStateModified(true);
notifyObserversIfAuto();
}
/**
* Creates a new {@link Project} with the given {@link Circuit}, the given
* name and the given application {@link Settings}.
*
* @param circuit
* the {@link Circuit} of this {@link Project}.
* @param name
* the name of this {@link Project}. Has to be non null.
* @param settings
* the {@link Settings} of the application to use. Has to be non
* null.
*/
public Project(Circuit circuit, String name, Settings settings) {
assert name != null;
this.name = name;
this.circuit = circuit;
if (circuit != null) {
circuit.addObserver(this);
}
initializeTransient(settings);
}
/**
* Initializes all the transient attributes of this {@link Project} with the
* given {@link Settings} of the application.
*
* @param settings
* the {@link Settings} of the application.
*/
public void initializeTransient(Settings settings) {
assert settings != null;
initInfo(ProjectInfo.getInfo());
graphCommandDispatcher =
new CommandDispatcher(
settings.getInt(Settings.MAXIMUM_COMMAND_QUEUE_SIZE));
simulationCommandDispatcher =
new CommandDispatcher(
settings.getInt(Settings.MAXIMUM_COMMAND_QUEUE_SIZE));
openedEditPanelModels = new HashSet<EditPanelModel>();
checkResults = new LinkedList<Result>();
timerDelay = settings.getInt(Settings.DEFAULT_TIMER_DELAY);
simulationPaused = false;
}
/**
* Return true if the simulation is in paused state.
*
* @return true if the simulation is in paused state
*/
public boolean isSimulationPaused() {
return simulationPaused;
}
/**
* true means simulation paused.
*
* @param simulationPaused
* true means simualtion paused
*/
public void setSimulationPaused(boolean simulationPaused) {
this.simulationPaused = simulationPaused;
setChanged();
getInfo().setSimulationControlStateModified(true);
notifyObserversIfAuto();
}
@Override
public void notifyObserver(ProjectInfo i, ProjectObserver obs) {
obs.projectChanged(this, i);
}
/**
* Getter method for project name.
*
* @return Project name.
*/
public String getName() {
return name;
}
/**
* Specifies new project name. Notifies all observers.
*
* @param name
*/
public void setName(String name) {
assert name != null;
if (!this.name.equals(name)) {
modified = true;
}
this.name = name;
setChanged();
getInfo().setNameChanged(true).setModified(true);
notifyObserversIfAuto();
}
/**
* Getter method for project hard disk path.
*
* @return Hard disk path as string. Can be null.
*/
public String getAbsolutePath() {
return path;
}
/**
* Specifies project path as string. Notifies all observers.
*
* @param path
* project path as string.
*/
public void setPath(String path) {
this.path = path;
setChanged();
getInfo().setPathChanged(true);
notifyObserversIfAuto();
}
/**
* Get the current {@link Simulation} for this project.
*
* @return the current {@link Simulation} for this project. Can be null.
*/
public Simulation getSimulation() {
return simulation;
}
/**
* Set the current {@link Simulation} for this project. Notifies all
* observers.
*
* @param simulation
* {@link Simulation} to set as current.
*/
public void setSimulation(Simulation simulation) {
getInfo().setOldSimulation(this.simulation);
this.simulation = simulation;
setChanged();
getInfo().setSimulationChanged(true);
notifyObserversIfAuto();
}
/**
* Returns true if this project is currently simulated.
*
* @return true if this project is currently simulated.
*/
public boolean hasSimulation() {
return simulation != null;
}
/**
* Returns the currently opened {@link EditPanelModel}s. This a reference to
* the internally used {@link Set} - do not modify!.
*
* @return the currently opened {@link EditPanelModel}s.
*/
public Set<EditPanelModel> getOpenedEditPanelModels() {
return openedEditPanelModels;
}
/**
* Gets the current selected {@link EditPanelModel}. Returns null if noting
* is selected.
*
* @return the current selected {@link EditPanelModel}. Can be null.
*/
public EditPanelModel getSelectedEditPanelModel() {
return selectedEditPanelModel;
}
/**
* Sets the currently selected {@link EditPanelModel}. Notifies all
* observers.
*
* @param panelModel
* the new selected {@link EditPanelModel}. Use null to unset.
*/
public void setSelectedEditPanelModel(EditPanelModel panelModel) {
selectedEditPanelModel = panelModel;
setChanged();
getInfo().setChangedModel(panelModel).setActiveEditPanelModelChanged(
true);
notifyObserversIfAuto();
}
/**
* Returns set of results from latest performed set of checks.
*
* @return set of results from latest performed set of checks. Is null if no
* check was performed.
*/
public List<Result> getCheckResults() {
return checkResults;
}
/**
* Sets the set of results from latest performed set of checks. Notifies all
* observers.
*
* @param checkResults
* the new set of results. Use null to unset.
*/
public void setCheckResults(List<Result> checkResults) {
this.checkResults = checkResults;
setChanged();
getInfo().setResultsChanged(true);
notifyObserversIfAuto();
}
/**
* Returns the circuit that belongs to this project.
*
* @return the circuit that belongs to this project.
*/
public Circuit getCircuit() {
return circuit;
}
/**
* Sets the {@link Circuit} that belongs to this project. Notifies all
* observers. Warning! This does just set the new circuit. Nothing is done
* to ensure consistent {@link EditPanelModel}s etc.
*
* @param circuit
* the new {@link Circuit} of this project.
*/
public void setCircuit(Circuit circuit) {
if (this.circuit != null) {
this.circuit.deleteObserver(this);
}
this.circuit = circuit;
if (circuit == null) {
setSimulation(null);
} else {
circuit.addObserver(this);
}
setChanged();
getInfo().setCircuitChanged(true);
notifyObserversIfAuto();
}
/**
* Adds a new {@link EditPanelModel} to the opened {@link EditPanelModel}s.
* Notifies all observers.
*
* @param panelModel
* the new {@link EditPanelModel}. Has to be non null.
*/
public void addEditPanelModel(EditPanelModel panelModel) {
assert panelModel != null;
openedEditPanelModels.add(panelModel);
setChanged();
getInfo().setChangedModel(panelModel).setEditPanelModelAdded(true);
notifyObserversIfAuto();
}
/**
* Removes the given {@link EditPanelModel} from the opened models and
* notifies the observers.
*
* @param model
* {@link EditPanelModel} to remove.
*/
public void removeEditPanelModel(EditPanelModel model) {
if (openedEditPanelModels.contains(model)) {
openedEditPanelModels.remove(model);
setChanged();
getInfo().setChangedModel(model).setEditPanelModelRemoved(true);
if (selectedEditPanelModel == model) {
selectedEditPanelModel = null;
getInfo().setChangedModel(model)
.setActiveEditPanelModelChanged(true);
}
notifyObserversIfAuto();
}
}
/**
* Returns the simulation command dispatcher of this project.
*
* @return the simulation command dispatcher of this project.
*/
public CommandDispatcher getSimulationCommandDispatcher() {
return simulationCommandDispatcher;
}
/**
* Returns the graph command dispatcher of this project.
*
* @return the graph command dispatcher of this project.
*/
public CommandDispatcher getGraphCommandDispatcher() {
return graphCommandDispatcher;
}
@Override
public String toString() {
return name;
}
/**
* Sets the ghosts which should be marked erroneous.
*
* @param ghosts the error ghosts, can be null
*/
public void setErrorGhosts(Set<Element> ghosts) {
this.errorGhosts = ghosts;
}
/**
* Get the ghosts set with {@link #setErrorGhosts(Set)}.
*
* @return the error ghosts
*/
public Set<Element> getErrorGhosts() {
return errorGhosts;
}
/**
* Returns the value set by {@link #setModified(boolean)}.
*
* @return true or false
*/
public boolean isModified() {
return modified;
}
/**
* Set to true if the Project is modified. Will lead to save questions, etc.
*
* @param modified true or false.
*/
public void setModified(boolean modified) {
this.modified = modified;
setChanged();
getInfo().setModified(true);
notifyObserversIfAuto();
}
@Override
public void graphModelChanged(Circuit source, GraphModelInfo i) {
setModified(true);
}
}