/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
Copyright (C) 2011-2013 Marchand Eric <ricoh51@free.fr>
This file is part of Freegressi.
Freegressi 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.
Freegressi 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 Freegressi. If not, see <http://www.gnu.org/licenses/>.
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
package freegressi.main;
import freegressi.graphics.GraphicModel.GraphicChangedEvent;
import freegressi.graphics.GraphicModel.GraphicListener;
import freegressi.graphics.GraphicModel.GraphicSizeChangedEvent;
import freegressi.graphics.GraphicModel.GraphicStyleChangedEvent;
import freegressi.main.MainModel.ApplicationSeFermeEvent;
import freegressi.main.MainModel.FichierOuvertEvent;
import freegressi.main.MainModel.MainListener;
import freegressi.main.MainModel.NouveauExperienceEvent;
import freegressi.main.MainModel.SaveEvent;
import freegressi.tableur.SpreadSheets.ActiveSheetChangedEvent;
import freegressi.tableur.SpreadSheets.SheetAddedEvent;
import freegressi.tableur.SpreadSheets.SheetDeletedEvent;
import freegressi.tableur.SpreadSheets.SheetDescriptionChangedEvent;
import freegressi.tableur.SpreadSheets.SheetsAngleChangedEvent;
import freegressi.tableur.SpreadSheets.SheetsCSChangedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnAddedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnDeletedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnModifiedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnMovedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnSortedEvent;
import freegressi.tableur.SpreadSheets.SheetsColumnsEditedEvent;
import freegressi.tableur.SpreadSheets.SheetsListener;
import freegressi.tableur.SpreadSheets.SheetsRenamedEvent;
import freegressi.tableur.Tableur.SheetCellChangedEvent;
import freegressi.tableur.Tableur.SheetLinesAddedEvent;
import freegressi.tableur.Tableur.SheetLinesDeletedEvent;
import freegressi.tableur.Tableur.TableurChangeListener;
import freegressi.fit.FitListener;
import freegressi.fit.FitModel;
import freegressi.fit.FitModel.TendanceChangedEvent;
import freegressi.fit.FitModel.TendanceCreatedEvent;
import freegressi.fit.FitModel.TendanceDeletedEvent;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.EventObject;
import java.util.List;
import javax.swing.event.EventListenerList;
/**
* La classe qui s'occupe des undo et redo. C'est un singleton, elle est à l'écoute
* des tableurs, du SpreadSheet, du tendanceModel, du graphicModel et du MainModel
* @author marchand
*/
public class UndoRedo implements TableurChangeListener,
FitListener, MainListener, SheetsListener, GraphicListener {
private List<Object> liste = new ArrayList<>();
private int index = -1;
private static UndoRedo undoRedo;
/** La liste des écouteurs */
private EventListenerList listeners = new EventListenerList();
/** Event qui correspond au dernier état sauvé */
private Object objectSaved;
//private final static Logger LOGGER = Logger.getLogger(UndoRedo.class.getName());
/**
* Constructeur privé pour singleton
*/
private UndoRedo() {
}
/**
* Return l'instance du singleton
* @return
*/
public static UndoRedo getInstance() {
if (undoRedo == null) {
undoRedo = new UndoRedo();
}
return undoRedo;
}
/**
* Réinitialise les undo redo lors de l'ouverture d'un fichier par exemple
*/
public void clear() {
liste.clear();
index = -1;
fireUndoRedoChange();
}
private String getTexte(Object object) {
if (object instanceof FreegressiEvent){
FreegressiEvent e = (FreegressiEvent) object;
return e.getText();
} else if (object instanceof TendanceCreatedEvent) {
TendanceCreatedEvent e = (TendanceCreatedEvent) object;
return e.getTexte();
} else if (object instanceof TendanceDeletedEvent) {
TendanceDeletedEvent e = (TendanceDeletedEvent) object;
return e.getTexte();
} else if (object instanceof TendanceChangedEvent) {
TendanceChangedEvent e = (TendanceChangedEvent) object;
return e.getTexte();
} else {
return "";
}
}
private String getNextUndo() {
if (!undoPossible()) {
return "";
}
Object object = liste.get(index);
return getTexte(object);
}
private String getNextRedo() {
if (!redoPossible()) {
return "";
}
Object object = liste.get(index + 1);
return getTexte(object);
}
public void undo() {
if (!undoPossible()) {
return;
}
Object object = liste.get(index);
index--;
if (object instanceof FreegressiEvent){
FreegressiEvent e = (FreegressiEvent) object;
e.undo();
} else if (object instanceof TendanceCreatedEvent) {
TendanceCreatedEvent e = (TendanceCreatedEvent) object;
FitModel.getInstance().undoRegressionAdded(e);
} else if (object instanceof TendanceDeletedEvent) {
TendanceDeletedEvent e = (TendanceDeletedEvent) object;
FitModel.getInstance().undoRegressionDeleted(e);
} else if (object instanceof TendanceChangedEvent) {
TendanceChangedEvent e = (TendanceChangedEvent) object;
FitModel.getInstance().undoRegressionChanged(e);
}
fireUndoRedoChange();
}
public void redo() {
if (!redoPossible()) {
return;
}
index++;
Object object = liste.get(index);
if (object instanceof FreegressiEvent){
FreegressiEvent e = (FreegressiEvent) object;
e.redo();
} else if (object instanceof TendanceCreatedEvent) {
TendanceCreatedEvent e = (TendanceCreatedEvent) object;
FitModel.getInstance().redoRegressionAdded(e);
} else if (object instanceof TendanceDeletedEvent) {
TendanceDeletedEvent e = (TendanceDeletedEvent) object;
FitModel.getInstance().redoRegressionDeleted(e);
} else if (object instanceof TendanceChangedEvent) {
TendanceChangedEvent e = (TendanceChangedEvent) object;
FitModel.getInstance().redoRegressionChanged(e);
}
fireUndoRedoChange();
}
private boolean undoPossible() {
return index > -1;
}
private boolean redoPossible() {
return index < liste.size() - 1;
}
private void printStatus(){
int i = -1;
for (Object object: liste){
i++;
if (i == index){
System.out.print("*****");
}
System.out.println(getTexte(object));
}
}
/**
* Ajoute l'object (correspondant à un evenement tableur, tendance ou graphique)
* à la liste. S'il y a des évenements après "index", ceux ci sont éffacés
* @param object l'évenement à ajouter
*/
private void ajoute(Object object) {
//LOGGER.info(((FreegressiEvent)object).getText());
// supprimer les éléments suivants
if (index != liste.size() - 1) {
for (int i = liste.size() - 1; i > index; i--) {
liste.remove(i);
}
}
// ajouter cet evenement
liste.add(object);
index++;
fireUndoRedoChange();
}
@Override
public void sheetCellChanged(SheetCellChangedEvent event) {
if (event.isUndoable()) {
ajoute(event);
}
}
@Override
public void sheetLinesAdded(SheetLinesAddedEvent event) {
if (event.isUndoable()) {
ajoute(event);
}
}
@Override
public void sheetLinesDeleted(SheetLinesDeletedEvent event) {
if (event.isUndoable()) {
ajoute(event);
}
}
@Override
public void tendanceChanged(TendanceChangedEvent event) {
if (event.isUndoable())
ajoute(event);
}
@Override
public void tendanceCreated(TendanceCreatedEvent event) {
if (event.isUndoable())
ajoute(event);
}
@Override
public void tendanceDeleted(TendanceDeletedEvent event) {
if (event.isUndoable())
ajoute(event);
}
@Override
public void fichierOuvert(FichierOuvertEvent event) {
clear();
fireUndoRedoChange();
}
@Override
public void applicationFermee(ApplicationSeFermeEvent event) {
}
@Override
public void nouveauExperience(NouveauExperienceEvent event) {
clear();
fireUndoRedoChange();
}
@Override
public void mainSave(SaveEvent event) {
if (index > -1){
objectSaved = liste.get(index);
}
fireUndoRedoChange();
}
@Override
public void activeSheetChanged(ActiveSheetChangedEvent event) {
}
@Override
public void sheetAdded(SheetAddedEvent event) {
if (event.isUndoable()) {
ajoute(event);
}
}
@Override
public void sheetDeleted(SheetDeletedEvent event) {
if (event.isUndoable()) {
ajoute(event);
}
}
@Override
public void columnAdded(SheetsColumnAddedEvent event) {
if (event.isUndoable()) {
ajoute(event);
}
}
@Override
public void columnDeleted(SheetsColumnDeletedEvent event) {
if (event.isUndoable()) {
ajoute(event);
}
}
@Override
public void sheetRenamed(SheetsRenamedEvent event) {
if (event.isUndoable()) {
ajoute(event);
}
}
@Override
public void angleChanged(SheetsAngleChangedEvent event) {
if (event.isUndoable()) {
ajoute(event);
}
}
@Override
public void columnModified(SheetsColumnModifiedEvent event) {
if (event.isUndoable()) {
ajoute(event);
}
}
@Override
public void columnSorted(SheetsColumnSortedEvent event) {
if (event.isUndoable()) {
ajoute(event);
}
}
@Override
public void columnMoved(SheetsColumnMovedEvent event) {
if (event.isUndoable()) {
ajoute(event);
}
}
@Override
public void columnsEdited(SheetsColumnsEditedEvent event) {
if (event.isUndoable()) {
ajoute(event);
}
}
@Override
public void sheetDescriptionChanged(SheetDescriptionChangedEvent event) {
if (event.isUndoable()) {
ajoute(event);
}
}
@Override
public void sheetsCSChanged(SheetsCSChangedEvent event) {
if (event.isUndoable()) {
ajoute(event);
}
}
@Override
public void graphicSizeChanged(GraphicSizeChangedEvent event) {
}
@Override
public void graphicChanged(GraphicChangedEvent event) {
}
@Override
public void graphicStyleChanged(GraphicStyleChangedEvent event) {
if (event.isUndoable()) {
ajoute(event);
}
}
public interface UndoRedoListener extends EventListener {
public void undoredoChange(UndoRedoEvent event);
}
/**
* Classe qui définit l'évenement "l'état des undo redo a changé"
*/
public class UndoRedoEvent extends EventObject {
public UndoRedoEvent(Object source) {
super(source);
}
public String getTexteNextUndo() {
return getNextUndo();
}
public String getTexteNextRedo() {
return getNextRedo();
}
public boolean isUndoPossible() {
return undoPossible();
}
public boolean isRedoPossible() {
return redoPossible();
}
public boolean isFileSaved(){
if (index > -1){
return objectSaved == liste.get(index);
} else {
return true;
}
}
}
/**
* Ajoute un écouteur à la liste
* @param listener l'écouteur à ajouter
*/
public final void addUndoRedoListener(UndoRedoListener listener) {
listeners.add(UndoRedoListener.class, listener);
}
/**
* Retire un écouteur de la liste
* @param listener l'écouteur à retirer
*/
public void removeUndoRedoListener(UndoRedoListener listener) {
listeners.remove(UndoRedoListener.class, listener);
}
/**
* Appelée par cette classe pour informer les écouteurs
*/
private void fireUndoRedoChange() {
UndoRedoEvent event = new UndoRedoEvent(this);
UndoRedoListener[] listenerListe = (UndoRedoListener[]) listeners.getListeners(UndoRedoListener.class);
for (UndoRedoListener listener : listenerListe) {
listener.undoredoChange(event);
}
//printStatus();
// System.out.println(SpreadSheets.getInstance().getActiveSheet().getListNames());
// ArrayList<Colonne> liste = SpreadSheets.getInstance().getActiveSheet().donneListeColonnesDependantes("x");
// for (Colonne col : liste){
// System.out.print(col.getColonneDescription().getNom() + " ");
// }
// System.out.println();
}
}