From 9242f3439c09ef2632e74afb82ca85dd93fb7570 Mon Sep 17 00:00:00 2001 From: drdev Date: Sun, 17 Nov 2013 21:17:14 +0000 Subject: [PATCH] Create FTextEditor to encapsulate a plain text editor with undo/redo support --- .gitattributes | 1 + .../java/forge/gui/toolbox/FTextEditor.java | 161 ++++++++++++++++++ .../gui/workshop/controllers/CCardScript.java | 15 +- .../forge/gui/workshop/views/VCardScript.java | 25 +-- 4 files changed, 175 insertions(+), 27 deletions(-) create mode 100644 forge-gui/src/main/java/forge/gui/toolbox/FTextEditor.java diff --git a/.gitattributes b/.gitattributes index c94f3427c16..e569c711c60 100644 --- a/.gitattributes +++ b/.gitattributes @@ -15412,6 +15412,7 @@ forge-gui/src/main/java/forge/gui/toolbox/FScrollPanel.java -text forge-gui/src/main/java/forge/gui/toolbox/FSkin.java -text forge-gui/src/main/java/forge/gui/toolbox/FTabbedPane.java -text forge-gui/src/main/java/forge/gui/toolbox/FTextArea.java -text +forge-gui/src/main/java/forge/gui/toolbox/FTextEditor.java -text forge-gui/src/main/java/forge/gui/toolbox/FTextField.java -text forge-gui/src/main/java/forge/gui/toolbox/LayoutHelper.java -text forge-gui/src/main/java/forge/gui/toolbox/SaveOpenDialog.java -text diff --git a/forge-gui/src/main/java/forge/gui/toolbox/FTextEditor.java b/forge-gui/src/main/java/forge/gui/toolbox/FTextEditor.java new file mode 100644 index 00000000000..df04dd21226 --- /dev/null +++ b/forge-gui/src/main/java/forge/gui/toolbox/FTextEditor.java @@ -0,0 +1,161 @@ +package forge.gui.toolbox; + +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.event.DocumentListener; +import javax.swing.event.UndoableEditEvent; +import javax.swing.event.UndoableEditListener; +import javax.swing.undo.CannotRedoException; +import javax.swing.undo.CannotUndoException; +import javax.swing.undo.UndoManager; + +@SuppressWarnings("serial") +public class FTextEditor extends JScrollPane { + private final JTextArea tarEditor; + + public FTextEditor() { + tarEditor = new JTextArea(); + FSkin.JTextComponentSkin skin = FSkin.get(tarEditor); + skin.setFont(FSkin.getFixedFont(16)); + skin.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); + skin.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2)); + skin.setCaretColor(FSkin.getColor(FSkin.Colors.CLR_TEXT)); + + tarEditor.setMargin(new Insets(3, 3, 3, 3)); + tarEditor.getDocument().addUndoableEditListener(new MyUndoableEditListener()); + tarEditor.addKeyListener(new KeyAdapter() { + @Override + public void keyPressed(KeyEvent e) { + if (e.isControlDown() && !e.isMetaDown()) { + switch (e.getKeyCode()) { + case KeyEvent.VK_Z: + if (e.isShiftDown()) { + redoAction.actionPerformed(null); + } + else { + undoAction.actionPerformed(null); + } + break; + case KeyEvent.VK_Y: + if (!e.isShiftDown()) { + redoAction.actionPerformed(null); + } + break; + } + } + } + }); + + this.setViewportView(tarEditor); + this.setBorder(null); + this.setOpaque(false); + } + + //Mapped functions to JTextArea + @Override + public boolean isEnabled() { + return tarEditor.isEnabled(); + } + @Override + public void setEnabled(boolean enabled) { + tarEditor.setEnabled(enabled); + } + public String getText() { + return tarEditor.getText(); + } + public void setText(String t) { + tarEditor.setText(t); + undoManager.discardAllEdits(); + } + public boolean isEditable() { + return tarEditor.isEditable(); + } + public void setEditable(boolean b) { + tarEditor.setEditable(b); + } + public int getCaretPosition() { + return tarEditor.getCaretPosition(); + } + public void setCaretPosition(int position) { + tarEditor.setCaretPosition(position); + } + public void addDocumentListener(DocumentListener listener) { + tarEditor.getDocument().addDocumentListener(listener); + } + + //Undo/Redo + private UndoAction undoAction = new UndoAction(); + private RedoAction redoAction = new RedoAction(); + private UndoManager undoManager = new UndoManager(); + + private class MyUndoableEditListener implements UndoableEditListener { + public void undoableEditHappened(UndoableEditEvent e) { + undoManager.addEdit(e.getEdit()); + undoAction.updateUndoState(); + redoAction.updateRedoState(); + } + } + + private class UndoAction extends AbstractAction { + public UndoAction() { + super("Undo"); + setEnabled(false); + } + + public void actionPerformed(ActionEvent e) { + try { + undoManager.undo(); + } catch (CannotUndoException ex) { + System.out.println("Unable to undo: " + ex); + ex.printStackTrace(); + } + updateUndoState(); + redoAction.updateRedoState(); + } + + protected void updateUndoState() { + if (undoManager.canUndo()) { + setEnabled(true); + putValue(Action.NAME, undoManager.getUndoPresentationName()); + } else { + setEnabled(false); + putValue(Action.NAME, "Undo"); + } + } + } + + private class RedoAction extends AbstractAction { + public RedoAction() { + super("Redo"); + setEnabled(false); + } + + public void actionPerformed(ActionEvent e) { + try { + undoManager.redo(); + } catch (CannotRedoException ex) { + System.out.println("Unable to redo: " + ex); + ex.printStackTrace(); + } + updateRedoState(); + undoAction.updateUndoState(); + } + + protected void updateRedoState() { + if (undoManager.canRedo()) { + setEnabled(true); + putValue(Action.NAME, undoManager.getRedoPresentationName()); + } else { + setEnabled(false); + putValue(Action.NAME, "Redo"); + } + } + } +} diff --git a/forge-gui/src/main/java/forge/gui/workshop/controllers/CCardScript.java b/forge-gui/src/main/java/forge/gui/workshop/controllers/CCardScript.java index 13e5b82b658..9a8c419d17e 100644 --- a/forge-gui/src/main/java/forge/gui/workshop/controllers/CCardScript.java +++ b/forge-gui/src/main/java/forge/gui/workshop/controllers/CCardScript.java @@ -12,6 +12,7 @@ import forge.Command; import forge.Singletons; import forge.gui.framework.FScreen; import forge.gui.framework.ICDoc; +import forge.gui.toolbox.FTextEditor; import forge.gui.workshop.menus.WorkshopFileMenu; import forge.gui.workshop.views.VCardDesigner; import forge.gui.workshop.views.VCardScript; @@ -35,7 +36,7 @@ public enum CCardScript implements ICDoc { private boolean isTextDirty; private CCardScript() { - VCardScript.SINGLETON_INSTANCE.getTarScript().getDocument().addDocumentListener(new DocumentListener() { + VCardScript.SINGLETON_INSTANCE.getTxtScript().addDocumentListener(new DocumentListener() { @Override public void removeUpdate(DocumentEvent arg0) { updateDirtyFlag(); @@ -54,7 +55,7 @@ public enum CCardScript implements ICDoc { } private void updateDirtyFlag() { - boolean isTextNowDirty = !VCardScript.SINGLETON_INSTANCE.getTarScript().getText().equals(baseText); + boolean isTextNowDirty = !VCardScript.SINGLETON_INSTANCE.getTxtScript().getText().equals(baseText); if (this.isTextDirty == isTextNowDirty) { return; } this.isTextDirty = isTextNowDirty; VCardDesigner.SINGLETON_INSTANCE.getBtnSaveCard().setEnabled(isTextNowDirty); @@ -94,10 +95,10 @@ public enum CCardScript implements ICDoc { } this.baseText = text; - JTextArea tarScript = VCardScript.SINGLETON_INSTANCE.getTarScript(); - tarScript.setText(text); - tarScript.setEditable(editable); - tarScript.setCaretPosition(0); //keep scrolled to top + FTextEditor txtScript = VCardScript.SINGLETON_INSTANCE.getTxtScript(); + txtScript.setText(text); + txtScript.setEditable(editable); + txtScript.setCaretPosition(0); //keep scrolled to top } public boolean hasChanges() { @@ -131,7 +132,7 @@ public enum CCardScript implements ICDoc { if (sourceFile == null) { return true; } try { - String text = VCardScript.SINGLETON_INSTANCE.getTarScript().getText(); + String text = VCardScript.SINGLETON_INSTANCE.getTxtScript().getText(); PrintWriter p = new PrintWriter(sourceFile); p.print(text); diff --git a/forge-gui/src/main/java/forge/gui/workshop/views/VCardScript.java b/forge-gui/src/main/java/forge/gui/workshop/views/VCardScript.java index fb42e74a99a..2cd4deb7148 100644 --- a/forge-gui/src/main/java/forge/gui/workshop/views/VCardScript.java +++ b/forge-gui/src/main/java/forge/gui/workshop/views/VCardScript.java @@ -1,16 +1,12 @@ package forge.gui.workshop.views; -import java.awt.Insets; - import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JTextArea; import net.miginfocom.swing.MigLayout; import forge.gui.framework.DragCell; import forge.gui.framework.DragTab; import forge.gui.framework.EDocID; import forge.gui.framework.IVDoc; -import forge.gui.toolbox.FSkin; +import forge.gui.toolbox.FTextEditor; import forge.gui.workshop.controllers.CCardScript; /** @@ -26,25 +22,14 @@ public enum VCardScript implements IVDoc { private DragCell parentCell; private final DragTab tab = new DragTab("Card Script"); - private final JTextArea tarScript = new JTextArea(); - private final JScrollPane scroller; + private final FTextEditor txtScript = new FTextEditor(); //========== Constructor private VCardScript() { - FSkin.JTextComponentSkin txtScriptSkin = FSkin.get(tarScript); - txtScriptSkin.setFont(FSkin.getFixedFont(16)); - txtScriptSkin.setForeground(FSkin.getColor(FSkin.Colors.CLR_TEXT)); - txtScriptSkin.setBackground(FSkin.getColor(FSkin.Colors.CLR_THEME2)); - txtScriptSkin.setCaretColor(FSkin.getColor(FSkin.Colors.CLR_TEXT)); - tarScript.setMargin(new Insets(3, 3, 3, 3)); - - scroller = new JScrollPane(tarScript); - scroller.setBorder(null); - scroller.setOpaque(false); } - public JTextArea getTarScript() { - return tarScript; + public FTextEditor getTxtScript() { + return txtScript; } //========== Overridden methods @@ -96,6 +81,6 @@ public enum VCardScript implements IVDoc { public void populate() { JPanel body = parentCell.getBody(); body.setLayout(new MigLayout("insets 1, gap 0, wrap")); - body.add(scroller, "w 100%, h 100%"); + body.add(txtScript, "w 100%, h 100%"); } }