// Copyright (c) 2006 - 2008, Markus Strauch.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// * 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.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS 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 THE COPYRIGHT OWNER OR 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.
package net.sf.sdedit.editor;
import java.awt.event.ActionEvent;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.swing.AbstractAction;
import javax.swing.Action;
import net.sf.sdedit.Constants;
import net.sf.sdedit.config.Configuration;
import net.sf.sdedit.config.ConfigurationManager;
import net.sf.sdedit.multipage.MultipageExporter;
import net.sf.sdedit.server.Exporter;
import net.sf.sdedit.ui.components.buttons.Activator;
import net.sf.sdedit.ui.components.configuration.Bean;
import net.sf.sdedit.util.OS;
import static net.sf.sdedit.editor.Shortcuts.*;
@SuppressWarnings("serial")
public final class Actions implements Constants {
public static final String ICON_NAME = "icon-name";
private Editor editor;
Actions(Editor editor) {
this.editor = editor;
}
public final Activator canConfigureActivator = new Activator() {
public boolean isEnabled() {
return editor.getUI().getConfiguration() != null;
}
};
public final Activator nonEmptyDiagramActivator = new Activator() {
public boolean isEnabled() {
return !editor.getUI().isDiagramBlank();
}
};
public final Activator noDiagramErrorActivator = new Activator() {
public boolean isEnabled() {
return !editor.getUI().isDiagramBlank() &&
editor.getUI().getDiagramError() == null;
}
};
public final Activator canNarrowActivator = new Activator() {
public boolean isEnabled() {
Bean<Configuration> conf = editor.getUI().getConfiguration();
if (conf == null) {
return false;
}
return conf.getDataObject().getGlue() > 0;
}
};
public final Activator regularTabActivator = new Activator() {
public boolean isEnabled() {
return editor.getUI().isDiagramTabSelected();
}
};
public final Activator verticalSplitPossibleActivator = new Activator() {
public boolean isEnabled() {
Bean<Configuration> conf = editor.getUI().getConfiguration();
return conf != null && !conf.getDataObject().isVerticallySplit();
}
};
public final Activator horizontalSplitPossibleActivator = new Activator() {
public boolean isEnabled() {
Bean<Configuration> conf = editor.getUI().getConfiguration();
return conf != null && conf.getDataObject().isVerticallySplit();
}
};
final Action clearAction = new AbstractAction() {
{
putValue(ICON_NAME, "eraser");
putValue(Action.SHORT_DESCRIPTION, "Erase the source code");
putValue(Action.NAME, getShortcut(CLEAR) + "&Erase code");
}
public void actionPerformed(ActionEvent e) {
editor.getUI().setCode("");
editor.codeChanged(false);
}
};
final Action configureGloballyAction = new AbstractAction() {
{
putValue(ICON_NAME, "globalsettings");
putValue(Action.SHORT_DESCRIPTION, "Edit global preferences");
putValue(Action.NAME, getShortcut(GLOBAL_CONFIGURATION)
+ "&Global preferences...");
}
public void actionPerformed(ActionEvent e) {
editor.getUI().configure(false);
}
};
final Action configureDiagramAction = new AbstractAction() {
{
putValue(ICON_NAME, "configure");
putValue(Action.SHORT_DESCRIPTION, "Edit diagram preferences");
putValue(Action.NAME, getShortcut(DIAGRAM_CONFIGURATION)
+ "&Diagram preferences...");
}
public void actionPerformed(ActionEvent e) {
editor.getUI().configure(true);
}
};
final Action helpAction = new AbstractAction() {
{
putValue(ICON_NAME, "help");
putValue(Action.SHORT_DESCRIPTION,
"Display a comprehensive help page");
putValue(Action.NAME, getShortcut(HELP) + "&Help");
}
public void actionPerformed(ActionEvent e) {
editor.getUI().help("Help", "/net/sf/sdedit/help/help.html", true);
}
};
final Action helpOnMultithreadingAction = new AbstractAction() {
{
putValue(ICON_NAME, "help");
putValue(Action.SHORT_DESCRIPTION,
"Show a help page dedicated to multithreading");
putValue(Action.NAME, "&Multithreading help");
}
public void actionPerformed(ActionEvent e) {
editor.getUI().help("Multithreading help",
"/net/sf/sdedit/help/multithreading_help.html", false);
}
};
final Action asyncNotesAction = new AbstractAction() {
{
putValue(ICON_NAME, "help");
putValue(Action.SHORT_DESCRIPTION,
"Show a help page containing notes on asynchronous messages");
putValue(Action.NAME, "&Notes on asynchronous messages");
}
public void actionPerformed(ActionEvent e) {
editor.getUI().help("Notes on asynchronous messages",
"/net/sf/sdedit/help/async.html", false);
}
};
final Action loadCodeAction = new AbstractAction() {
{
putValue(ICON_NAME, "open");
putValue(Action.NAME, getShortcut(OPEN) + "&Open...");
putValue(Action.SHORT_DESCRIPTION, "Load diagram");
}
public void actionPerformed(ActionEvent e) {
try {
editor.loadCode();
} catch (Exception ex) {
ex.printStackTrace();
editor.error("Could not open the file due to an\n"
+ "exception of type: " + ex.getClass().getSimpleName()
+ "\n" + "with the message: " + ex.getMessage());
}
}
};
final Action newDiagramAction = new AbstractAction() {
{
putValue(ICON_NAME, "new");
putValue(Action.NAME, getShortcut(NEW) + "&New diagram");
putValue(Action.SHORT_DESCRIPTION, "Add a tab for a new diagram");
}
public void actionPerformed(ActionEvent e) {
Bean<Configuration> conf = ConfigurationManager
.createNewDefaultConfiguration();
editor.getUI().addTab("untitled", conf);
}
};
final Action closeAllAction = new AbstractAction() {
{
putValue(ICON_NAME, "close");
putValue(Action.NAME, getShortcut(CLOSE_ALL) + "Close All");
putValue(Action.SHORT_DESCRIPTION, "Close all tabs");
}
public void actionPerformed(ActionEvent e) {
if (editor.closeAll()) {
editor.getUI().addTab("untitled",
ConfigurationManager.createNewDefaultConfiguration());
}
}
};
public final Action closeDiagramAction = new AbstractAction() {
{
putValue(ICON_NAME, "close");
putValue(Action.NAME, getShortcut(CLOSE) + "&Close");
putValue(Action.SHORT_DESCRIPTION, "Close the current tab");
}
public void actionPerformed(ActionEvent e) {
if (editor.getUI().getNumberOfTabs() > 1) {
if (editor.getUI().isClean()) {
editor.getUI().removeCurrentTab(false);
} else {
String option = editor.getUI().getOption(
"<html>There are unsaved changes.<br>"
+ "Do you want to save them?", "Cancel",
"No", "Yes#");
if (option.equals("Yes")) {
try {
if (editor.saveCode(false)) {
editor.getUI().removeCurrentTab(true);
}
} catch (RuntimeException re) {
throw re;
}
catch (Exception ioe) {
editor.error(ioe.getMessage());
}
} else if (option.equals("No")) {
editor.getUI().removeCurrentTab(true);
}
}
}
}
};
final Action quitAction = new AbstractAction() {
{
putValue(ICON_NAME, "exit");
putValue(Action.SHORT_DESCRIPTION, "Quit the application");
putValue(Action.NAME, getShortcut(QUIT) + "&Quit");
}
public void actionPerformed(ActionEvent e) {
editor.quit();
}
};
final Action saveCodeAction = new AbstractAction() {
{
putValue(ICON_NAME, "save");
putValue(NAME, getShortcut(SAVE) + "&Save");
putValue(SHORT_DESCRIPTION, "Save the diagram source code");
}
public void actionPerformed(ActionEvent e) {
try {
editor.saveCode(false);
} catch (RuntimeException re) {
throw re;
} catch (Exception ioe) {
editor.error(ioe.getMessage());
}
}
};
final Action saveCodeAsAction = new AbstractAction() {
{
putValue(ICON_NAME, "saveas");
putValue(Action.NAME, getShortcut(SAVE_AS) + "S&ave as...");
putValue(Action.SHORT_DESCRIPTION,
"Save the diagram source code as a new file");
}
public void actionPerformed(ActionEvent e) {
try {
editor.saveCode(true);
} catch (RuntimeException re) {
throw re;
}
catch (Exception ex) {
editor.error("Could not open the file due to an\n"
+ "exception of type: " + ex.getClass().getSimpleName()
+ "\n" + "with the message: " + ex.getMessage());
}
}
};
final Action saveImageAction = new AbstractAction() {
{
putValue(ICON_NAME, "image");
putValue(Action.NAME, getShortcut(EXPORT_IMAGE)
+ "&Export as PNG...");
putValue(Action.SHORT_DESCRIPTION,
"Export the diagram as a PNG image");
}
public void actionPerformed(ActionEvent e) {
try {
editor.saveImage();
} catch (IOException ioe) {
editor.error(ioe.getMessage());
}
}
};
final Action redrawAction = new AbstractAction() {
{
putValue(ICON_NAME, "reload");
putValue(Action.NAME, getShortcut(REDRAW) + "Re&draw");
putValue(Action.SHORT_DESCRIPTION, "Redraw the diagram");
}
public void actionPerformed(ActionEvent e) {
editor.codeChanged(false);
}
};
final Action widenAction = new AbstractAction() {
{
putValue(ICON_NAME, "widen");
putValue(Action.SHORT_DESCRIPTION, "Widen the diagram");
putValue(Action.NAME, getShortcut(WIDEN) + "&Widen");
}
public void actionPerformed(ActionEvent e) {
Configuration conf = editor.getUI().getConfiguration()
.getDataObject();
if (conf != null) {
conf.setGlue(conf.getGlue()
+ ConfigurationManager.getGlobalConfiguration()
.getGlueChangeAmount());
editor.codeChanged(false);
}
}
};
final Action narrowAction = new AbstractAction() {
{
putValue(ICON_NAME, "narrow");
putValue(Action.SHORT_DESCRIPTION, "Narrow the diagram");
putValue(Action.NAME, getShortcut(NARROW) + "&Narrow");
}
public void actionPerformed(ActionEvent e) {
Configuration conf = editor.getUI().getConfiguration()
.getDataObject();
if (conf != null) {
int glue = Math.max(0, conf.getGlue()
- ConfigurationManager.getGlobalConfiguration()
.getGlueChangeAmount());
conf.setGlue(glue);
editor.codeChanged(false);
}
}
};
final Action getExampleAction(final String name, final String file) {
return new AbstractAction() {
{
putValue(Action.NAME, name);
}
public void actionPerformed(ActionEvent e) {
InputStream stream = null;
try {
URL url = getClass().getResource(
"/net/sf/sdedit/examples/" + file);
stream = url.openStream();
editor.loadCode(stream, file);
} catch (RuntimeException re) {
throw re;
}
catch (Exception ex) {
editor.getUI().errorMessage(
"Loading example from classpath failed\n"
+ "due to an exception of type "
+ ex.getClass().getSimpleName() + "\n"
+ "with the message: " + ex.getMessage());
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
}
};
}
final Action redoAction = new AbstractAction("Redo") {
{
putValue(Action.NAME, getShortcut(REDO) + "&Redo");
putValue(Action.SHORT_DESCRIPTION,
"Redo the typing that has most recently been undone");
putValue(ICON_NAME, "redo");
}
public void actionPerformed(ActionEvent evt) {
editor.getUI().redo();
}
};
final Action undoAction = new AbstractAction("Undo") {
{
putValue(Action.NAME, getShortcut(UNDO) + "&Undo");
putValue(Action.SHORT_DESCRIPTION,
"Undo the typing that has most recently been done");
putValue(ICON_NAME, "undo");
}
public void actionPerformed(ActionEvent evt) {
editor.getUI().undo();
}
};
//
// final Action nextTabAction = new AbstractAction("Next tab") {
// {
// putValue(Action.NAME, "[" + ctrl() + " shift N]&Next tab");
// putValue(Action.SHORT_DESCRIPTION, "Switch to the text tab");
//
// putValue(ICON_NAME, "next");
// }
//
// public void actionPerformed(ActionEvent evt) {
// editor.getUI().nextTab();
// }
// };
//
// final Action previousTabAction = new AbstractAction("Previous tab") {
// {
// putValue(Action.NAME, "[" + ctrl() + " shift B]&Previous tab");
// putValue(Action.SHORT_DESCRIPTION, "Switch to the previous tab");
//
// putValue(ICON_NAME, "previous");
// }
//
// public void actionPerformed(ActionEvent evt) {
// editor.getUI().previousTab();
// }
// };
final Action showAboutDialogAction = new AbstractAction() {
{
putValue(Action.NAME, "About");
putValue(ICON_NAME, "help");
}
public void actionPerformed(ActionEvent evt) {
editor.getUI().showAboutDialog(
Editor.class.getResource("/net/sf/sdedit/about.html"));
}
};
final Action fullScreenAction = new AbstractAction() {
{
putValue(Action.NAME, getShortcut(FULL_SCREEN) + "&Full screen");
putValue(ICON_NAME, "fullscreen");
putValue(Action.SHORT_DESCRIPTION,
"Display the diagram in full-screen mode");
}
public void actionPerformed(ActionEvent evt) {
editor.getUI().fullScreen();
}
};
final Action filterAction = new AbstractAction() {
{
putValue(Action.NAME, getShortcut(FILTER) + "&Filter...");
putValue(ICON_NAME, "filter");
putValue(Action.SHORT_DESCRIPTION,
"Filter the (selected) text through a command");
}
public void actionPerformed(ActionEvent evt) {
editor.getUI().toggleFilterMode();
}
};
final Action serverAction = new AbstractAction() {
{
putValue(Action.NAME, "Start/stop &RT server...");
putValue(ICON_NAME, "server");
putValue(Action.SHORT_DESCRIPTION,
"Start or stop a server that receives diagram specifications through sockets");
}
public void actionPerformed(ActionEvent evt) {
if (editor.isServerRunning()) {
if (editor.getUI().confirmOrCancel(
"Stop real-time diagram server?") == 1) {
editor.shutDownServer();
}
return;
}
String port = String.valueOf(ConfigurationManager
.getGlobalConfiguration().getRealtimeServerPort());
port = editor
.getUI()
.getString(
"Enter the port where"
+ " the real-time diagram\nserver should listen (0 for any free port):",
port);
if (port == null || port.equals("")) {
return;
}
try {
int p = Integer.parseInt(port);
int actualPort = editor.startRealtimeServer(p);
ConfigurationManager.getGlobalConfiguration()
.setRealtimeServerPort(p);
editor.getUI().message(
"Started real-time diagram server@localhost:"
+ actualPort);
} catch (Exception e) {
editor.getUI().errorMessage(
"The real-time diagram server could not be started\n"
+ "due to an exception of type "
+ e.getClass().getSimpleName()
+ " with the message:" + e.getMessage());
}
}
};
final Action getRecentFileAction(final String fileName) {
return new AbstractAction() {
{
putValue(Action.NAME, new File(fileName).getName());
putValue(Action.SHORT_DESCRIPTION, new File(fileName)
.getAbsolutePath());
}
public void actionPerformed(ActionEvent e) {
try {
editor.loadCode(new File(fileName));
} catch (RuntimeException re) {
throw re;
} catch (Exception ex) {
editor.error("Could not open the file due to an\n"
+ "exception of type: "
+ ex.getClass().getSimpleName() + "\n"
+ "with the message: " + ex.getMessage());
}
}
};
}
final Action splitLeftRightAction = new AbstractAction() {
{
putValue(Action.NAME, getShortcut(SPLIT_LEFT_RIGHT)
+ "Split view left/right");
putValue(ICON_NAME, "view_left_right");
putValue(Action.SHORT_DESCRIPTION, "Split view left/right");
}
public void actionPerformed(ActionEvent evt) {
editor.getUI().layout(0);
}
};
final Action splitTopBottomAction = new AbstractAction() {
{
putValue(Action.NAME, getShortcut(SPLIT_TOP_BOTTOM)
+ "Split view top/bottom");
putValue(ICON_NAME, "view_top_bottom");
putValue(Action.SHORT_DESCRIPTION, "Split view top/bottom");
}
public void actionPerformed(ActionEvent evt) {
editor.getUI().layout(1);
}
};
final Action getExportAction() {
return Exporter.isAvailable() ? new ExportAction(editor) : null;
}
final Action getPrintAction(final String filetype) {
if (!MultipageExporter.isAvailable()) {
return null;
}
return new AbstractAction() {
{
putValue(ICON_NAME, filetype);
putValue(Action.SHORT_DESCRIPTION,
"Prints or exports the diagram in multi-page "
+ filetype.toUpperCase() + " format");
putValue(Action.NAME, getShortcut(PRINT)
+ "&Print/export multi-page " + filetype.toUpperCase()
+ "...");
}
public void actionPerformed(ActionEvent e) {
String code = editor.getUI().getCode();
if (code != null && code.trim().length() > 0) {
editor.getUI().showPrintDialog(filetype);
}
}
};
}
}