/* LanguageTool, a natural language style checker
* Copyright (C) 2005 Daniel Naber (http://www.danielnaber.de)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
* USA
*/
package org.languagetool.gui;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.ResourceBundle;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.ImageIcon;
import javax.swing.InputMap;
import javax.swing.KeyStroke;
import javax.swing.event.UndoableEditEvent;
import javax.swing.event.UndoableEditListener;
import javax.swing.text.JTextComponent;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.CannotUndoException;
import javax.swing.undo.CompoundEdit;
import javax.swing.undo.UndoManager;
import org.languagetool.JLanguageTool;
/**
* Provides Undo/Redo support and actions for JTextComponent
*
* @author Panagiotis Minos
*/
class UndoRedoSupport {
final UndoAction undoAction;
final RedoAction redoAction;
private final UndoManager undoManager;
private final ResourceBundle messages;
private boolean compoundMode = false;
private CompoundEdit ce = null;
UndoRedoSupport(JTextComponent textComponent, ResourceBundle messages) {
this.messages = messages;
undoManager = new UndoManager();
undoAction = new UndoAction();
redoAction = new RedoAction();
textComponent.getDocument().addUndoableEditListener(new UndoableEditListener() {
@Override
public void undoableEditHappened(UndoableEditEvent e) {
if(compoundMode) {
ce.addEdit(e.getEdit());
} else {
undoManager.addEdit(e.getEdit());
}
undoAction.updateUndoState();
redoAction.updateRedoState();
}
});
InputMap inputMap = textComponent.getInputMap();
KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_Z,
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
inputMap.put(key, "undo");
textComponent.getActionMap().put("undo", undoAction);
key = KeyStroke.getKeyStroke(KeyEvent.VK_Z,
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | java.awt.event.InputEvent.SHIFT_DOWN_MASK);
inputMap.put(key, "redo");
textComponent.getActionMap().put("redo", redoAction);
}
/**
* Notify manager to start merging undoable edits.
*
* Calling startCompoundEdit when already in compound mode is an error
* and will throw a RuntimeException.
*
* @since 2.7
*/
void startCompoundEdit()
{
if(compoundMode) {
throw new RuntimeException("already in compound mode");
}
ce = new CompoundEdit();
compoundMode = true;
}
/**
* Notify manager to stop merging undoable edits.
*
* Calling endCompoundEdit when not in compound mode is an error
* and will throw a RuntimeException.
*
* @since 2.7
*/
void endCompoundEdit()
{
if(!compoundMode) {
throw new RuntimeException("not in compound mode");
}
ce.end();
undoManager.addEdit(ce);
ce = null;
compoundMode = false;
}
class UndoAction extends AbstractAction {
private UndoAction() {
super(messages.getString("guiUndo"));
Image img;
img = Toolkit.getDefaultToolkit().getImage(
JLanguageTool.getDataBroker().getFromResourceDirAsUrl("sc_undo.png"));
putValue(Action.SMALL_ICON, new ImageIcon(img));
img = Toolkit.getDefaultToolkit().getImage(
JLanguageTool.getDataBroker().getFromResourceDirAsUrl("lc_undo.png"));
putValue(Action.LARGE_ICON_KEY, new ImageIcon(img));
KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_Z,
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
putValue(Action.ACCELERATOR_KEY, key);
putValue(Action.MNEMONIC_KEY, KeyEvent.VK_U);
setEnabled(false);
}
@Override
public void actionPerformed(ActionEvent e) {
try {
undoManager.undo();
} catch (CannotUndoException ex) {
// ignore
}
updateUndoState();
redoAction.updateRedoState();
}
private void updateUndoState() {
if (undoManager.canUndo()) {
setEnabled(true);
} else {
setEnabled(false);
}
}
}
class RedoAction extends AbstractAction {
private RedoAction() {
super(messages.getString("guiRedo"));
Image img;
img = Toolkit.getDefaultToolkit().getImage(
JLanguageTool.getDataBroker().getFromResourceDirAsUrl("sc_redo.png"));
putValue(Action.SMALL_ICON, new ImageIcon(img));
img = Toolkit.getDefaultToolkit().getImage(
JLanguageTool.getDataBroker().getFromResourceDirAsUrl("lc_redo.png"));
putValue(Action.LARGE_ICON_KEY, new ImageIcon(img));
KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_Z,
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | java.awt.event.InputEvent.SHIFT_DOWN_MASK);
putValue(Action.ACCELERATOR_KEY, key);
putValue(Action.MNEMONIC_KEY, KeyEvent.VK_R);
setEnabled(false);
}
@Override
public void actionPerformed(ActionEvent e) {
try {
undoManager.redo();
} catch (CannotRedoException ex) {
// ignore
}
updateRedoState();
undoAction.updateUndoState();
}
private void updateRedoState() {
if (undoManager.canRedo()) {
setEnabled(true);
} else {
setEnabled(false);
}
}
}
}