/*
* WPCleaner: A tool to help on Wikipedia maintenance tasks.
* Copyright (C) 2013 Nicolas Vervelle
*
* See README.txt file for licensing information.
*/
package org.wikipediacleaner.gui.swing.component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.LinkedList;
import javax.swing.JButton;
/**
* Manage Undo/Redo operations on MWPane.
*/
public class MWPaneUndoManager implements ActionListener {
/**
* MWPane.
*/
private final MWPane textPane;
MWPaneUndoManager(MWPane textPane) {
this.textPane = textPane;
this.undoLevels = 0;
this.undoTexts = new LinkedList<String>();
this.redoTexts = new LinkedList<String>();
}
/* ======================================================================= */
/* UNDO levels */
/* ======================================================================= */
/**
* Maximum number of Undo levels.
*/
private int undoLevels;
/**
* @param levels Number of undo levels.
*/
public void setUndoLevels(int levels) {
this.undoLevels = levels;
}
/* ======================================================================= */
/* Text management */
/* ======================================================================= */
/**
* Previous texts for Undo.
*/
private LinkedList<String> undoTexts;
/**
* Previous texts for Redo.
*/
private LinkedList<String> redoTexts;
/**
* Clear Undo/Redo texts.
*/
void clear() {
undoTexts.clear();
redoTexts.clear();
}
/* ======================================================================= */
/* Action management */
/* ======================================================================= */
/**
* Undo action.
*/
private final static String ACTION_UNDO = "UNDO";
/**
* Redo action.
*/
private final static String ACTION_REDO = "REDO";
/**
* Memorize current text for undo / redo.
*/
void validateCurrentText() {
if (undoLevels <= 0) {
return;
}
// Check if memorizing text is useful
String currentText = textPane.getText();
if (!undoTexts.isEmpty() && currentText.equals(undoTexts.getLast())) {
return;
}
// Adding text
undoTexts.addLast(currentText);
while (undoTexts.size() > undoLevels) {
undoTexts.removeFirst();
}
redoTexts.clear();
updateUndoButtons();
}
/**
* Undo last change.
*/
private void undo() {
if (undoTexts.isEmpty()) {
return;
}
String newText = undoTexts.getLast();
String oldText = textPane.getText();
if (oldText.equals(newText)) {
if (undoTexts.size() < 1) {
return;
}
undoTexts.removeLast();
if (undoTexts.isEmpty()) {
return;
}
newText = undoTexts.getLast();
}
undoTexts.removeLast();
redoTexts.addLast(oldText);
textPane.changeText(newText);
updateUndoButtons();
}
/**
* Redo last change.
*/
private void redo() {
if (redoTexts.isEmpty()) {
return;
}
String newText = redoTexts.getLast();
String oldText = textPane.getText();
if (oldText.equals(newText)) {
if (redoTexts.size() < 1) {
return;
}
redoTexts.removeLast();
newText = redoTexts.getLast();
}
redoTexts.removeLast();
undoTexts.addLast(oldText);
textPane.changeText(newText);
updateUndoButtons();
}
/**
* @param e Event.
* @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent)
*/
@Override
public void actionPerformed(ActionEvent e) {
if ((e == null) || (e.getActionCommand() == null)) {
return;
}
if (e.getActionCommand().equals(ACTION_UNDO)) {
undo();
} else if (e.getActionCommand().equals(ACTION_REDO)) {
redo();
}
}
/* ======================================================================= */
/* Buttons management */
/* ======================================================================= */
/**
* Undo button.
*/
private JButton undoButton;
/**
* Redo button.
*/
private JButton redoButton;
/**
* Update status of Undo / Redo buttons.
*/
void updateUndoButtons() {
if (undoButton != null) {
undoButton.setEnabled(!undoTexts.isEmpty() && textPane.isModified());
}
if (redoButton != null) {
redoButton.setEnabled(!redoTexts.isEmpty());
}
}
/**
* @param undo Undo button.
*/
public void setUndoButton(JButton undo) {
if (undoButton != null) {
undoButton.removeActionListener(this);
}
undoButton = undo;
if (undoButton != null) {
undoButton.setActionCommand(ACTION_UNDO);
undoButton.addActionListener(this);
}
updateUndoButtons();
}
/**
* @param redo Redo button.
*/
public void setRedoButton(JButton redo) {
if (redoButton != null) {
redoButton.removeActionListener(this);
}
redoButton = redo;
if (redoButton != null) {
redoButton.setActionCommand(ACTION_REDO);
redoButton.addActionListener(this);
}
updateUndoButtons();
}
}