/*
* The University of Wales, Cardiff Triana Project Software License (Based
* on the Apache Software License Version 1.1)
*
* Copyright (c) 2007 University of Wales, Cardiff. All rights reserved.
*
* Redistribution and use of the software in source and binary forms, with
* or without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The end-user documentation included with the redistribution, if any,
* must include the following acknowledgment: "This product includes
* software developed by the University of Wales, Cardiff for the Triana
* Project (http://www.trianacode.org)." Alternately, this
* acknowledgment may appear in the software itself, if and wherever
* such third-party acknowledgments normally appear.
*
* 4. The names "Triana" and "University of Wales, Cardiff" must not be
* used to endorse or promote products derived from this software
* without prior written permission. For written permission, please
* contact triana@trianacode.org.
*
* 5. Products derived from this software may not be called "Triana," nor
* may Triana appear in their name, without prior written permission of
* the University of Wales, Cardiff.
*
* 6. This software may not be sold, used or incorporated into any product
* for sale to third parties.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL UNIVERSITY OF WALES, CARDIFF OR ITS CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* ------------------------------------------------------------------------
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Triana Project. For more information on the
* Triana Project, please see. http://www.trianacode.org.
*
* This license is based on the BSD license as adopted by the Apache
* Foundation and is governed by the laws of England and Wales.
*
*/
package org.trianacode.gui.action.tools;
import org.trianacode.gui.Display;
import org.trianacode.gui.action.ActionDisplayOptions;
import org.trianacode.gui.action.ToolSelectionHandler;
import org.trianacode.gui.hci.GUIEnv;
import org.trianacode.gui.main.organize.TaskGraphOrganize;
import org.trianacode.gui.panels.ParameterPanel;
import org.trianacode.gui.panels.TFileChooser;
import org.trianacode.gui.util.Env;
import org.trianacode.gui.windows.ParameterWindow;
import org.trianacode.gui.windows.WindowButtonConstants;
import org.trianacode.taskgraph.Task;
import org.trianacode.taskgraph.TaskGraph;
import org.trianacode.taskgraph.clipin.HistoryClipIn;
import org.trianacode.taskgraph.ser.XMLWriter;
import org.trianacode.taskgraph.service.ClipableTaskInterface;
import org.trianacode.taskgraph.service.HistoryTrackerAutoSave;
import org.trianacode.taskgraph.util.FileUtils;
import javax.swing.*;
import javax.swing.filechooser.FileFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
/**
* The action for showing the node editor
*
* @author Ian Wang
* @version $Revision: 4048 $
*/
public class HistoryTrackingAction extends AbstractAction implements ActionDisplayOptions {
private ToolSelectionHandler selhandler;
public HistoryTrackingAction(ToolSelectionHandler sel) {
this.selhandler = sel;
putValue(SHORT_DESCRIPTION, Env.getString("HistoryTrackingTip"));
putValue(ACTION_COMMAND_KEY, Env.getString("HistoryTracking"));
putValue(NAME, Env.getString("HistoryTracking") + "...");
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed(ActionEvent e) {
if (selhandler.isSingleSelectedTool() && (selhandler.getSelectedTool() instanceof Task)) {
showHistoryTrackingDialog((Task) selhandler.getSelectedTool(), e.getSource());
}
}
/**
* Show the history tracking dialog for the specified task
*
* @param source the source object asking for the node editor to be shown
*/
protected void showHistoryTrackingDialog(Task task, Object source) {
ParameterWindow historyWindow = new ParameterWindow(GUIEnv.getApplicationFrame(),
WindowButtonConstants.OK_CANCEL_APPLY_BUTTONS, true);
historyWindow.setTitle(Env.getString("HistoryTracking") + ": " + task.getToolName());
HistoryTrackingPanel historypanel = new HistoryTrackingPanel();
historypanel.setTask(task);
historypanel.init();
historyWindow.setParameterPanel(historypanel);
Point loc = Display.getAnchorPoint(source, historyWindow);
loc.translate(140, 40);
historyWindow.setLocation(loc);
historyWindow.setVisible(true);
historyWindow.requestFocus();
if (historyWindow.isAccepted()) {
task.setParameter(HistoryTrackerAutoSave.AUTO_SAVE, String.valueOf(historypanel.isAutoSave()));
task.setParameter(HistoryTrackerAutoSave.AUTO_SAVE_FILENAME, historypanel.getFileName());
task.setParameter(HistoryTrackerAutoSave.AUTO_SAVE_APPEND,
String.valueOf(historypanel.isAppendSequenceNumber()));
}
}
private class HistoryTrackingPanel extends ParameterPanel implements ActionListener, ItemListener {
private JButton savebutton = new JButton(Env.getString("saveHistoryNow") + "...");
private JCheckBox autosave = new JCheckBox(Env.getString("autoSaveHistory"));
private JTextField filename = new JTextField(25);
private JButton filebrowse = new JButton(GUIEnv.getIcon("dots.png"));
private JCheckBox seqcheck = new JCheckBox();
/**
* Hides the auto commit button
*/
public boolean isAutoCommitVisible() {
return false;
}
/**
* This method returns false by default. It should be overridden if the panel wants parameter changes to be
* commited automatically
*/
public boolean isAutoCommitByDefault() {
return false;
}
/**
* This method returns WindowButtonConstants.OK_CANCEL_APPLY_BUTTONS by default. It should be overridden if the
* panel has different preferred set of buttons.
*
* @return the panels preferred button combination (as defined in Windows Constants).
*/
public byte getPreferredButtons() {
return WindowButtonConstants.OK_CANCEL_BUTTONS;
}
/**
* This method is called when the task is set for this panel. It is overridden to create the panel layout.
*/
public void init() {
setLayout(new BorderLayout(3, 3));
JPanel savepanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
savepanel.add(savebutton);
savebutton.addActionListener(this);
JPanel filepanel = new JPanel(new BorderLayout(3, 0));
filepanel.add(new JLabel("File Name"), BorderLayout.WEST);
filepanel.add(filename, BorderLayout.CENTER);
filepanel.add(filebrowse, BorderLayout.EAST);
filepanel.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 0));
filebrowse.setMargin(new Insets(6, 4, 2, 4));
filebrowse.addActionListener(this);
JPanel seqpanel = new JPanel(new BorderLayout(3, 0));
seqpanel.add(new JLabel("Append Sequence Number"), BorderLayout.WEST);
seqpanel.add(seqcheck, BorderLayout.CENTER);
seqpanel.setBorder(BorderFactory.createEmptyBorder(0, 15, 0, 0));
JPanel autopanel = new JPanel(new BorderLayout(3, 3));
autopanel.add(autosave, BorderLayout.NORTH);
autopanel.add(filepanel, BorderLayout.CENTER);
autopanel.add(seqpanel, BorderLayout.SOUTH);
autosave.addItemListener(this);
filename.setEnabled(autosave.isSelected());
filebrowse.setEnabled(autosave.isSelected());
seqcheck.setEnabled(autosave.isSelected());
add(savepanel, BorderLayout.NORTH);
add(autopanel, BorderLayout.CENTER);
}
/**
* This method is called when the panel is reset or cancelled. It should reset all the panels components to the
* values specified by the associated task, e.g. a component representing a parameter called "noise" should be
* set to the value returned by a getTool().getParameter("noise") call.
*/
public void reset() {
}
/**
* This method is called when the panel is finished with. It should dispose of any components (e.g. windows)
* used by the panel.
*/
public void dispose() {
}
/**
* @return true if auto save is enabled
*/
public boolean isAutoSave() {
return autosave.isSelected();
}
/**
* @return the filename
*/
public String getFileName() {
return filename.getText();
}
/**
* @return true if a sequence number is to be appended
*/
public boolean isAppendSequenceNumber() {
return seqcheck.isSelected();
}
/**
* Pulls up a file panel that allows the user to choose the file that the history is saved in
*/
private void saveHistory(Task task) {
if (!(task instanceof ClipableTaskInterface)) {
JOptionPane.showMessageDialog(GUIEnv.getApplicationFrame(),
"Save Histroy Error: Clipins not implemented for " + task.getToolName(),
"Save Error", JOptionPane.ERROR_MESSAGE, GUIEnv.getTrianaIcon());
return;
}
if (!((ClipableTaskInterface) task).isClipInName(HistoryClipIn.HISTORY_CLIPIN_NAME)) {
JOptionPane.showMessageDialog(GUIEnv.getApplicationFrame(),
"Save Histroy Error: No history information availible, try re-running with history tracking",
"Save Error", JOptionPane.ERROR_MESSAGE, GUIEnv.getTrianaIcon());
return;
}
TFileChooser chooser = new TFileChooser(Env.DATA_DIRECTORY);
chooser.setDialogTitle(task.getToolName() + ": " + Env.getString("saveHistory"));
chooser.setFileFilter(new XMLFileFilter());
if (chooser.showSaveDialog(GUIEnv.getApplicationFrame()) == JFileChooser.APPROVE_OPTION) {
saveHistory((ClipableTaskInterface) task, chooser.getSelectedFile());
}
}
/**
* Save the history in the specified file
*/
private void saveHistory(ClipableTaskInterface task, File file) {
HistoryClipIn clipin = (HistoryClipIn) task.getClipIn(HistoryClipIn.HISTORY_CLIPIN_NAME);
TaskGraph history = clipin.getHistory();
TaskGraphOrganize.organizeTaskGraph(TaskGraphOrganize.TREE_ORGANIZE, history);
try {
String taskName = FileUtils.getFileNameNoSuffix(file.getAbsolutePath());
history.setToolName(taskName);
XMLWriter writer = new XMLWriter(new FileWriter(file));
writer.writeComponent(history);
writer.close();
} catch (IOException except) {
JOptionPane
.showMessageDialog(GUIEnv.getApplicationFrame(), "Save Histroy Error: " + except.getMessage(),
"Save Error", JOptionPane.ERROR_MESSAGE,
GUIEnv.getTrianaIcon());
}
}
private void fileBrowse() {
TFileChooser chooser = new TFileChooser(Env.DATA_DIRECTORY);
chooser.setSelectedFile(new File(getFileName()));
chooser.setMultiSelectionEnabled(false);
int result = chooser.showDialog(this, "O.K.");
if (result == JFileChooser.APPROVE_OPTION) {
filename.setText(chooser.getSelectedFile().getAbsolutePath());
filename.setCaretPosition(0);
}
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed(ActionEvent event) {
if (event.getSource() == savebutton) {
saveHistory(getTask());
} else if (event.getSource() == filebrowse) {
fileBrowse();
}
}
/**
* Invoked when an item has been selected or deselected by the user. The code written for this method performs
* the operations that need to occur when an item is selected (or deselected).
*/
public void itemStateChanged(ItemEvent event) {
if (event.getSource() == autosave) {
filename.setEnabled(autosave.isSelected());
filebrowse.setEnabled(autosave.isSelected());
seqcheck.setEnabled(autosave.isSelected());
}
}
}
private class XMLFileFilter extends FileFilter {
private static final String XML_EXTENSION = ".xml";
/**
* Whether the given file is accepted by this filter.
*/
public boolean accept(File file) {
return file.isDirectory() || file.getName().toLowerCase().endsWith(XML_EXTENSION);
}
/**
* The description of this filter. For example: "JPG and GIF Images"
*
* @see javax.swing.filechooser.FileView#getName
*/
public String getDescription() {
return "XML Files";
}
}
}