/*
* Copyright (c) 2011 Patrick Meyer
*
* 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 com.itemanalysis.jmetrik.swing;
import com.itemanalysis.jmetrik.utils.JmetrikFileUtils;
import com.itemanalysis.jmetrik.workspace.FileOpener;
import com.itemanalysis.jmetrik.workspace.FileSaver;
import com.itemanalysis.jmetrik.workspace.JmetrikPreferencesManager;
import org.apache.log4j.Logger;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.*;
import javax.swing.text.Document;
import javax.swing.undo.CannotRedoException;
import javax.swing.undo.UndoManager;
import java.awt.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.io.*;
import java.util.Formatter;
public class JmetrikTextFile extends JTextArea{
protected File f = null;
final UndoManager undoer;
private Document doc;
private JmetrikPreferencesManager p = null;
private boolean unsavedChanges = false;
private static final String USER_HOME = System.getProperty("user.home").replaceAll("\\\\", "/");
static Logger logger = Logger.getLogger("jmetrik-logger");
protected Action undoAction, redoAction;
public JmetrikTextFile(){
setBorder(new EmptyBorder(5,5,5,5));
setBackground(Color.WHITE);
initializeFont();
undoer = new UndoManager();
doc = getDocument();
doc.addDocumentListener(new UpdateListener());
doc.addUndoableEditListener(new Undoer());
}
/**
* Font obtained from jmetrik preferences
*/
private void initializeFont(){
p = new JmetrikPreferencesManager();
Font font = p.getFont();
setFont(font);
}
public void fileSave(){
if(f!=null){
FileSaver fileSaver = new FileSaver(f, this);
PropertyChangeListener[] pcl = this.getPropertyChangeListeners();
for(PropertyChangeListener p :pcl){
fileSaver.addPropertyChangeListener(p);
}
fileSaver.addPropertyChangeListener(new FileSavedListener());
fileSaver.execute();
}
}
public void fileSave(JmetrikTab tab){
if(f!=null){
FileSaver fileSaver = new FileSaver(f, this, tab);
PropertyChangeListener[] pcl = this.getPropertyChangeListeners();
for(PropertyChangeListener p :pcl){
fileSaver.addPropertyChangeListener(p);
}
fileSaver.addPropertyChangeListener(new FileSavedListener());
fileSaver.execute();
}
}
public void fileSave(File f){
this.f = f;
FileSaver fileSaver = new FileSaver(f, this);
PropertyChangeListener[] pcl = this.getPropertyChangeListeners();
for(PropertyChangeListener p :pcl){
fileSaver.addPropertyChangeListener(p);
}
fileSaver.addPropertyChangeListener(new FileSavedListener());
fileSaver.execute();
}
public void fileSave(File f, JmetrikTab tab){
this.f = f;
FileSaver fileSaver = new FileSaver(f, this, tab);
PropertyChangeListener[] pcl = this.getPropertyChangeListeners();
for(PropertyChangeListener p :pcl){
fileSaver.addPropertyChangeListener(p);
}
fileSaver.addPropertyChangeListener(new FileSavedListener());
fileSaver.execute();
}
public void openFile(final File f){
this.f = f;
FileOpener fileOpener = new FileOpener(f, this);
PropertyChangeListener[] pcl = this.getPropertyChangeListeners();
for(PropertyChangeListener p :pcl){
fileOpener.addPropertyChangeListener(p);
}
fileOpener.execute();
}
public Document getTextFileDocument(){
doc = getDocument();
return doc;
}
public boolean hasFile(){
return f!=null;
}
/*
* Method for adding a String object to the TextFile. User's will
* be able to edit the JTextArea directly. This method is for, say,
* adding the contents of one file or the output of a method
* to this file.
*
* aStringToAdd - String to be added to TextFile
*/
public void addText(String aStringToAdd){
append(aStringToAdd);
}
/*
* Method for adding a Formatter object to the TextFile. User's will
* be able to edit the JTextArea directly. This method is for, say,
* adding the contents of one file or the output of a method
* to this file.
*
* aFormatterToAdd - a Formatter object to be added to TextFile
*/
public void addText(Formatter aFormatterToAdd){
append(aFormatterToAdd.toString());
}
/*
* Returns the file name if teh file has been created.
* Otherwise a blank file name is returned.
*/
public String getFileName(){
if(f==null) return "text file";
return f.getName();
}
public File getFile(){
return f;
}
// public void setFile(File f){
// this.f = f;
// }
public boolean canUndo(){
return undoer.canUndo();
}
public boolean canRedo(){
return undoer.canRedo();
}
public void undoText(){
try{
undoer.undo();
}catch(CannotRedoException ex){
logger.fatal(ex.getMessage(), ex);
this.firePropertyChange("error", null, "Error - Check log for details.");
}
}
public void redoText(){
try{
undoer.redo();
}catch(CannotRedoException ex){
logger.fatal(ex.getMessage(), ex);
this.firePropertyChange("error", null, "Error - Check log for details.");
}
}
public int promptToSave(Component parent){
int result = -1;
if(unsavedChanges){
String fileName = this.getFileName();
result = JOptionPane.showConfirmDialog(parent,
"Save changes to " + fileName + " before closing tab?",
"Save Changes",
JOptionPane.YES_NO_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE);
if(result==JOptionPane.YES_OPTION){
if(f==null){
JmetrikFileUtils fUtils = new JmetrikFileUtils();
f = fUtils.chooseFileToSave(parent, new File(USER_HOME));
if(f==null) return JOptionPane.CANCEL_OPTION;
}
fileSave();
}
}else{
result = JOptionPane.YES_OPTION;
}
return result;
}
class UpdateListener implements DocumentListener {
public void insertUpdate(DocumentEvent e){
unsavedChanges = true;
}
public void removeUpdate(DocumentEvent e){
unsavedChanges = true;
}
public void changedUpdate(DocumentEvent e){
unsavedChanges = true;
}
}
class Undoer implements UndoableEditListener {
public Undoer(){
undoer.die();
}
public void undoableEditHappened(UndoableEditEvent e){
undoer.addEdit(e.getEdit());
}
}
class FileSavedListener implements PropertyChangeListener{
public void propertyChange(PropertyChangeEvent evt){
if("file-saved".equals(evt.getPropertyName())){
unsavedChanges = false;
}
}
}
}