/*
* Open Source Physics software is free software as described near the bottom of this code file.
*
* For additional information and documentation on Open Source Physics please see:
* <http://www.opensourcephysics.org/>
*/
package org.opensourcephysics.tools;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.font.FontRenderContext;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JFileChooser;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.JToolBar;
import javax.swing.JViewport;
import javax.swing.KeyStroke;
import javax.swing.SpinnerModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.border.Border;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.tree.TreePath;
import org.opensourcephysics.controls.OSPLog;
import org.opensourcephysics.controls.XML;
import org.opensourcephysics.controls.XMLControl;
import org.opensourcephysics.controls.XMLControlElement;
import org.opensourcephysics.display.DisplayRes;
import org.opensourcephysics.display.OSPRuntime;
import org.opensourcephysics.display.PrintUtils;
/**
* This provides a GUI for building LaunchNode and LaunchSet xml files.
*
* @author Douglas Brown
* @version 1.2
*/
public class LaunchBuilder extends Launcher {
// static constants
static final Color RED = new Color(255, 102, 102);
// static fields
static JFileChooser fileChooser;
static javax.swing.filechooser.FileFilter jarFileFilter;
static javax.swing.filechooser.FileFilter htmlFileFilter;
static javax.swing.filechooser.FileFilter pdfFileFilter;
static javax.swing.filechooser.FileFilter allFileFilter;
static int maxArgs = 4; // max number of main method args
static File ospJarFolder;
static Color enabledColor, disabledColor;
// instance fields
Action newTabSetAction; // creates a new tabset with a single tab
Action changeAction; // loads input data into selected node
Action newTabAction; // creates a new root node and tab
Action addAction; // adds new node to selected node
Action cutAction; // cuts selected node to clipboard
Action copyAction; // copies selected node to clipboard
Action pasteAction; // adds clipboard node to selected node
Action importAction; // adds xml file node to selected node
Action saveAsAction; // saves selected node to a new file
Action saveAction; // saves selected node
Action saveAllAction; // saves tabset and all nodes
Action saveSetAsAction; // saves tabset and all nodes to new files
Action moveUpAction; // moves selected node up
Action moveDownAction; // moves selected node down
Action openJarAction; // opens a jar file and sets node path
Action searchJarAction; // searches the current jars for a launchable class
Action saveJarAction; // saves a jar file containing the current tab set
Action openArgAction; // opens an xml file and sets the current argument
Action openModelArgAction; // opens an xml file and sets the current model argument
Action openURLAction; // opens an html file and sets url
Action openPDFAction; // opens a pdf file and sets url
Action searchJarForModelAction; // searches the current jars for a model class
Action openTabAction; // opens a node in a new tab
Icon openIcon;
JTabbedPane editorTabs;
FocusListener focusListener;
KeyListener keyListener;
JPanel displayPanel;
JPanel launchPanel;
JPanel authorPanel;
ArrayList<JLabel> labels;
JTextField titleField;
JLabel titleLabel;
JTextField passwordEditor;
JLabel passwordLabel;
JTextField nameField;
JLabel nameLabel;
JTextField tooltipField;
JLabel tooltipLabel;
TitledBorder displayTitle;
JTextField classField;
JLabel classLabel;
JTextField argField;
JLabel argLabel;
JSpinner argSpinner;
JTextField jarField;
JLabel jarLabel;
JToolBar displayBar;
JLabel displayLabel;
SpinnerNumberModel displaySpinnerModel;
JSpinner displaySpinner;
JLabel pathLabel;
JTextField pathField;
JButton openDisplayChooserButton;
JButton showModelArgsButton;
JDialog modelArgsDialog;
JTextField modelArgField;
JLabel modelArgLabel;
JSpinner modelArgSpinner;
JButton modelArgCloseButton;
JButton modelArgClearButton;
JLabel tabTitleLabel;
JTextField tabTitleField;
JPanel urlPanel;
JTextPane descriptionPane;
JScrollPane descriptionScroller;
TitledBorder descriptionTitle;
JEditorPane htmlPane;
JScrollPane htmlScroller;
JSplitPane displaySplitPane;
JTextField authorField;
JLabel authorLabel;
JTextField keywordField;
JLabel keywordLabel;
JTextField levelField;
JLabel levelLabel;
JTextField languagesField;
JLabel languagesLabel;
JTextPane commentPane;
JScrollPane commentScroller;
TitledBorder commentTitle;
TitledBorder optionsTitle;
TitledBorder securityTitle;
JCheckBox editorEnabledCheckBox;
JCheckBox encryptCheckBox;
JCheckBox onEditCheckBox;
JCheckBox onLoadCheckBox;
JCheckBox hideRootCheckBox;
JCheckBox hiddenCheckBox;
JCheckBox buttonViewCheckBox;
JCheckBox singleVMCheckBox;
JCheckBox showLogCheckBox;
JCheckBox clearLogCheckBox;
JCheckBox singletonCheckBox;
JCheckBox singleAppCheckBox;
JComboBox levelDropDown;
String previousClassPath;
JButton newTabButton;
JButton addButton;
JButton cutButton;
JButton copyButton;
JButton pasteButton;
JButton moveUpButton;
JButton moveDownButton;
JMenuItem newItem;
JMenuItem previewItem;
JMenuItem saveNodeItem;
JMenuItem saveNodeAsItem;
JMenuItem saveSetAsItem;
JMenuItem saveAllItem;
JMenuItem saveJarItem;
JMenuItem importItem;
JMenuItem openTabItem;
JMenu toolsMenu;
JMenuItem encryptionToolItem;
JToolBar toolbar;
LaunchSaver saver = new LaunchSaver(this);
static {
// LaunchClassChooser.setBasePath("C:/Documents and Settings/DoBrown/My Documents/Eclipse/workspace_deploy");
// Launcher.setJarsOnly(false);
enabledColor = UIManager.getColor("Label.foreground"); //$NON-NLS-1$
if (enabledColor==null)
enabledColor = Color.BLACK;
disabledColor = UIManager.getColor("Label.disabledForeground"); //$NON-NLS-1$
if (disabledColor==null)
disabledColor = UIManager.getColor("Label.disabledText"); //$NON-NLS-1$
if (disabledColor==null)
disabledColor = Color.LIGHT_GRAY;
}
/**
* No-arg constructor.
*/
public LaunchBuilder() {
OSPRuntime.setAuthorMode(true);
XML.setLoader(NodeSet.class, new NodeSet.Loader());
}
/**
* Constructs a builder and loads the specified file.
*
* @param fileName the file name
*/
public LaunchBuilder(String fileName) {
super(fileName);
OSPRuntime.setAuthorMode(true);
XML.setLoader(NodeSet.class, new NodeSet.Loader());
}
/**
* Constructs a builder with or without a splash screen.
*
* @param splash true to show the splash screen
*/
public LaunchBuilder(boolean splash) {
super(splash);
OSPRuntime.setAuthorMode(true);
XML.setLoader(NodeSet.class, new NodeSet.Loader());
}
/**
* Constructs a builder and loads the specified file with or without splash.
*
* @param fileName the file name
* @param splash true to show the splash screen
*/
public LaunchBuilder(String fileName, boolean splash) {
super(fileName, splash);
OSPRuntime.setAuthorMode(true);
XML.setLoader(NodeSet.class, new NodeSet.Loader());
}
/**
* Main entry point when used as application.
*
* @param args args[0] may be an xml file name
*/
public static void main(String[] args) {
// java.util.Locale.setDefault(new java.util.Locale("es"));
// OSPLog.setLevel(ConsoleLevel.ALL);
// OSPRuntime.setJavaLookAndFeel(true);
String fileName = null;
if((args!=null)&&(args.length!=0)) {
fileName = args[0];
}
LaunchBuilder builder = new LaunchBuilder(fileName);
builder.frame.setVisible(true);
}
/**
* Saves a node to the specified file.
*
* @param node the node
* @param fileName the desired name of the file
* @return the name of the saved file, or null if not saved
*/
public String save(LaunchNode node, String fileName) {
if(node==null) {
return null;
}
if((fileName==null)||fileName.trim().equals("")) { //$NON-NLS-1$
return saveAs(node);
}
// add .xml extension if none but don't require it
if(XML.getExtension(fileName)==null) {
while(fileName.endsWith(".")) { //$NON-NLS-1$
fileName = fileName.substring(0, fileName.length()-1);
}
fileName += ".xml"; //$NON-NLS-1$
}
if(!saveOwnedNodes(node)) {
return null;
}
String filepath = fileName;
if(!tabSetBasePath.equals("")) { //$NON-NLS-1$
filepath = XML.getResolvedPath(fileName, tabSetBasePath);
} else {
String jarBase = OSPRuntime.getLaunchJarDirectory();
filepath = XML.getResolvedPath(fileName, jarBase);
}
File file = new File(filepath);
OSPLog.fine(fileName+" = "+file.getAbsolutePath()); //$NON-NLS-1$
String fullName = XML.forwardSlash(file.getAbsolutePath());
String path = XML.getDirectoryPath(fullName);
XML.createFolders(path);
XMLControlElement control = new XMLControlElement(node);
control.write(fullName);
if(!control.canWrite) {
OSPLog.info(LaunchRes.getString("Dialog.SaveFailed.Message")+" "+fullName); //$NON-NLS-1$//$NON-NLS-2$
JOptionPane.showMessageDialog(null, LaunchRes.getString("Dialog.SaveFailed.Message")+" "+fileName, //$NON-NLS-1$//$NON-NLS-2$
LaunchRes.getString("Dialog.SaveFailed.Title"), //$NON-NLS-1$
JOptionPane.WARNING_MESSAGE);
return null;
}
node.setFileName(fileName);
changedFiles.remove(node.getFileName());
return fileName;
}
/**
* Saves a node to an xml file selected with a chooser.
*
* @param node the node
* @return the name of the file
*/
public String saveAs(LaunchNode node) {
getXMLChooser().setFileFilter(xmlFileFilter);
if(node.getFileName()!=null) {
String name = XML.getResolvedPath(node.getFileName(), tabSetBasePath);
getXMLChooser().setSelectedFile(new File(name));
} else {
String name = node.name;
if(name.equals(LaunchRes.getString("NewNode.Name"))|| //$NON-NLS-1$
name.equals(LaunchRes.getString("NewTab.Name"))) { //$NON-NLS-1$
name = LaunchRes.getString("NewFile.Name"); //$NON-NLS-1$
}
String path = XML.getResolvedPath(name+".xml", tabSetBasePath); //$NON-NLS-1$
getXMLChooser().setSelectedFile(new File(path));
}
int result = getXMLChooser().showDialog(null, LaunchRes.getString("FileChooser.SaveAs.Title")); //$NON-NLS-1$
if(result==JFileChooser.APPROVE_OPTION) {
File file = getXMLChooser().getSelectedFile();
// create folder structure
String path = XML.forwardSlash(file.getParent());
XML.createFolders(path);
// check to see if file already exists
if(file.exists()) {
// prevent duplicate file names
String name = XML.forwardSlash(file.getAbsolutePath());
name = XML.getPathRelativeTo(name, tabSetBasePath);
if(getOpenPaths().contains(name)) {
JOptionPane.showMessageDialog(frame, LaunchRes.getString("Dialog.DuplicateFileName.Message")+" \""+name+"\"", //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
LaunchRes.getString("Dialog.DuplicateFileName.Title"), //$NON-NLS-1$
JOptionPane.WARNING_MESSAGE);
return null;
}
int selected = JOptionPane.showConfirmDialog(frame, LaunchRes.getString("Dialog.ReplaceFile.Message")+" "+ //$NON-NLS-1$//$NON-NLS-2$
file.getName()+XML.NEW_LINE+LaunchRes.getString("Dialog.ReplaceFile.Question"), //$NON-NLS-1$
LaunchRes.getString("Dialog.ReplaceFile.Title"), //$NON-NLS-1$
JOptionPane.YES_NO_OPTION);
if(selected!=JOptionPane.YES_OPTION) {
return null;
}
}
path = XML.forwardSlash(file.getAbsolutePath());
String fileName = XML.getPathRelativeTo(path, tabSetBasePath);
OSPRuntime.chooserDir = XML.getDirectoryPath(path);
// get clones before saving
Map<LaunchPanel, LaunchNode> clones = getClones(node);
path = save(node, fileName);
if(path!=null) {
if(node.isRoot()) {
// refresh title of root tab
for(int i = 0; i<tabbedPane.getTabCount(); i++) {
LaunchPanel tab = (LaunchPanel) tabbedPane.getComponentAt(i);
if(tab.getRootNode()==node) {
tabbedPane.setTitleAt(i, node.toString());
break;
}
}
}
// refresh clones
for(Iterator<LaunchPanel> it = clones.keySet().iterator(); it.hasNext(); ) {
LaunchPanel cloneTab = it.next();
LaunchNode clone = clones.get(cloneTab);
clone.setFileName(node.getFileName());
// refresh title of clone tab
if(clone==cloneTab.getRootNode()) {
int n = tabbedPane.indexOfComponent(cloneTab);
tabbedPane.setTitleAt(n, node.toString());
}
}
if(tabSetName!=null) {
changedFiles.add(tabSetName);
}
}
return path;
}
return null;
}
// ______________________________ protected methods _____________________________
/**
* Saves the owned nodes of the specified node.
*
* @param node the node
* @return true unless cancelled by user
*/
protected boolean saveOwnedNodes(LaunchNode node) {
if(node==null) {
return false;
}
if(node.isSelfContained()) {
return true; // owned nodes saved within node
}
LaunchNode[] nodes = node.getChildOwnedNodes();
for(int i = 0; i<nodes.length; i++) {
// save owned nodes of owned node, if any
if(nodes[i].getChildOwnedNodes().length>1) {
if(!saveOwnedNodes(nodes[i])) {
return false;
}
}
if(save(nodes[i], nodes[i].getFileName())==null) {
return false;
}
}
return true;
}
/**
* Saves a tabset to a file selected with a chooser.
*
* @return the absolute path of the tabset file
*/
protected String saveTabSetAs() {
saver.setBuilder(this);
saver.setVisible(true);
if(!saver.isApproved()) {
return null;
}
String fileName = XML.getResolvedPath(tabSetName, tabSetBasePath);
File file = new File(fileName);
if(file.exists()) {
int selected = JOptionPane.showConfirmDialog(frame, LaunchRes.getString("Dialog.ReplaceFile.Message")+" "+ //$NON-NLS-1$//$NON-NLS-2$
file.getName()+XML.NEW_LINE+LaunchRes.getString("Dialog.ReplaceFile.Question"), //$NON-NLS-1$
LaunchRes.getString("Dialog.ReplaceFile.Title"), //$NON-NLS-1$
JOptionPane.YES_NO_OPTION);
if(selected!=JOptionPane.YES_OPTION) {
return null;
}
}
saveState = saver.saveStateCheckBox.isSelected();
return saveTabSet();
}
/**
* Saves the current tabset.
*
* @return the full path to the saved file, or null if not saved
*/
public String saveTabSet() {
if(tabSetName==null) {
return null;
}
if(tabSetName.trim().equals("")) { //$NON-NLS-1$
return saveTabSetAs();
}
// check for read-only files
if(!isTabSetWritable()) {
return saveTabSetAs();
}
if(!selfContained&&!saveTabs()) {
return null;
}
// save tab set
String fileName = tabSetName;
if(!tabSetBasePath.equals("")) { //$NON-NLS-1$
fileName = XML.getResolvedPath(tabSetName, tabSetBasePath);
} else {
String jarBase = OSPRuntime.getLaunchJarDirectory();
fileName = XML.getResolvedPath(tabSetName, jarBase);
}
OSPLog.fine(fileName);
File file = new File(fileName);
fileName = XML.forwardSlash(file.getAbsolutePath());
String path = XML.getDirectoryPath(fileName);
XML.createFolders(path);
LaunchSet tabset = new LaunchSet(this, tabSetName);
XMLControlElement control = new XMLControlElement(tabset);
if(control.write(fileName)==null) {
return null;
}
changedFiles.clear();
jarBasePath = null; // signals tabset is now a file
if(spawner!=null) {
spawner.open(fileName);
spawner.refreshGUI();
}
return fileName;
}
/**
* Saves tabs.
* @return true unless cancelled by user
*/
public boolean saveTabs() {
Component[] tabs = tabbedPane.getComponents();
for(int i = 0; i<tabs.length; i++) {
LaunchPanel tab = (LaunchPanel) tabs[i];
LaunchNode root = tab.getRootNode();
if((root.getFileName()==null)||root.getFileName().equals("")) { //$NON-NLS-1$
continue;
}
save(root, XML.getResolvedPath(root.getFileName(), tabSetBasePath));
}
return true;
}
/**
* Refreshes the selected node.
*/
protected void refreshSelectedNode() {
refreshNode(getSelectedNode());
}
/**
* Refreshes the specified node with data from the input fields.
*
* @param node the node to refresh
*/
protected void refreshNode(LaunchNode node) {
boolean changed = false;
if(node!=null) {
if(node.isSingleVM()!=singleVMCheckBox.isSelected()) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeVM")); //$NON-NLS-1$
LaunchNode parent = (LaunchNode) node.getParent();
if((parent!=null)&&parent.isSingleVM()) {
node.singleVM = false;
node.singleVMOff = !singleVMCheckBox.isSelected();
} else {
node.singleVM = singleVMCheckBox.isSelected();
node.singleVMOff = false;
}
if(node.isSingleVM()) {
showLogCheckBox.setSelected(node.showLog);
clearLogCheckBox.setSelected(node.clearLog);
singleAppCheckBox.setSelected(node.isSingleApp());
} else {
singletonCheckBox.setSelected(node.singleton);
}
changed = true;
}
if(node.isSingleVM()&&(node.showLog!=showLogCheckBox.isSelected())) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeShowLog")); //$NON-NLS-1$
node.showLog = showLogCheckBox.isSelected();
changed = true;
}
if(node.isSingleVM()&&node.isShowLog()&&(node.clearLog!=clearLogCheckBox.isSelected())) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeClearLog")); //$NON-NLS-1$
node.clearLog = clearLogCheckBox.isSelected();
changed = true;
}
if(node.isSingleVM()&&(node.isSingleApp()!=singleAppCheckBox.isSelected())) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeSingleApp")); //$NON-NLS-1$
LaunchNode parent = (LaunchNode) node.getParent();
if((parent!=null)&&parent.isSingleApp()) {
node.singleApp = false;
node.singleAppOff = !singleAppCheckBox.isSelected();
} else {
node.singleApp = singleAppCheckBox.isSelected();
node.singleAppOff = false;
}
changed = true;
}
if(node.singleton!=singletonCheckBox.isSelected()) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeSingleton")); //$NON-NLS-1$
node.singleton = singletonCheckBox.isSelected();
changed = true;
}
if(node.hiddenInLauncher!=hiddenCheckBox.isSelected()) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeHidden")); //$NON-NLS-1$
node.hiddenInLauncher = hiddenCheckBox.isSelected();
changed = true;
}
if(node.isButtonView()!=buttonViewCheckBox.isSelected()) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeButtonView")); //$NON-NLS-1$
node.setButtonView(buttonViewCheckBox.isSelected());
changed = true;
}
if(!node.name.equals(nameField.getText())) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeName")); //$NON-NLS-1$
node.name = nameField.getText();
changed = true;
}
if(!node.tooltip.equals(tooltipField.getText())) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeTooltip")); //$NON-NLS-1$
node.tooltip = tooltipField.getText();
changed = true;
}
if(!node.description.equals(descriptionPane.getText())) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeDesc")); //$NON-NLS-1$
node.description = descriptionPane.getText();
changed = true;
}
int n = ((Integer) argSpinner.getValue()).intValue();
String arg = argField.getText();
if(!arg.equals("")) { //$NON-NLS-1$
node.setMinimumArgLength(n+1);
}
if((node.args.length>n)&&!arg.equals(node.args[n])) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeArgs")+" "+n); //$NON-NLS-1$//$NON-NLS-2$
node.args[n] = arg;
if(arg.equals("")) { //$NON-NLS-1$
node.setMinimumArgLength(1);
}
changed = true;
}
String jarPath = jarField.getText();
if((jarPath.equals("")&&(node.classPath!=null))||(!jarPath.equals("")&&!jarPath.equals(node.classPath))) { //$NON-NLS-1$//$NON-NLS-2$
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodePath")); //$NON-NLS-1$
node.setClassPath(jarPath.equals("") //$NON-NLS-1$
? null : jarPath);
changed = true;
}
n = ((Integer) displaySpinner.getValue()).intValue();
LaunchNode.DisplayTab displayTab = node.getDisplayTab(n);
String input = pathField.getText();
if (displayTab==null
||((displayTab.path!=null &&!displayTab.path.equals(input))
||(input!=null && !input.equals(displayTab.path)))) {
String title = (displayTab==null) ? null : displayTab.title;
String[] args = (displayTab==null) ? null : displayTab.getModelArgs();
node.setDisplayTab(n, title, input, args);
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeURL")); //$NON-NLS-1$
changed = true;
}
if (displayTab!=null
&& displayTab.modelClass != null
&& modelArgsDialog.isVisible()) {
n = ((Integer) modelArgSpinner.getValue()).intValue();
arg = modelArgField.getText();
if(!arg.equals("")) { //$NON-NLS-1$
displayTab.setMinimumModelArgLength(n+1);
}
String[] args = displayTab.getModelArgs();
if(args.length>n && !arg.equals(args[n])) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeModelArgs")+" "+n); //$NON-NLS-1$//$NON-NLS-2$
args[n] = arg.equals("")? null: arg; //$NON-NLS-1$
displayTab.setModelArgs(args);
if(arg.equals("")) { //$NON-NLS-1$
displayTab.setMinimumModelArgLength(0);
}
changed = true;
}
}
input = tabTitleField.getText();
if(input.equals("")) { //$NON-NLS-1$
input = null;
}
if(displayTab!= null
&& ((displayTab.title!=null && !displayTab.title.equals(input))
|| (input!=null && !input.equals(displayTab.title)))) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeHTMLTabTitle")); //$NON-NLS-1$
node.setDisplayTab(n, input, displayTab.path, displayTab.getModelArgs());
changed = true;
}
String className = classField.getText();
if(className.equals("")) { //$NON-NLS-1$
if(node.launchClassName!=null) {
node.launchClassName = null;
node.launchClass = null;
node.launchModelScroller = null;
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeLaunchClass")); //$NON-NLS-1$
changed = true;
}
} else if(!className.equals(node.launchClassName)||(!className.equals("")&&(node.getLaunchClass()==null))) { //$NON-NLS-1$
boolean change = node.setLaunchClass(className);
if(change) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeLaunchClass")); //$NON-NLS-1$
changed = true;
}
}
if(!node.getAuthor().equals(authorField.getText())) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeAuthor")); //$NON-NLS-1$
node.author = authorField.getText();
changed = true;
}
if(!node.keywords.equals(keywordField.getText())) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeKeywords")); //$NON-NLS-1$
node.keywords = keywordField.getText();
changed = true;
}
if(!node.level.equals(levelField.getText())) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeLevel")); //$NON-NLS-1$
node.level = levelField.getText();
changed = true;
}
if(!node.languages.equals(languagesField.getText())) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeLanguages")); //$NON-NLS-1$
node.languages = languagesField.getText();
changed = true;
}
if(!node.comment.equals(commentPane.getText())) {
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeComment")); //$NON-NLS-1$
node.comment = commentPane.getText();
changed = true;
}
LaunchNode root = (LaunchNode) node.getRoot();
if(root!=null) {
boolean hide = hideRootCheckBox.isSelected();
if(hide!=root.hiddenWhenRoot) {
root.hiddenWhenRoot = hide;
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeRootHidden")); //$NON-NLS-1$
changed = true;
}
boolean edit = editorEnabledCheckBox.isSelected();
if(edit!=editorEnabled) {
editorEnabled = edit;
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeNodeEditorEnabled")); //$NON-NLS-1$
if(tabSetName!=null) {
changedFiles.add(tabSetName);
}
refreshGUI();
}
}
if(changed) {
OSPLog.fine(LaunchRes.getString("Log.Message.ChangeNode")+" \""+node.toString()+"\""); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
LaunchPanel tab = getSelectedTab();
if(tab!=null) {
tab.treeModel.nodeChanged(node);
}
if(node.getOwner()!=null) {
changedFiles.add(node.getOwner().getFileName());
} else {
changedFiles.add(tabSetName);
}
refreshClones(node);
refreshGUI();
}
}
}
/**
* Creates a LaunchPanel with the specified root and adds it to a new tab.
*
* @param root the root node
* @return true if tab successfully added
*/
public boolean addTab(LaunchNode root) {
if(root==null) {
return false;
}
OSPLog.finest(root.toString());
boolean added = super.addTab(root);
if(added) {
if(tabSetName==null) {
tabSetName = LaunchRes.getString("Tabset.Name.New"); //$NON-NLS-1$
}
changedFiles.add(tabSetName);
refreshGUI();
}
return added;
}
/**
* Removes the selected tab. Overrides Launcher method.
*
* @return true if the tab was removed
*/
public boolean removeSelectedTab() {
// close the tabset if only one tab is open
if(tabbedPane.getTabCount()==1) {
String[] prevArgs = undoManager.getLauncherState();
boolean removed = removeAllTabs();
if(removed&&(prevArgs!=null)) {
// null new args indicate not redoable
LauncherUndo.LoadEdit edit = undoManager.new LoadEdit(null, prevArgs);
undoSupport.postEdit(edit);
}
return removed;
}
// check for unsaved changes in the selected tab
LaunchPanel tab = (LaunchPanel) tabbedPane.getSelectedComponent();
if(tab!=null) {
if(!saveChanges(tab)) {
return false;
}
}
boolean removed = super.removeSelectedTab();
if((tabSetName!=null)&&removed) {
changedFiles.add(tabSetName);
refreshGUI();
}
return removed;
}
/**
* Offers to save changes, if any, to the specified tab.
*
* @param tab the tab
* @return true unless cancelled by user
*/
protected boolean saveChanges(LaunchPanel tab) {
LaunchNode root = tab.getRootNode();
int n = tabbedPane.indexOfComponent(tab);
String name = (n>-1) ? tabbedPane.getTitleAt(n) : getDisplayName(root.getFileName());
boolean changed = changedFiles.contains(root.getFileName());
LaunchNode[] nodes = root.getAllOwnedNodes();
for(int i = 0; i<nodes.length; i++) {
changed = changed||changedFiles.contains(nodes[i].getFileName());
}
if(changed) {
int selected = JOptionPane.showConfirmDialog(frame, LaunchRes.getString("Dialog.SaveChanges.Tab.Message")+" \""+ //$NON-NLS-1$//$NON-NLS-2$
name+"\""+XML.NEW_LINE+ //$NON-NLS-1$
LaunchRes.getString("Dialog.SaveChanges.Question"), //$NON-NLS-1$
LaunchRes.getString("Dialog.SaveChanges.Title"), //$NON-NLS-1$
JOptionPane.YES_NO_CANCEL_OPTION);
if(selected==JOptionPane.CANCEL_OPTION) {
return false;
}
if(selected==JOptionPane.YES_OPTION) {
// save root and all owned nodes
save(root, root.getFileName());
}
}
return true;
}
/**
* Removes all tabs and closes the tabset.
*
* @return true if all tabs were removed
*/
protected boolean removeAllTabs() {
if(!saveAllChanges()) {
return false;
}
return super.removeAllTabs();
}
/**
* Offers to save all changes, if any.
*
* @return true unless cancelled by user
*/
protected boolean saveAllChanges() {
// save changes to tab set
if(!changedFiles.isEmpty()&&(tabbedPane.getTabCount()>0)) {
String message = LaunchRes.getString("Dialog.SaveChanges.Tabset.Message"); //$NON-NLS-1$
int selected = JOptionPane.showConfirmDialog(frame, message+"\""+ //$NON-NLS-1$
tabSetName+"\""+XML.NEW_LINE+ //$NON-NLS-1$
LaunchRes.getString("Dialog.SaveChanges.Question"), //$NON-NLS-1$
LaunchRes.getString("Dialog.SaveChanges.Title"), //$NON-NLS-1$
JOptionPane.YES_NO_CANCEL_OPTION);
if(selected==JOptionPane.CANCEL_OPTION) {
return false;
}
if(selected==JOptionPane.YES_OPTION) {
if(tabSetName.equals(LaunchRes.getString("Tabset.Name.New"))|| //$NON-NLS-1$
!saveAllItem.isEnabled()) {
saveTabSetAs();
} else {
saveTabSet();
}
}
}
return true;
}
/**
* Refreshes string resources.
*/
protected void refreshStringResources() {
super.refreshStringResources();
saver = new LaunchSaver(this);
editorTabs.setTitleAt(0, LaunchRes.getString("Tab.Display")); //$NON-NLS-1$
editorTabs.setTitleAt(1, LaunchRes.getString("Tab.Launch")); //$NON-NLS-1$
editorTabs.setTitleAt(2, LaunchRes.getString("Tab.Author")); //$NON-NLS-1$
displayTitle.setTitle(LaunchRes.getString("Label.DisplayPane")); //$NON-NLS-1$
commentTitle.setTitle(LaunchRes.getString("Label.Comments")); //$NON-NLS-1$
descriptionTitle.setTitle(LaunchRes.getString("Label.Description")); //$NON-NLS-1$
optionsTitle.setTitle(LaunchRes.getString("Label.Options")); //$NON-NLS-1$
hiddenCheckBox.setText(LaunchRes.getString("Checkbox.Hidden")); //$NON-NLS-1$
buttonViewCheckBox.setText(LaunchRes.getString("Checkbox.ButtonView")); //$NON-NLS-1$
nameLabel.setText(LaunchRes.getString("Label.Name")); //$NON-NLS-1$
tooltipLabel.setText(LaunchRes.getString("Label.Tooltip")); //$NON-NLS-1$
displayLabel.setText(LaunchRes.getString("Label.Display")); //$NON-NLS-1$
tabTitleLabel.setText(LaunchRes.getString("Label.TabTitle")); //$NON-NLS-1$
pathLabel.setText(LaunchRes.getString("Label.Path")); //$NON-NLS-1$
jarLabel.setText(LaunchRes.getString("Label.Jar")); //$NON-NLS-1$
classLabel.setText(LaunchRes.getString("Label.Class")); //$NON-NLS-1$
argLabel.setText(LaunchRes.getString("Label.Args")); //$NON-NLS-1$
singleVMCheckBox.setText(LaunchRes.getString("Checkbox.SingleVM")); //$NON-NLS-1$
showLogCheckBox.setText(LaunchRes.getString("Checkbox.ShowLog")); //$NON-NLS-1$
clearLogCheckBox.setText(LaunchRes.getString("Checkbox.ClearLog")); //$NON-NLS-1$
singletonCheckBox.setText(LaunchRes.getString("Checkbox.Singleton")); //$NON-NLS-1$
singleAppCheckBox.setText(LaunchRes.getString("Checkbox.SingleApp")); //$NON-NLS-1$
authorLabel.setText(LaunchRes.getString("Label.Author")); //$NON-NLS-1$
keywordLabel.setText(LaunchRes.getString("Label.Keywords")); //$NON-NLS-1$
levelLabel.setText(LaunchRes.getString("Label.Level")); //$NON-NLS-1$
languagesLabel.setText(LaunchRes.getString("Label.Languages")); //$NON-NLS-1$
securityTitle.setTitle(LaunchRes.getString("Label.Security")); //$NON-NLS-1$
editorEnabledCheckBox.setText(LaunchRes.getString("Checkbox.EditorEnabled")); //$NON-NLS-1$
encryptCheckBox.setText(LaunchRes.getString("Checkbox.Encrypted")); //$NON-NLS-1$
passwordLabel.setText(LaunchRes.getString("Label.Password")); //$NON-NLS-1$
onLoadCheckBox.setText(LaunchRes.getString("Checkbox.PWLoad")); //$NON-NLS-1$
titleLabel.setText(LaunchRes.getString("Label.Title")); //$NON-NLS-1$
hideRootCheckBox.setText(LaunchRes.getString("Checkbox.HideRoot")); //$NON-NLS-1$
previewItem.setText(LaunchRes.getString("Menu.File.Preview")); //$NON-NLS-1$
encryptionToolItem.setText(LaunchRes.getString("MenuItem.EncryptionTool")); //$NON-NLS-1$
newItem.setText(LaunchRes.getString("Menu.File.New")); //$NON-NLS-1$
importItem.setText(LaunchRes.getString("Action.Import")); //$NON-NLS-1$
saveNodeItem.setText(LaunchRes.getString("Action.SaveNode")); //$NON-NLS-1$
saveNodeAsItem.setText(LaunchRes.getString("Action.SaveNodeAs")); //$NON-NLS-1$
saveAllItem.setText(LaunchRes.getString("Action.SaveAll")); //$NON-NLS-1$
openTabItem.setText(LaunchRes.getString("Action.OpenTab")); //$NON-NLS-1$
saveSetAsItem.setText(LaunchRes.getString("Action.SaveSetAs")); //$NON-NLS-1$
toolsMenu.setText(LaunchRes.getString("Menu.Tools")); //$NON-NLS-1$
newTabButton.setText(LaunchRes.getString("Action.New")); //$NON-NLS-1$
addButton.setText(LaunchRes.getString("Action.Add")); //$NON-NLS-1$
cutButton.setText(LaunchRes.getString("Action.Cut")); //$NON-NLS-1$
copyButton.setText(LaunchRes.getString("Action.Copy")); //$NON-NLS-1$
pasteButton.setText(LaunchRes.getString("Action.Paste")); //$NON-NLS-1$
moveUpButton.setText(LaunchRes.getString("Action.Up")); //$NON-NLS-1$
moveDownButton.setText(LaunchRes.getString("Action.Down")); //$NON-NLS-1$
showModelArgsButton.setText(LaunchRes.getString("Button.ModelArgs")); //$NON-NLS-1$
modelArgsDialog.setTitle(LaunchRes.getString("Dialog.ModelArgs.Title")); //$NON-NLS-1$
modelArgCloseButton.setText(LaunchRes.getString("Dialog.Button.Close")); //$NON-NLS-1$
modelArgClearButton.setText(LaunchRes.getString("Dialog.Button.Clear")); //$NON-NLS-1$
modelArgLabel.setText(LaunchRes.getString("Label.Args")); //$NON-NLS-1$
// set tool tips
pathField.setToolTipText(LaunchRes.getString("Display.Path.Tooltip")); //$NON-NLS-1$
tabTitleField.setToolTipText(LaunchRes.getString("Display.Tab.Title.Tooltip")); //$NON-NLS-1$
displaySpinner.setToolTipText(LaunchRes.getString("Display.Tab.Number.Tooltip"));//$NON-NLS-1$
openDisplayChooserButton.setToolTipText(LaunchRes.getString("Button.OpenDisplay.Tooltip")); //$NON-NLS-1$
showModelArgsButton.setToolTipText(LaunchRes.getString("Button.ModelArgs.Tooltip")); //$NON-NLS-1$
// reset label sizes
labels.clear();
labels.add(nameLabel);
labels.add(tooltipLabel);
labels.add(displayLabel);
// set label sizes
FontRenderContext frc = new FontRenderContext(null, false, false);
Font font = nameLabel.getFont();
//display panel labels
int w = 0;
for(Iterator<JLabel> it = labels.iterator(); it.hasNext(); ) {
JLabel next = it.next();
Rectangle2D rect = font.getStringBounds(next.getText()+" ", frc); //$NON-NLS-1$
w = Math.max(w, (int) rect.getWidth()+1);
}
Dimension labelSize = new Dimension(w, 20);
for(Iterator<JLabel> it = labels.iterator(); it.hasNext(); ) {
JLabel next = it.next();
next.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 2));
next.setPreferredSize(labelSize);
next.setHorizontalAlignment(SwingConstants.TRAILING);
}
// launch panel labels
labels.clear();
labels.add(jarLabel);
labels.add(classLabel);
labels.add(argLabel);
w = 0;
for(Iterator<JLabel> it = labels.iterator(); it.hasNext(); ) {
JLabel next = it.next();
Rectangle2D rect = font.getStringBounds(next.getText()+" ", frc); //$NON-NLS-1$
w = Math.max(w, (int) rect.getWidth()+1);
}
labelSize = new Dimension(w, 20);
for(Iterator<JLabel> it = labels.iterator(); it.hasNext(); ) {
JLabel next = it.next();
next.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 2));
next.setPreferredSize(labelSize);
next.setHorizontalAlignment(SwingConstants.TRAILING);
}
labels.clear();
// author panel labels
labels.add(authorLabel);
labels.add(keywordLabel);
labels.add(levelLabel);
labels.add(languagesLabel);
w = 0;
for(Iterator<JLabel> it = labels.iterator(); it.hasNext(); ) {
JLabel next = it.next();
Rectangle2D rect = font.getStringBounds(next.getText()+" ", frc); //$NON-NLS-1$
w = Math.max(w, (int) rect.getWidth()+1);
}
labelSize = new Dimension(w, 20);
for(Iterator<JLabel> it = labels.iterator(); it.hasNext(); ) {
JLabel next = it.next();
next.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 2));
next.setPreferredSize(labelSize);
next.setHorizontalAlignment(SwingConstants.TRAILING);
}
}
/**
* Refreshes the GUI.
*/
protected void refreshGUI() {
if(previousNode!=null) { // new tab has been selected
LaunchNode prev = previousNode;
previousNode = null;
refreshNode(prev);
}
if(newNodeSelected) {
argSpinner.setValue(new Integer(0));
displaySpinner.setValue(new Integer(0));
newNodeSelected = false;
}
LaunchNode root = getRootNode();
boolean rootEnabled = root==null || root.enabled;
if (!rootEnabled)
editorTabs.setSelectedIndex(0);
titleField.setText(title);
titleField.setBackground(Color.white);
super.refreshGUI();
// refresh frame title
String theTitle = frame.getTitle();
if(this.title!=null) {
if(!changedFiles.isEmpty()) {
theTitle += " ["+tabSetName+"*]"; //$NON-NLS-1$//$NON-NLS-2$
} else {
theTitle += " ["+tabSetName+"]"; //$NON-NLS-1$//$NON-NLS-2$
}
} else if(!changedFiles.isEmpty()) {
if(tabbedPane.getTabCount()==0) {
changedFiles.clear();
} else {
theTitle += "*"; //$NON-NLS-1$
}
}
frame.setTitle(theTitle);
// refresh selected node items
final LaunchNode node = getSelectedNode();
if(node!=null) {
// refresh tab titles
for(int i = 0; i<tabbedPane.getTabCount(); i++) {
root = getTab(i).getRootNode();
tabbedPane.setTitleAt(i, root.toString());
}
// refresh display tab
hiddenCheckBox.setSelected(node.isHiddenInLauncher());
boolean parentHidden = (node.getParent()!=null)&&((LaunchNode) node.getParent()).isHiddenInLauncher();
hiddenCheckBox.setEnabled(!parentHidden && rootEnabled);
nameField.setText(node.toString());
nameField.setBackground(Color.white);
tooltipField.setText(node.tooltip);
tooltipField.setBackground(Color.white);
descriptionPane.setText(node.description);
descriptionPane.setBackground(Color.white);
int n = ((Integer) displaySpinner.getValue()).intValue();
LaunchNode.DisplayTab displayTab = node.getDisplayTab(n);
String urlPath = (displayTab!=null)? displayTab.path: null;
boolean badURL = (urlPath!=null && displayTab.url==null && displayTab.modelClass==null);
pathField.setText(urlPath);
pathField.setBackground(badURL ? RED : Color.white);
displaySpinnerModel.setMaximum(new Integer(node.getDisplayTabCount()));
displaySpinner.setVisible(node.getDisplayTab(0)!=null);
boolean hasHTML = displayTab!=null && displayTab.path!=null && !displayTab.path.toLowerCase().endsWith("pdf"); //$NON-NLS-1$
tabTitleLabel.setVisible(hasHTML);
tabTitleField.setVisible(hasHTML);
tabTitleField.setText((displayTab!=null) ? displayTab.title : null);
tabTitleField.setBackground(Color.white);
displayBar.remove(showModelArgsButton);
if(displayTab!=null
&& ((displayTab.url!=null && !displayTab.url.getPath().toLowerCase().endsWith("pdf")) //$NON-NLS-1$
|| displayTab.getModelScroller()!=null)) {
if(displayTab.url!=null) {
displaySplitPane.setTopComponent(htmlScroller);
if (htmlPane.getPage()!=displayTab.url) {
try {
if(displayTab.url.getContent()!=null) {
final java.net.URL url = displayTab.url;
Runnable runner = new Runnable() {
public void run() {
try {
htmlPane.setPage(url);
} catch(IOException ex) {
OSPLog.fine(LaunchRes.getString("Log.Message.BadURL")+" "+url); //$NON-NLS-1$//$NON-NLS-2$
}
}
};
SwingUtilities.invokeLater(runner);
}
} catch(IOException ex) {
htmlPane.setText(null);
}
}
}
else if (displayTab.getModelScroller()!= null) {
JScrollPane scroller = displayTab.getModelScroller();
scroller.setBorder(displayTitle);
displaySplitPane.setTopComponent(scroller);
// add modelArgsButton at end
displayBar.add(showModelArgsButton);
n = ((Integer) modelArgSpinner.getValue()).intValue();
if(displayTab.modelArgs.length>n) {
modelArgField.setText(displayTab.modelArgs[n]);
} else {
modelArgField.setText(""); //$NON-NLS-1$
}
boolean xmlArg = modelArgField.getText().endsWith(".xml"); //$NON-NLS-1$
Resource res = null;
if(xmlArg) {
res = ResourceLoader.getResource(modelArgField.getText());
modelArgField.setBackground((res==null) ? RED : Color.white);
} else {
modelArgField.setBackground(Color.white);
}
}
}
else {
if (n == 0 && node.getLaunchModelScroller() != null) {
JScrollPane scroller = node.getLaunchModelScroller();
scroller.setBorder(displayTitle);
displaySplitPane.setTopComponent(scroller);
}
else {
displaySplitPane.setTopComponent(htmlScroller);
htmlPane.setContentType(LaunchPanel.TEXT_TYPE);
htmlPane.setText(null);
}
}
displayBar.validate();
// refresh launch node
// check the path and update the class chooser
String path = node.getClassPath(); // in node-to-root order
if(!path.equals(previousClassPath)) {
boolean success = getClassChooser().setPath(path);
searchJarAction.setEnabled(success);
searchJarForModelAction.setEnabled(success);
}
// store path for later comparison
previousClassPath = node.getClassPath();
jarField.setText(node.classPath);
jarField.setBackground(((node.classPath!=null)&&!getClassChooser().isLoaded(node.classPath)) ? RED : Color.white);
classField.setText(node.launchClassName);
classField.setBackground(((node.getLaunchClass()==null)&&(node.launchClassName!=null)) ? RED : Color.white);
n = ((Integer) argSpinner.getValue()).intValue();
if(node.args.length>n) {
argField.setText(node.args[n]);
} else {
argField.setText(""); //$NON-NLS-1$
}
boolean xmlArg = argField.getText().endsWith(".xml"); //$NON-NLS-1$
Resource res = null;
if(xmlArg) {
res = ResourceLoader.getResource(argField.getText());
argField.setBackground((res==null) ? RED : Color.white);
} else {
argField.setBackground(Color.white);
}
// set enabled and selected states of checkboxes
LaunchNode parent = (LaunchNode) node.getParent(); // may be null
singletonCheckBox.setEnabled((parent==null)||!parent.isSingleton());
singletonCheckBox.setSelected(node.isSingleton());
singleVMCheckBox.setSelected(node.isSingleVM());
if(node.isSingleVM()) {
showLogCheckBox.setEnabled((parent==null)||!parent.isShowLog());
showLogCheckBox.setSelected(node.isShowLog());
clearLogCheckBox.setEnabled((parent==null)||!parent.isClearLog());
clearLogCheckBox.setSelected(node.isClearLog());
singleAppCheckBox.setEnabled(true);
singleAppCheckBox.setSelected(node.isSingleApp());
} else {
showLogCheckBox.setEnabled(false);
showLogCheckBox.setSelected(false);
clearLogCheckBox.setEnabled(false);
clearLogCheckBox.setSelected(false);
singleAppCheckBox.setEnabled(false);
singleAppCheckBox.setSelected(false);
}
levelDropDown.setVisible(node.isShowLog());
clearLogCheckBox.setVisible(node.isShowLog());
// refresh the level dropdown if visible
if(levelDropDown.isVisible()) {
boolean useAll = ((parent==null)||!parent.isShowLog());
// disable during refresh to prevent triggering events
levelDropDown.setEnabled(false);
levelDropDown.removeAllItems();
for(int i = 0; i<OSPLog.levels.length; i++) {
if(useAll||(OSPLog.levels[i].intValue()<=parent.getLogLevel().intValue())) {
levelDropDown.addItem(OSPLog.levels[i]);
}
}
levelDropDown.setSelectedItem(node.getLogLevel());
levelDropDown.setEnabled(true);
}
// refresh author tab
authorField.setText(node.getAuthor());
authorField.setBackground(Color.white);
keywordField.setText(node.keywords);
keywordField.setBackground(Color.white);
levelField.setText(node.level);
levelField.setBackground(Color.white);
languagesField.setText(node.languages);
languagesField.setBackground(Color.white);
commentPane.setText(node.comment);
commentPane.setBackground(Color.white);
boolean hasPW = (password!=null)&&!password.equals(""); //$NON-NLS-1$
onLoadCheckBox.setEnabled(hasPW);
onLoadCheckBox.setSelected(hasPW&&pwRequiredToLoad);
encryptCheckBox.setSelected(password!=null);
passwordEditor.setEnabled(encryptCheckBox.isSelected());
passwordLabel.setEnabled(encryptCheckBox.isSelected());
passwordEditor.setText(password);
passwordEditor.setBackground(Color.white);
}
// rebuild file menu
fileMenu.removeAll();
fileMenu.add(newItem);
if(undoManager.canReload()) {
fileMenu.add(backItem);
}
fileMenu.addSeparator();
fileMenu.add(openItem);
if(openFromJarMenu!=null) {
fileMenu.add(openFromJarMenu);
}
LaunchPanel tab = getSelectedTab();
if (tab!=null && !tab.getRootNode().enabled) {
fileMenu.add(passwordItem);
}
boolean isZipped = (jarBasePath!=null)&&!jarBasePath.equals(""); //$NON-NLS-1$
saveAllItem.setEnabled(!isZipped&&isTabSetWritable());
if(tab!=null) {
if (rootEnabled) fileMenu.add(importItem);
fileMenu.addSeparator();
if (rootEnabled) fileMenu.add(closeTabItem);
fileMenu.add(closeAllItem);
fileMenu.addSeparator();
fileMenu.add(previewItem);
if (rootEnabled) {
fileMenu.addSeparator();
fileMenu.add(saveAllItem);
fileMenu.add(saveSetAsItem);
if(OSPRuntime.getLaunchJarName()!=null) {
fileMenu.addSeparator();
fileMenu.add(saveJarItem);
}
}
// added by W. Christian to capture screen
JMenu printMenu = new JMenu(DisplayRes.getString("DrawingFrame.Print_menu_title")); //$NON-NLS-1$
JMenuItem printFrameItem = new JMenuItem(DisplayRes.getString("DrawingFrame.PrintFrame_menu_item")); //$NON-NLS-1$
JMenuItem saveFrameAsEPSItem = new JMenuItem(DisplayRes.getString("DrawingFrame.SaveFrameAsEPS_menu_item")); //$NON-NLS-1$
printMenu.add(printFrameItem);
printMenu.add(saveFrameAsEPSItem);
fileMenu.add(printMenu);
// print action
printFrameItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
PrintUtils.printComponent(frame);
}
});
// save as EPS action
saveFrameAsEPSItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
PrintUtils.saveComponentAsEPS(frame);
} catch(IOException ex) {
/** empty block */
}
}
});
// end W. Christian code
// set tab properties
frame.getContentPane().add(toolbar, BorderLayout.NORTH);
tab.dataPanel.add(editorTabs, BorderLayout.CENTER);
// hidden root
if(getRootNode().getChildCount()==0) {
getRootNode().hiddenWhenRoot = false;
hideRootCheckBox.setEnabled(false);
} else {
hideRootCheckBox.setEnabled((node==null)||!node.isButtonView());
}
if (!rootEnabled)
hideRootCheckBox.setEnabled(false);
boolean rootVisible = !getRootNode().hiddenWhenRoot;
hideRootCheckBox.setSelected(!rootVisible);
tab.tree.setRootVisible(rootVisible);
if((getSelectedNode()==null)&&!rootVisible) {
tab.setSelectedNode((LaunchNode) getRootNode().getChildAt(0));
}
// button view
buttonViewCheckBox.setSelected((node!=null)&&node.isButtonView());
buttonViewCheckBox.setEnabled(rootVisible && rootEnabled);
// editor enabled
editorEnabledCheckBox.setSelected(editorEnabled);
// rootEnabled effects
editorTabs.setEnabled(rootEnabled);
nameField.setEnabled(rootEnabled);
tooltipField.setEnabled(rootEnabled);
descriptionPane.setEnabled(rootEnabled);
pathField.setEnabled(rootEnabled);
titleField.setEnabled(rootEnabled);
displaySpinner.setEnabled(rootEnabled);
openDisplayChooserButton.setEnabled(rootEnabled);
titleLabel.setEnabled(rootEnabled);
nameLabel.setEnabled(rootEnabled);
tooltipLabel.setEnabled(rootEnabled);
displayLabel.setEnabled(rootEnabled);
pathLabel.setEnabled(rootEnabled);
newTabButton.setEnabled(rootEnabled);
addButton.setEnabled(rootEnabled);
cutButton.setEnabled(rootEnabled);
copyButton.setEnabled(rootEnabled);
pasteButton.setEnabled(rootEnabled);
moveUpButton.setEnabled(rootEnabled);
moveDownButton.setEnabled(rootEnabled);
tabTitleField.setEnabled(rootEnabled);
htmlScroller.setEnabled(rootEnabled);
showModelArgsButton.setEnabled(rootEnabled);
displayTitle.setTitleColor(rootEnabled? enabledColor: disabledColor);
descriptionTitle.setTitleColor(rootEnabled? enabledColor: disabledColor);
} else { // no tab
frame.getContentPane().remove(toolbar);
}
if(exitItem!=null) {
fileMenu.addSeparator();
fileMenu.add(exitItem);
}
// update tabbed pane tool tips and icons
for(int k = 0; k<tabbedPane.getTabCount(); k++) {
root = getTab(k).getRootNode();
if(root.getFileName()!=null) {
tabbedPane.setIconAt(k, getFileIcon(root));
tabbedPane.setToolTipTextAt(k, LaunchRes.getString("ToolTip.FileName")+" \""+root.getFileName()+"\""); //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
} else {
tabbedPane.setIconAt(k, null);
tabbedPane.setToolTipTextAt(k, null);
}
}
}
/**
* Creates the GUI.
*
* @param splash true to show the splash screen
*/
protected void createGUI(boolean splash) {
wInit = 600;
hInit = 540;
labels = new ArrayList<JLabel>();
super.createGUI(splash);
// add listeners to refresh GUI
frame.addWindowListener(new WindowAdapter() {
// Added by W. Christian to disable the Language menu
public void windowGainedFocus(WindowEvent e) {
OSPRuntime.setAuthorMode(true);
}
public void windowActivated(WindowEvent e) {
OSPRuntime.setAuthorMode(true);
}
public void windowOpened(WindowEvent e) {
if(getSelectedNode()!=null) {
// clear htmlPane to force a full refresh
htmlPane.setContentType(LaunchPanel.TEXT_TYPE);
htmlPane.setText(null);
}
refreshGUI();
}
});
tabbedPane.addComponentListener(new ComponentAdapter() {
public void componentResized(ComponentEvent e) {
refreshGUI();
}
});
// create additional file and folder icons
String imageFile = "/org/opensourcephysics/resources/tools/images/whitefile.gif"; //$NON-NLS-1$
whiteFileIcon = loadIcon(imageFile);
imageFile = "/org/opensourcephysics/resources/tools/images/ghostfile.gif"; //$NON-NLS-1$
ghostFileIcon = loadIcon(imageFile);
imageFile = "/org/opensourcephysics/resources/tools/images/redfile.gif"; //$NON-NLS-1$
redFileIcon = loadIcon(imageFile);
imageFile = "/org/opensourcephysics/resources/tools/images/yellowfile.gif"; //$NON-NLS-1$
yellowFileIcon = loadIcon(imageFile);
imageFile = "/org/opensourcephysics/resources/tools/images/whitefolder.gif"; //$NON-NLS-1$
whiteFolderIcon = loadIcon(imageFile);
imageFile = "/org/opensourcephysics/resources/tools/images/redfolder.gif"; //$NON-NLS-1$
redFolderIcon = loadIcon(imageFile);
imageFile = "/org/opensourcephysics/resources/tools/images/greenfolder.gif"; //$NON-NLS-1$
greenFolderIcon = loadIcon(imageFile);
imageFile = "/org/opensourcephysics/resources/tools/images/yellowfolder.gif"; //$NON-NLS-1$
yellowFolderIcon = loadIcon(imageFile);
// create actions
createActions();
// create fields
titleField = new JTextField();
titleField.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_ENTER) {
String text = titleField.getText();
if(text.equals("")) { //$NON-NLS-1$
text = null;
}
if(text!=title) {
changedFiles.add(tabSetName);
}
title = text;
refreshGUI();
} else {
titleField.setBackground(Color.yellow);
}
}
});
titleField.addFocusListener(new FocusAdapter() {
public void focusLost(FocusEvent e) {
String text = titleField.getText();
if(text.equals("")) { //$NON-NLS-1$
text = null;
}
if(text!=title) {
changedFiles.add(tabSetName);
}
title = text;
refreshGUI();
}
});
nameField = new JTextField();
nameField.addKeyListener(keyListener);
nameField.addFocusListener(focusListener);
tooltipField = new JTextField();
tooltipField.addKeyListener(keyListener);
tooltipField.addFocusListener(focusListener);
displayTitle = BorderFactory.createTitledBorder(LaunchRes.getString("Label.DisplayPane")); //$NON-NLS-1$
classField = new JTextField();
classField.addKeyListener(keyListener);
classField.addFocusListener(focusListener);
argField = new JTextField();
argField.addKeyListener(keyListener);
argField.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if(OSPRuntime.isPopupTrigger(e)) {
XMLControl control = new XMLControlElement();
if(control.read(argField.getText())!=null) {
JPopupMenu popup = new JPopupMenu();
JMenuItem item = new JMenuItem(LaunchRes.getString("MenuItem.EncryptionTool")); //$NON-NLS-1$
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
EncryptionTool tool = EncryptionTool.getTool();
tool.open(argField.getText());
tool.setVisible(true);
}
});
popup.add(item);
popup.show(argField, e.getX(), e.getY()+8);
}
}
}
});
argField.addFocusListener(focusListener);
modelArgField = new JTextField();
modelArgField.addKeyListener(keyListener);
modelArgField.addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if(OSPRuntime.isPopupTrigger(e)) {
XMLControl control = new XMLControlElement();
if(control.read(modelArgField.getText())!=null) {
JPopupMenu popup = new JPopupMenu();
JMenuItem item = new JMenuItem(LaunchRes.getString("MenuItem.EncryptionTool")); //$NON-NLS-1$
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
EncryptionTool tool = EncryptionTool.getTool();
tool.open(modelArgField.getText());
tool.setVisible(true);
}
});
popup.add(item);
popup.show(modelArgField, e.getX(), e.getY()+8);
}
}
}
});
modelArgField.addFocusListener(focusListener);
jarField = new JTextField();
jarField.addKeyListener(keyListener);
jarField.addFocusListener(focusListener);
pathField = new JTextField();
pathField.addKeyListener(keyListener);
pathField.addFocusListener(focusListener);
tabTitleField = new JTextField();
tabTitleField.addKeyListener(keyListener);
tabTitleField.addFocusListener(focusListener);
keywordField = new JTextField();
keywordField.addKeyListener(keyListener);
keywordField.addFocusListener(focusListener);
authorField = new JTextField();
authorField.addKeyListener(keyListener);
authorField.addFocusListener(focusListener);
levelField = new JTextField();
levelField.addKeyListener(keyListener);
levelField.addFocusListener(focusListener);
languagesField = new JTextField();
languagesField.addKeyListener(keyListener);
languagesField.addFocusListener(focusListener);
commentPane = new JTextPane() {
public void paintComponent(Graphics g) {
if(OSPRuntime.antiAliasText) {
Graphics2D g2 = (Graphics2D) g;
RenderingHints rh = g2.getRenderingHints();
rh.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
rh.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
super.paintComponent(g);
}
};
commentPane.addKeyListener(keyListener);
commentPane.addFocusListener(focusListener);
commentScroller = new JScrollPane(commentPane);
commentTitle = BorderFactory.createTitledBorder(LaunchRes.getString("Label.Comments")); //$NON-NLS-1$
commentScroller.setBorder(commentTitle);
descriptionPane = new JTextPane();
descriptionPane.addKeyListener(keyListener);
descriptionPane.addFocusListener(focusListener);
descriptionScroller = new JScrollPane(descriptionPane);
descriptionTitle = BorderFactory.createTitledBorder(LaunchRes.getString("Label.Description")); //$NON-NLS-1$
descriptionScroller.setBorder(descriptionTitle);
displaySplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT) {
public void setDividerLocation(int loc) {
super.setDividerLocation(loc);
double divider = getDividerLocation();
divider /= getHeight()-getDividerSize();
setName(""+divider); //$NON-NLS-1$
}
public void setTopComponent(Component comp) {
if (comp == getTopComponent()) return;
int prev = getLastDividerLocation();
String divider = getName();
super.setTopComponent(comp);
if(divider!=null) {
double loc = Double.parseDouble(divider);
loc = Math.max(0.0, loc);
loc = Math.min(1.0, loc);
setDividerLocation(loc);
setLastDividerLocation(prev);
Runnable runner = new Runnable() {
public void run() {
JViewport view = descriptionScroller.getViewport();
view.setViewPosition(new Point(0, 0));
}
};
SwingUtilities.invokeLater(runner);
}
}
};
displaySplitPane.setBottomComponent(descriptionScroller);
displaySplitPane.setOneTouchExpandable(true);
displaySplitPane.setResizeWeight(1);
htmlPane = new JTextPane() {
public void paintComponent(Graphics g) {
if(OSPRuntime.antiAliasText) {
Graphics2D g2 = (Graphics2D) g;
RenderingHints rh = g2.getRenderingHints();
rh.put(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
rh.put(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
}
super.paintComponent(g);
}
};
htmlPane.setEditable(false);
htmlScroller = new JScrollPane(htmlPane);
htmlScroller.setBorder(displayTitle);
displaySplitPane.setTopComponent(htmlScroller);
hiddenCheckBox = new JCheckBox();
hiddenCheckBox.addActionListener(changeAction);
hiddenCheckBox.setContentAreaFilled(false);
hiddenCheckBox.setAlignmentX(Component.LEFT_ALIGNMENT);
buttonViewCheckBox = new JCheckBox();
buttonViewCheckBox.addActionListener(changeAction);
buttonViewCheckBox.setContentAreaFilled(false);
buttonViewCheckBox.setAlignmentX(Component.LEFT_ALIGNMENT);
// assemble display panel
JPanel displayPanel = new JPanel(new BorderLayout());
JToolBar nameBar = new JToolBar();
nameBar.setFloatable(false);
nameLabel = new JLabel();
labels.add(nameLabel);
nameBar.add(nameLabel);
nameBar.add(nameField);
nameBar.add(hiddenCheckBox);
displayPanel.add(nameBar, BorderLayout.NORTH);
JPanel tooltipPanel = new JPanel(new BorderLayout());
displayPanel.add(tooltipPanel, BorderLayout.CENTER);
JToolBar tooltipBar = new JToolBar();
tooltipBar.setFloatable(false);
tooltipLabel = new JLabel();
tooltipBar.add(tooltipLabel);
tooltipBar.add(tooltipField);
tooltipPanel.add(tooltipBar, BorderLayout.NORTH);
urlPanel = new JPanel(new BorderLayout());
tooltipPanel.add(urlPanel, BorderLayout.CENTER);
displayBar = new JToolBar();
displayBar.setFloatable(false);
displayLabel = new JLabel();
pathLabel = new JLabel();
pathLabel.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 2));
tabTitleLabel = new JLabel();
tabTitleLabel.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 2));
displaySpinnerModel = new SpinnerNumberModel(0, 0, 1, 1);
displaySpinner = new JSpinner(displaySpinnerModel);
JSpinner.NumberEditor editor = new JSpinner.NumberEditor(displaySpinner);
displaySpinner.setEditor(editor);
displaySpinner.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
if(pathField.getBackground()==Color.yellow) {
refreshSelectedNode();
} else {
refreshGUI();
}
}
});
displayBar.add(displayLabel);
displayBar.add(displaySpinner);
displayBar.add(pathLabel);
displayBar.add(pathField);
openDisplayChooserButton = new JButton(openIcon);
openDisplayChooserButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JPopupMenu openPopup = new JPopupMenu();
openPopup.add(openURLAction);
openPopup.add(openPDFAction);
openPopup.add(searchJarForModelAction);
openPopup.show(openDisplayChooserButton, 0, openDisplayChooserButton.getHeight());
}
});
displayBar.add(openDisplayChooserButton);
modelArgsDialog = new JDialog(frame, true);
JToolBar modelArgBar = new JToolBar();
modelArgBar.setFloatable(false);
modelArgBar.setBorder(BorderFactory.createEmptyBorder(6, 6, 6, 10));
modelArgLabel = new JLabel();
modelArgLabel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 3));
SpinnerModel model = new SpinnerNumberModel(0, 0, maxArgs-1, 1);
modelArgSpinner = new JSpinner(model);
editor = new JSpinner.NumberEditor(modelArgSpinner);
modelArgSpinner.setEditor(editor);
modelArgSpinner.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
if(argField.getBackground()==Color.yellow) {
refreshSelectedNode();
} else {
refreshGUI();
}
}
});
modelArgBar.add(modelArgLabel);
modelArgBar.add(modelArgSpinner);
modelArgBar.add(modelArgField);
modelArgBar.add(openModelArgAction);
modelArgCloseButton = new JButton(LaunchRes.getString("Dialog.Button.Close")); //$NON-NLS-1$
modelArgCloseButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
modelArgsDialog.setVisible(false);
}
});
modelArgClearButton = new JButton(LaunchRes.getString("Dialog.Button.Clear")); //$NON-NLS-1$
modelArgClearButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
int n = ((Integer) displaySpinner.getValue()).intValue();
LaunchNode node = getSelectedNode();
LaunchNode.DisplayTab tab = node.getDisplayTab(n);
if (tab!=null) {
tab.setModelArgs(new String[0]);
refreshGUI();
}
}
});
JPanel buttonPanel = new JPanel();
buttonPanel.add(modelArgClearButton);
buttonPanel.add(modelArgCloseButton);
modelArgsDialog.add(modelArgBar, BorderLayout.CENTER);
modelArgsDialog.add(buttonPanel, BorderLayout.SOUTH);
modelArgsDialog.pack();
Dimension dim = modelArgsDialog.getSize();
int w = Math.max(dim.width, 240);
modelArgsDialog.setSize(w, dim.height);
// button to show the modelArgs dialog
showModelArgsButton = new JButton();
showModelArgsButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
Point p0 = new Frame().getLocation();
if (modelArgsDialog.getLocation().x == p0.x)
modelArgsDialog.setLocationRelativeTo(showModelArgsButton);
modelArgsDialog.setVisible(true);
}
});
displayBar.add(tabTitleLabel);
displayBar.add(tabTitleField);
urlPanel.add(displayBar, BorderLayout.NORTH);
urlPanel.add(displaySplitPane, BorderLayout.CENTER);
// assemble launch panel
JPanel launchPanel = new JPanel(new BorderLayout());
JToolBar jarBar = new JToolBar();
jarBar.setFloatable(false);
jarLabel = new JLabel();
labels.add(jarLabel);
jarBar.add(jarLabel);
jarBar.add(jarField);
jarBar.add(openJarAction);
launchPanel.add(jarBar, BorderLayout.NORTH);
JPanel classPanel = new JPanel(new BorderLayout());
launchPanel.add(classPanel, BorderLayout.CENTER);
JToolBar classBar = new JToolBar();
classBar.setFloatable(false);
classLabel = new JLabel();
labels.add(classLabel);
classBar.add(classLabel);
classBar.add(classField);
classBar.add(searchJarAction);
classPanel.add(classBar, BorderLayout.NORTH);
JPanel argPanel = new JPanel(new BorderLayout());
classPanel.add(argPanel, BorderLayout.CENTER);
JToolBar argBar = new JToolBar();
argBar.setFloatable(false);
argLabel = new JLabel();
labels.add(argLabel);
argBar.add(argLabel);
model = new SpinnerNumberModel(0, 0, maxArgs-1, 1);
argSpinner = new JSpinner(model);
editor = new JSpinner.NumberEditor(argSpinner);
argSpinner.setEditor(editor);
argSpinner.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent e) {
if(argField.getBackground()==Color.yellow) {
refreshSelectedNode();
} else {
refreshGUI();
}
}
});
argBar.add(argSpinner);
argBar.add(argField);
argBar.add(openArgAction);
argPanel.add(argBar, BorderLayout.NORTH);
JPanel optionsPanel = new JPanel(new BorderLayout());
argPanel.add(optionsPanel, BorderLayout.CENTER);
JToolBar optionsBar = new JToolBar();
optionsBar.setFloatable(false);
singleVMCheckBox = new JCheckBox();
singleVMCheckBox.addActionListener(changeAction);
singleVMCheckBox.setContentAreaFilled(false);
singleVMCheckBox.setAlignmentX(Component.LEFT_ALIGNMENT);
showLogCheckBox = new JCheckBox();
showLogCheckBox.addActionListener(changeAction);
showLogCheckBox.setContentAreaFilled(false);
showLogCheckBox.setAlignmentX(Component.LEFT_ALIGNMENT);
clearLogCheckBox = new JCheckBox();
clearLogCheckBox.addActionListener(changeAction);
clearLogCheckBox.setContentAreaFilled(false);
clearLogCheckBox.setAlignmentX(Component.LEFT_ALIGNMENT);
singletonCheckBox = new JCheckBox();
singletonCheckBox.addActionListener(changeAction);
singletonCheckBox.setContentAreaFilled(false);
singletonCheckBox.setAlignmentX(Component.LEFT_ALIGNMENT);
singleAppCheckBox = new JCheckBox();
singleAppCheckBox.addActionListener(changeAction);
singleAppCheckBox.setContentAreaFilled(false);
singleAppCheckBox.setAlignmentX(Component.LEFT_ALIGNMENT);
levelDropDown = new JComboBox(OSPLog.levels);
levelDropDown.setMaximumSize(levelDropDown.getMinimumSize());
levelDropDown.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(levelDropDown.isEnabled()) {
LaunchNode node = getSelectedNode();
if(node!=null) {
node.setLogLevel((Level) levelDropDown.getSelectedItem());
}
}
}
});
Box checkBoxPanel = Box.createVerticalBox();
JToolBar bar = new JToolBar();
bar.setFloatable(false);
bar.setAlignmentX(Component.LEFT_ALIGNMENT);
bar.add(singletonCheckBox);
bar.add(Box.createHorizontalGlue());
checkBoxPanel.add(bar);
bar = new JToolBar();
bar.setFloatable(false);
bar.setAlignmentX(Component.LEFT_ALIGNMENT);
bar.add(singleVMCheckBox);
bar.add(Box.createHorizontalGlue());
checkBoxPanel.add(bar);
bar = new JToolBar();
bar.setFloatable(false);
bar.setAlignmentX(Component.LEFT_ALIGNMENT);
bar.add(singleAppCheckBox);
bar.add(Box.createHorizontalGlue());
checkBoxPanel.add(bar);
bar = new JToolBar();
bar.setFloatable(false);
bar.add(showLogCheckBox);
bar.add(Box.createHorizontalStrut(4));
bar.add(levelDropDown);
bar.add(Box.createHorizontalStrut(4));
bar.add(clearLogCheckBox);
bar.add(Box.createHorizontalGlue());
bar.setAlignmentX(Component.LEFT_ALIGNMENT);
checkBoxPanel.add(bar);
optionsTitle = BorderFactory.createTitledBorder(LaunchRes.getString("Label.Options")); //$NON-NLS-1$
Border recess = BorderFactory.createLoweredBevelBorder();
optionsBar.setBorder(BorderFactory.createCompoundBorder(recess, optionsTitle));
optionsBar.add(checkBoxPanel);
optionsPanel.add(optionsBar, BorderLayout.NORTH);
// create author tab
JPanel authorPanel = new JPanel(new BorderLayout());
// put author field on top
JToolBar authorBar = new JToolBar();
authorPanel.add(authorBar, BorderLayout.NORTH);
authorBar.setFloatable(false);
authorLabel = new JLabel();
labels.add(authorLabel);
authorBar.add(authorLabel);
authorBar.add(authorField);
// add keyword panel
JPanel keywordPanel = new JPanel(new BorderLayout());
authorPanel.add(keywordPanel, BorderLayout.CENTER);
JToolBar keywordBar = new JToolBar();
keywordPanel.add(keywordBar, BorderLayout.NORTH);
keywordBar.setFloatable(false);
keywordLabel = new JLabel();
labels.add(keywordLabel);
keywordBar.add(keywordLabel);
keywordBar.add(keywordField);
// add level panel
JPanel levelPanel = new JPanel(new BorderLayout());
keywordPanel.add(levelPanel, BorderLayout.CENTER);
JToolBar levelBar = new JToolBar();
levelPanel.add(levelBar, BorderLayout.NORTH);
levelBar.setFloatable(false);
levelLabel = new JLabel();
labels.add(levelLabel);
levelBar.add(levelLabel);
levelBar.add(levelField);
// add languages panel
JPanel languagesPanel = new JPanel(new BorderLayout());
levelPanel.add(languagesPanel, BorderLayout.CENTER);
JToolBar languagesBar = new JToolBar();
languagesPanel.add(languagesBar, BorderLayout.NORTH);
languagesBar.setFloatable(false);
languagesLabel = new JLabel();
labels.add(languagesLabel);
languagesBar.add(languagesLabel);
languagesBar.add(languagesField);
// put security panel in center
JPanel securityPanel = new JPanel(new BorderLayout());
languagesPanel.add(securityPanel, BorderLayout.CENTER);
JToolBar securityBar = new JToolBar();
securityBar.setFloatable(false);
securityPanel.add(securityBar, BorderLayout.NORTH);
securityTitle = BorderFactory.createTitledBorder(LaunchRes.getString("Label.Security")); //$NON-NLS-1$
securityBar.setBorder(BorderFactory.createCompoundBorder(recess, securityTitle));
// use vertical box to stack components in security panel
Box securityBox = Box.createVerticalBox();
securityBar.add(securityBox);
// add editorEnabled to box
bar = new JToolBar();
bar.setFloatable(false);
bar.setAlignmentX(Component.LEFT_ALIGNMENT);
editorEnabledCheckBox = new JCheckBox();
editorEnabledCheckBox.addActionListener(changeAction);
editorEnabledCheckBox.setContentAreaFilled(false);
editorEnabledCheckBox.setAlignmentX(Component.LEFT_ALIGNMENT);
bar.add(editorEnabledCheckBox);
bar.add(Box.createHorizontalGlue());
securityBox.add(bar);
// add encrypt checkbox to box
bar = new JToolBar();
bar.setFloatable(false);
bar.setAlignmentX(Component.LEFT_ALIGNMENT);
encryptCheckBox = new JCheckBox();
encryptCheckBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(encryptCheckBox.isSelected()&&(password==null)) {
password = ""; //$NON-NLS-1$
} else if(!encryptCheckBox.isSelected()) {
password = null;
}
OSPLog.finest(LaunchRes.getString("Log.Message.ChangeEncrypted")); //$NON-NLS-1$
if(tabSetName!=null) {
changedFiles.add(tabSetName);
}
refreshGUI();
}
});
encryptCheckBox.setContentAreaFilled(false);
bar.add(encryptCheckBox);
bar.add(Box.createHorizontalGlue());
securityBox.add(bar);
// add password field to box
bar = new JToolBar();
bar.setFloatable(false);
bar.setAlignmentX(Component.LEFT_ALIGNMENT);
passwordLabel = new JLabel();
passwordLabel.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 2));
bar.add(passwordLabel);
passwordEditor = new JTextField();
passwordEditor.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_ENTER) {
String text = passwordEditor.getText();
if(text.equals("")&& //$NON-NLS-1$
(!encryptCheckBox.isSelected()||!encryptCheckBox.isEnabled())) {
text = null;
}
if(text!=password) {
changedFiles.add(tabSetName);
}
password = text;
refreshGUI();
} else {
passwordEditor.setBackground(Color.yellow);
}
}
});
bar.add(passwordEditor);
bar.add(Box.createHorizontalGlue());
onLoadCheckBox = new JCheckBox();
onLoadCheckBox.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
pwRequiredToLoad = onLoadCheckBox.isSelected();
OSPLog.finest(LaunchRes.getString("Log.Message.ChangePWRequirement")); //$NON-NLS-1$
if(tabSetName!=null) {
changedFiles.add(tabSetName);
}
refreshGUI();
}
});
onLoadCheckBox.setContentAreaFilled(false);
bar.add(onLoadCheckBox);
securityBox.add(bar);
securityPanel.add(commentScroller, BorderLayout.CENTER);
// create the editor tabs
editorTabs = new JTabbedPane(SwingConstants.TOP);
editorTabs.addTab(LaunchRes.getString("Tab.Display"), displayPanel); //$NON-NLS-1$
editorTabs.addTab(LaunchRes.getString("Tab.Launch"), launchPanel); //$NON-NLS-1$
editorTabs.addTab(LaunchRes.getString("Tab.Author"), authorPanel); //$NON-NLS-1$
// editorTabs.addTab(LaunchRes.getString("Tab.Server"), serverPanel);
// create toolbar
toolbar = new JToolBar();
toolbar.setFloatable(false);
toolbar.setRollover(true);
toolbar.setBorder(BorderFactory.createLineBorder(Color.gray));
frame.getContentPane().add(toolbar, BorderLayout.NORTH);
newTabButton = new JButton(newTabAction);
toolbar.add(newTabButton);
addButton = new JButton(addAction);
toolbar.add(addButton);
cutButton = new JButton(cutAction);
toolbar.add(cutButton);
copyButton = new JButton(copyAction);
toolbar.add(copyButton);
pasteButton = new JButton(pasteAction);
toolbar.add(pasteButton);
moveUpButton = new JButton(moveUpAction);
toolbar.add(moveUpButton);
moveDownButton = new JButton(moveDownAction);
toolbar.add(moveDownButton);
titleLabel = new JLabel(LaunchRes.getString("Label.Title")); //$NON-NLS-1$
titleLabel.setBorder(BorderFactory.createEmptyBorder(0, 4, 0, 2));
toolbar.add(titleLabel);
toolbar.add(titleField);
toolbar.add(buttonViewCheckBox);
hideRootCheckBox = new JCheckBox();
hideRootCheckBox.addActionListener(changeAction);
hideRootCheckBox.setContentAreaFilled(false);
toolbar.add(hideRootCheckBox);
// create menu items
int mask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
// create new tabset item
newItem = new JMenuItem(newTabSetAction);
newItem.setAccelerator(KeyStroke.getKeyStroke('N', mask));
// create preview item
previewItem = new JMenuItem();
previewItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String base = tabSetBasePath;
previewing = true;
LaunchSet set = new LaunchSet(LaunchBuilder.this, tabSetName);
XMLControlElement control = new XMLControlElement(set);
control.setValue("filename", tabSetName); //$NON-NLS-1$
Launcher launcher = new Launcher(control.toXML());
LaunchNode node = LaunchBuilder.this.getSelectedNode();
if(node!=null) {
launcher.setSelectedNode(node.getPathString());
}
Point p = LaunchBuilder.this.frame.getLocation();
launcher.frame.setLocation(p.x+24, p.y+24);
launcher.frame.setVisible(true);
// set close operation to dispose to distinguish from default hide
launcher.frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
tabSetBasePath = base;
previewing = false;
launcher.password = password;
launcher.previewing = true;
launcher.spawner = LaunchBuilder.this;
launcher.refreshGUI();
}
});
// create other menu items
importItem = new JMenuItem(importAction);
saveJarItem = new JMenuItem(saveJarAction);
saveNodeItem = new JMenuItem(saveAction);
saveNodeAsItem = new JMenuItem(saveAsAction);
saveAllItem = new JMenuItem(saveAllAction);
openTabItem = new JMenuItem(openTabAction);
saveAllItem.setAccelerator(KeyStroke.getKeyStroke('S', mask));
saveSetAsItem = new JMenuItem(saveSetAsAction);
toolsMenu = new JMenu();
frame.getJMenuBar().add(toolsMenu, 2);
encryptionToolItem = new JMenuItem();
toolsMenu.add(encryptionToolItem);
encryptionToolItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
EncryptionTool.getTool().setVisible(true);
}
});
// replace tab listener
tabbedPane.removeMouseListener(tabListener);
tabListener = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
if(contentPane.getTopLevelAncestor()!=frame) {
return;
}
if(OSPRuntime.isPopupTrigger(e)) {
// make popup and add items
JPopupMenu popup = new JPopupMenu();
JMenuItem item = new JMenuItem(LaunchRes.getString("MenuItem.Close")); //$NON-NLS-1$
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
removeSelectedTab();
}
});
popup.add(item);
popup.addSeparator();
item = new JMenuItem(LaunchRes.getString("Menu.File.SaveAs")); //$NON-NLS-1$
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
LaunchNode node = getSelectedTab().getRootNode();
if(saveAs(node)!=null) {
int i = tabbedPane.getSelectedIndex();
tabbedPane.setTitleAt(i, node.toString());
}
refreshGUI();
}
});
popup.add(item);
final int i = tabbedPane.getSelectedIndex();
if((i>0)||(i<tabbedPane.getTabCount()-1)) {
popup.addSeparator();
}
if(i<tabbedPane.getTabCount()-1) {
item = new JMenuItem(LaunchRes.getString("Popup.MenuItem.MoveUp")); //$NON-NLS-1$
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
LaunchPanel tab = getSelectedTab();
LaunchNode root = tab.getRootNode();
LaunchBuilder.super.removeSelectedTab();
tabbedPane.insertTab(getDisplayName(root.getFileName()), null, tab, null, i+1);
tabbedPane.setSelectedComponent(tab);
tabs.add(i+1, tab);
}
});
popup.add(item);
}
if(i>0) {
item = new JMenuItem(LaunchRes.getString("Popup.MenuItem.MoveDown")); //$NON-NLS-1$
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
LaunchPanel tab = getSelectedTab();
LaunchNode root = tab.getRootNode();
LaunchBuilder.super.removeSelectedTab();
tabbedPane.insertTab(getDisplayName(root.getFileName()), null, tab, null, i-1);
tabbedPane.setSelectedComponent(tab);
tabs.add(i-1, tab);
}
});
popup.add(item);
}
popup.show(tabbedPane, e.getX(), e.getY()+8);
}
}
};
tabbedPane.addMouseListener(tabListener);
frame.pack();
displaySplitPane.setDividerLocation(0.7);
}
/**
* Sets the font level.
*
* @param level the level
*/
protected void setFontLevel(int level) {
final int prev = displaySplitPane.getLastDividerLocation();
final String divider = displaySplitPane.getName();
// set font levels of titled borders
FontSizer.setFonts(displayTitle, level);
FontSizer.setFonts(commentTitle, level);
FontSizer.setFonts(descriptionTitle, level);
FontSizer.setFonts(optionsTitle, level);
FontSizer.setFonts(securityTitle, level);
super.setFontLevel(level);
if(divider!=null) {
Runnable runner = new Runnable() {
public void run() {
double loc = Double.parseDouble(divider);
loc = Math.max(0.0, loc);
loc = Math.min(1.0, loc);
displaySplitPane.setDividerLocation(loc);
displaySplitPane.setLastDividerLocation(prev);
}
};
SwingUtilities.invokeLater(runner);
}
}
/**
* Creates the actions.
*/
protected void createActions() {
String imageFile = "/org/opensourcephysics/resources/tools/images/open.gif"; //$NON-NLS-1$
openIcon = loadIcon(imageFile);
openJarAction = new AbstractAction(null, openIcon) {
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = getJARChooser();
int result = chooser.showOpenDialog(null);
if(result==JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
String newJar = XML.getRelativePath(file.getPath());
String jars = jarField.getText();
if(jars.indexOf(newJar)>-1) {
newJar = null;
}
if(!jars.equals("")) { //$NON-NLS-1$
jars += ";"; //$NON-NLS-1$
}
if(newJar!=null) {
jarField.setText(jars+newJar);
}
OSPRuntime.chooserDir = XML.getDirectoryPath(file.getPath());
searchJarAction.setEnabled(true);
refreshSelectedNode();
}
}
};
searchJarAction = new AbstractAction(null, openIcon) {
public void actionPerformed(ActionEvent e) {
LaunchNode node = getSelectedNode();
if((node!=null)&&getClassChooser().chooseClassFor(node)) {
if(node.getOwner()!=null) {
changedFiles.add(node.getOwner().getFileName());
} else {
changedFiles.add(tabSetName);
}
refreshClones(node);
refreshGUI();
}
}
};
searchJarAction.setEnabled(false);
saveJarAction = new AbstractAction(LaunchRes.getString("LaunchBuilder.Action.CreateJar.Name")) { //$NON-NLS-1$
public void actionPerformed(ActionEvent e) {
// define base folder
File base = new File(XML.getDirectoryPath(OSPRuntime.getLaunchJarPath()));
String jarName = XML.stripExtension(LaunchBuilder.this.tabSetName)+".jar"; //$NON-NLS-1$
File target = new File(base, jarName);
// source list includes launch jar plus user-selected files/folders
final ArrayList<String> source = new ArrayList<String>();
JarTreeDialog jarChooser = new JarTreeDialog(frame, base);
// in jarChooser, preselect launch jar and all non-zip/jar child files
source.add(OSPRuntime.getLaunchJarName()); // launch jar added first
// add files in accept method
base.listFiles(new java.io.FileFilter() {
public boolean accept(File f) {
// skip jars, zip files and other undesirables
if(f.getName().endsWith(".jar")|| //$NON-NLS-1$
f.getName().endsWith(".zip")|| //$NON-NLS-1$
f.getName().endsWith(".trz")|| //$NON-NLS-1$
f.getName().endsWith(".DS_Store")|| //$NON-NLS-1$
f.getName().endsWith(".localized")|| //$NON-NLS-1$
f.getName().endsWith(".tmp")) { //$NON-NLS-1$
return false;
}
// file is accepted, so add to source list
source.add(f.getName());
return true;
}
});
jarChooser.setSelectionRelativePaths(source.toArray(new String[0]));
jarChooser.setVisible(true);
String[] paths = jarChooser.getSelectionRelativePaths();
if(paths==null) {
return;
}
source.clear();
// add paths to source list
for(int i = 0; i<paths.length; i++) {
if(paths[i].equals(OSPRuntime.getLaunchJarName())) {
// put launch jar first so later paths will overwrite
source.add(0, paths[i]);
} else {
source.add(paths[i]);
}
}
java.util.jar.Manifest manifest = JarTool.createManifest("", "org.opensourcephysics.tools.Launcher"); //$NON-NLS-1$//$NON-NLS-2$
JarTool.alwaysOverwrite(); // overwrite all with no warning
JarTool.setOwnerFrame(frame); // set owner of progress dialog
JarTool.getTool().create(source, base, target, manifest);
}
};
openArgAction = new AbstractAction(null, openIcon) {
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = getFileChooser();
int result = chooser.showOpenDialog(null);
if(result==JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
argField.setText(XML.getRelativePath(file.getPath()));
OSPRuntime.chooserDir = XML.getDirectoryPath(file.getPath());
refreshSelectedNode();
}
}
};
openModelArgAction = new AbstractAction(null, openIcon) {
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = getFileChooser();
int result = chooser.showOpenDialog(null);
if(result==JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
modelArgField.setText(XML.getRelativePath(file.getPath()));
OSPRuntime.chooserDir = XML.getDirectoryPath(file.getPath());
refreshSelectedNode();
}
}
};
openURLAction = new AbstractAction(LaunchRes.getString("Popup.MenuItem.OpenHTML")) { //$NON-NLS-1$
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = getHTMLChooser();
int result = chooser.showOpenDialog(null);
if(result==JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
pathField.setText(XML.getRelativePath(file.getPath()));
OSPRuntime.chooserDir = XML.getDirectoryPath(file.getPath());
refreshSelectedNode();
}
}
};
openPDFAction = new AbstractAction(LaunchRes.getString("Popup.MenuItem.OpenPDF")) { //$NON-NLS-1$
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = getPDFChooser();
int result = chooser.showOpenDialog(null);
if(result==JFileChooser.APPROVE_OPTION) {
File file = chooser.getSelectedFile();
pathField.setText(XML.getRelativePath(file.getPath()));
OSPRuntime.chooserDir = XML.getDirectoryPath(file.getPath());
refreshSelectedNode();
}
}
};
searchJarForModelAction = new AbstractAction(LaunchRes.getString("Popup.MenuItem.OpenModel")) { //$NON-NLS-1$
public void actionPerformed(ActionEvent e) {
Class<?> type = getClassChooser().chooseModel(pathField.getText());
if(type!=null) {
pathField.setText(type.getName());
refreshSelectedNode();
}
}
};
searchJarForModelAction.setEnabled(false);
openTabAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
LaunchNode node = getSelectedNode();
String tabName = node.toString();
for(int i = 0; i<tabbedPane.getComponentCount(); i++) {
if(tabbedPane.getTitleAt(i).equals(tabName)) {
tabbedPane.setSelectedIndex(i);
return;
}
}
XMLControl control = new XMLControlElement(node);
XMLControl cloneControl = new XMLControlElement(control);
LaunchNode clone = (LaunchNode) cloneControl.loadObject(null);
clone.setFileName(node.getFileName());
addTab(clone);
refreshGUI();
}
};
changeAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
refreshSelectedNode();
}
};
newTabSetAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
String[] prevArgs = undoManager.getLauncherState();
if(removeAllTabs()) {
if(prevArgs!=null) {
// null new args indicate not redoable
LauncherUndo.LoadEdit edit = undoManager.new LoadEdit(null, prevArgs);
undoSupport.postEdit(edit);
}
LaunchNode root = new LaunchNode(LaunchRes.getString("NewTab.Name")); //$NON-NLS-1$
addTab(root);
}
}
};
addAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
LaunchNode newNode = new LaunchNode(LaunchRes.getString("NewNode.Name")); //$NON-NLS-1$
addChildToSelectedNode(newNode);
}
};
newTabAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
LaunchNode root = new LaunchNode(LaunchRes.getString("NewTab.Name")); //$NON-NLS-1$
addTab(root);
}
};
cutAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
copyAction.actionPerformed(null);
removeSelectedNodes();
}
};
copyAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
if(getSelectedTab()!=null) {
ArrayList<LaunchNode> nodes = getSelectedTab().getSelectedNodes();
if(nodes!=null) {
NodeSet nodeSet = new NodeSet(nodes);
XMLControl control = new XMLControlElement(nodeSet);
StringSelection data = new StringSelection(control.toXML());
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(data, data);
}
}
}
};
pasteAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
try {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable data = clipboard.getContents(null);
String dataString = (String) data.getTransferData(DataFlavor.stringFlavor);
if(dataString!=null) {
XMLControlElement control = new XMLControlElement();
control.readXML(dataString);
if(control.getObjectClass()==NodeSet.class) {
NodeSet nodeSet = (NodeSet) control.loadObject(null);
for (Object[] next: nodeSet.nodes) {
LaunchNode node = (LaunchNode)next[0];
if (next.length>1 && next[1]!=null)
node.setFileName(next[1].toString());
addChildToSelectedNode(node);
}
}
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
};
importAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
getXMLChooser().setFileFilter(xmlFileFilter);
int result = getXMLChooser().showOpenDialog(null);
if(result==JFileChooser.APPROVE_OPTION) {
// open the file in an xml control
File file = getXMLChooser().getSelectedFile();
String fileName = file.getAbsolutePath();
OSPRuntime.chooserDir = XML.getDirectoryPath(file.getPath());
XMLControlElement control = new XMLControlElement(fileName);
if(control.failedToRead()) {
OSPLog.info(LaunchRes.getString("Log.Message.InvalidXML")+" "+fileName); //$NON-NLS-1$//$NON-NLS-2$
JOptionPane.showMessageDialog(null, LaunchRes.getString("Dialog.InvalidXML.Message")+" \""+XML.getName(fileName) //$NON-NLS-1$ //$NON-NLS-2$
+"\"", //$NON-NLS-1$
LaunchRes.getString("Dialog.InvalidXML.Title"), JOptionPane.WARNING_MESSAGE); //$NON-NLS-1$
return;
}
if(control.getObjectClass()==LaunchNode.class) {
// add the child node
LaunchNode child = (LaunchNode) control.loadObject(null);
child.setFileName(fileName);
addChildToSelectedNode(child);
} else {
OSPLog.info(LaunchRes.getString("Log.Message.NotLauncherFile")+" "+fileName); //$NON-NLS-1$//$NON-NLS-2$
JOptionPane.showMessageDialog(null, LaunchRes.getString("Dialog.NotLauncherFile.Message")+" \"" //$NON-NLS-1$ //$NON-NLS-2$
+XML.getName(fileName)+"\"", //$NON-NLS-1$
LaunchRes.getString("Dialog.NotLauncherFile.Title"), //$NON-NLS-1$
JOptionPane.WARNING_MESSAGE);
}
}
}
};
saveAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
LaunchNode node = getSelectedNode();
if(node.getFileName()!=null) {
save(node, node.getFileName());
refreshGUI();
}
}
};
saveAsAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
LaunchNode node = getSelectedNode();
LaunchNode parent = (LaunchNode) node.getParent();
String fileName = saveAs(node);
if(fileName!=null) {
// set ancestors to self-contained=false so this node will be saved correctly
selfContained = false;
Enumeration<?> en = node.pathFromAncestorEnumeration(node.getRoot());
while(en.hasMoreElements()) {
LaunchNode next = (LaunchNode) en.nextElement();
next.setSelfContained(false);
next.parentSelfContained = false;
}
if(parent!=null) {
if(parent.getOwner()!=null) {
changedFiles.add(parent.getOwner().getFileName());
}
refreshClones(parent);
}
}
refreshGUI();
}
};
saveAllAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
if(tabSetName.equals(LaunchRes.getString("Tabset.Name.New"))) { //$NON-NLS-1$
saveTabSetAs();
} else {
saveTabSet();
}
refreshGUI();
}
};
saveSetAsAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
saveTabSetAs();
refreshGUI();
}
};
moveUpAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
ArrayList<LaunchNode> nodes = getSelectedTab().getSelectedNodes();
if (nodes == null) return;
// move nodes up in top to bottom order
for (LaunchNode node: nodes) {
LaunchNode parent = (LaunchNode) node.getParent();
if(parent==null) {
continue;
}
int i = parent.getIndex(node);
if(i>0 && !nodes.contains(parent.getChildBefore(node))) {
getSelectedTab().treeModel.removeNodeFromParent(node);
getSelectedTab().treeModel.insertNodeInto(node, parent, i-1);
if(parent.getOwner()!=null) {
changedFiles.add(parent.getOwner().getFileName());
} else {
changedFiles.add(tabSetName);
}
}
}
getSelectedTab().setSelectedNodes(nodes);
refreshGUI();
}
};
moveDownAction = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
ArrayList<LaunchNode> nodes = getSelectedTab().getSelectedNodes();
if (nodes == null) return;
// move nodes down in bottom to top order
for (int j = nodes.size()-1; j > -1; j--) {
LaunchNode node = nodes.get(j);
LaunchNode parent = (LaunchNode) node.getParent();
if(parent==null) {
continue;
}
int i = parent.getIndex(node);
int end = parent.getChildCount();
if(i<end-1 && !nodes.contains(parent.getChildAfter(node))) {
getSelectedTab().treeModel.removeNodeFromParent(node);
getSelectedTab().treeModel.insertNodeInto(node, parent, i+1);
if(parent.getOwner()!=null) {
changedFiles.add(parent.getOwner().getFileName());
} else {
changedFiles.add(tabSetName);
}
}
}
getSelectedTab().setSelectedNodes(nodes);
refreshGUI();
}
};
// create focus listener
focusListener = new FocusAdapter() {
public void focusLost(FocusEvent e) {
refreshSelectedNode();
refreshGUI();
}
};
// create key listener
keyListener = new KeyAdapter() {
public void keyPressed(KeyEvent e) {
JComponent comp = (JComponent) e.getSource();
if((e.getKeyCode()==KeyEvent.VK_ENTER)&&(((comp!=descriptionPane)&&(comp!=commentPane))||e.isControlDown()||e.isShiftDown())) {
refreshSelectedNode();
refreshGUI();
} else {
comp.setBackground(Color.yellow);
}
}
};
}
/**
* Removes the selected node.
*/
public void removeSelectedNode() {
LaunchNode node = getSelectedNode();
if((node==null)||(node.getParent()==null)) {
return;
}
LaunchNode parent = (LaunchNode) node.getParent();
getSelectedTab().treeModel.removeNodeFromParent(node);
getSelectedTab().setSelectedNode(parent);
if(parent.getOwner()!=null) {
changedFiles.add(parent.getOwner().getFileName());
} else {
changedFiles.add(tabSetName);
}
refreshClones(parent);
refreshGUI();
}
/**
* Removes the selected nodes.
*/
public void removeSelectedNodes() {
if (getSelectedTab()==null) return;
ArrayList<LaunchNode> nodes = getSelectedTab().getSelectedNodes();
if (nodes == null) return;
LaunchNode toSelect = null; // parent of first (top) node removed
for (LaunchNode node: nodes) {
if((node.getParent()==null) || node.getRoot()!=getRootNode()) {
continue;
}
LaunchNode parent = (LaunchNode) node.getParent();
if (toSelect == null)
toSelect = parent;
getSelectedTab().treeModel.removeNodeFromParent(node);
if(parent.getOwner()!=null) {
changedFiles.add(parent.getOwner().getFileName());
} else {
changedFiles.add(tabSetName);
}
refreshClones(parent);
}
if (toSelect != null) {
getSelectedTab().setSelectedNode(toSelect);
refreshGUI();
}
}
/**
* Adds a child node to the selected node.
*
* @param child the child node to add
*/
public void addChildToSelectedNode(LaunchNode child) {
LaunchNode parent = getSelectedNode();
if((parent!=null)&&(child!=null)) {
LaunchNode[] nodes = child.getAllOwnedNodes();
for(int i = 0; i<nodes.length; i++) {
LaunchNode node = getSelectedTab().getClone(nodes[i]);
if(node!=null) {
getSelectedTab().setSelectedNode(node);
JOptionPane.showMessageDialog(frame, LaunchRes.getString("Dialog.DuplicateNode.Message")+" \""+node+"\"", //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
LaunchRes.getString("Dialog.DuplicateNode.Title"), //$NON-NLS-1$
JOptionPane.WARNING_MESSAGE);
return;
}
}
getSelectedTab().treeModel.insertNodeInto(child, parent, parent.getChildCount());
getSelectedTab().tree.scrollPathToVisible(new TreePath(child.getPath()));
child.setLaunchClass(child.launchClassName);
if(parent.getOwner()!=null) {
changedFiles.add(parent.getOwner().getFileName());
} else {
changedFiles.add(tabSetName);
}
refreshClones(parent);
refreshGUI();
}
}
/**
* Replaces clones of a specified node with new clones.
*
* @param node the current version of the node to clone
*/
protected void refreshClones(LaunchNode node) {
Map<LaunchPanel, LaunchNode> clones = getClones(node);
replaceClones(node, clones);
}
/**
* Replaces nodes with clones of the specified node.
*
* @param node the current version of the node to clone
* @param clones the current clones to replace
*/
protected void replaceClones(LaunchNode node, Map<LaunchPanel, LaunchNode> clones) {
// find clones
if(clones.isEmpty()) {
return;
}
// replace clones
XMLControl control = new XMLControlElement(node.getOwner());
Iterator<LaunchPanel> it = clones.keySet().iterator();
while(it.hasNext()) {
LaunchPanel tab = it.next();
LaunchNode clone = clones.get(tab);
LaunchNode parent = (LaunchNode) clone.getParent();
boolean expanded = tab.tree.isExpanded(new TreePath(clone.getPath()));
if(parent!=null) {
int index = parent.getIndex(clone);
tab.treeModel.removeNodeFromParent(clone);
clone = (LaunchNode) new XMLControlElement(control).loadObject(null);
clone.setFileName(node.getFileName());
tab.treeModel.insertNodeInto(clone, parent, index);
} else {
clone = (LaunchNode) new XMLControlElement(control).loadObject(null);
clone.setFileName(node.getFileName());
tab.treeModel.setRoot(clone);
}
if(expanded) {
tab.tree.expandPath(new TreePath(clone.getPath()));
}
}
}
/**
* Returns clones containing a specified node in a tab-to-node map.
*
* @param node the node
* @return the tab-to-node map
*/
protected Map<LaunchPanel, LaunchNode> getClones(LaunchNode node) {
Map<LaunchPanel, LaunchNode> clones = new HashMap<LaunchPanel, LaunchNode>();
// find clones
node = node.getOwner();
if(node==null) {
return clones;
}
Component[] tabs = tabbedPane.getComponents();
for(int i = 0; i<tabs.length; i++) {
LaunchPanel tab = (LaunchPanel) tabs[i];
LaunchNode clone = tab.getClone(node);
if((clone!=null)&&(clone!=node)) {
clones.put(tab, clone);
}
}
return clones;
}
/**
* Gets a file chooser for selecting jar files.
*
* @return the jar chooser
*/
protected static JFileChooser getJARChooser() {
getFileChooser().setFileFilter(jarFileFilter);
return fileChooser;
}
/**
* Gets a file chooser for selecting html files.
*
* @return the html chooser
*/
public static JFileChooser getHTMLChooser() {
getFileChooser().setFileFilter(htmlFileFilter);
return fileChooser;
}
/**
* Gets a file chooser for selecting pdf files.
*
* @return the pdf chooser
*/
public static JFileChooser getPDFChooser() {
getFileChooser().setFileFilter(pdfFileFilter);
return fileChooser;
}
/**
* Gets a file chooser.
*
* @return the file chooser
*/
protected static JFileChooser getFileChooser() {
if(fileChooser==null) {
fileChooser = new JFileChooser(new File(OSPRuntime.chooserDir));
allFileFilter = fileChooser.getFileFilter();
// create jar file filter
jarFileFilter = new javax.swing.filechooser.FileFilter() {
// accept all directories and *.jar files.
public boolean accept(File f) {
if(f==null) {
return false;
}
if(f.isDirectory()) {
return true;
}
String extension = null;
String name = f.getName();
int i = name.lastIndexOf('.');
if((i>0)&&(i<name.length()-1)) {
extension = name.substring(i+1).toLowerCase();
}
if((extension!=null)&&extension.equals("jar")) { //$NON-NLS-1$
return true;
}
return false;
}
// the description of this filter
public String getDescription() {
return LaunchRes.getString("FileChooser.JarFilter.Description"); //$NON-NLS-1$
}
};
// create html file filter
htmlFileFilter = new javax.swing.filechooser.FileFilter() {
// accept all directories, *.htm and *.html files.
public boolean accept(File f) {
if(f==null) {
return false;
}
if(f.isDirectory()) {
return true;
}
String extension = null;
String name = f.getName();
int i = name.lastIndexOf('.');
if((i>0)&&(i<name.length()-1)) {
extension = name.substring(i+1).toLowerCase();
}
if((extension!=null)&&(extension.equals("htm")||extension.equals("html"))) { //$NON-NLS-1$//$NON-NLS-2$
return true;
}
return false;
}
// the description of this filter
public String getDescription() {
return LaunchRes.getString("FileChooser.HTMLFilter.Description"); //$NON-NLS-1$
}
};
// create html file filter
pdfFileFilter = new javax.swing.filechooser.FileFilter() {
// accept all directories and *.pdf files.
public boolean accept(File f) {
if (f==null) return false;
if (f.isDirectory()) return true;
String extension = XML.getExtension(f.getName());
if(extension!=null && extension.equals("pdf")) return true; //$NON-NLS-1$
return false;
}
// the description of this filter
public String getDescription() {
return LaunchRes.getString("FileChooser.PDFFilter.Description"); //$NON-NLS-1$
}
};
}
fileChooser.removeChoosableFileFilter(jarFileFilter);
fileChooser.removeChoosableFileFilter(htmlFileFilter);
fileChooser.setFileFilter(allFileFilter);
FontSizer.setFonts(fileChooser, FontSizer.getLevel());
return fileChooser;
}
/**
* Gets a file filter for selecting HTML files.
*
* @return the html file filter
*/
public static javax.swing.filechooser.FileFilter getHTMLFilter() {
if (htmlFileFilter==null) {
getFileChooser();
}
return htmlFileFilter;
}
/**
* Gets a file filter for selecting PDF files.
*
* @return the pdf file filter
*/
public static javax.swing.filechooser.FileFilter getPDFFilter() {
if (pdfFileFilter==null) {
getFileChooser();
}
return pdfFileFilter;
}
/**
* Handles a mouse pressed event.
*
* @param e the mouse event
* @param tab the launch panel triggering the event
*/
protected void handleMousePressed(MouseEvent e, final LaunchPanel tab) {
super.handleMousePressed(e, tab);
if(OSPRuntime.isPopupTrigger(e)) {
TreePath path = tab.tree.getPathForLocation(e.getX(), e.getY());
if(path==null) {
return;
}
final LaunchNode node = getSelectedNode();
if(node==null) {
return;
}
// add items to popup
String fileName = node.getFileName();
if((fileName!=null)&&changedFiles.contains(fileName)) {
// add saveNode item
if(popup.getComponentCount()!=0) {
popup.addSeparator();
}
popup.add(saveNodeItem);
}
// add saveNodeAs item
if(popup.getComponentCount()!=0) {
popup.addSeparator();
}
popup.add(saveNodeAsItem);
// add openTab item
if(!node.isRoot()) {
popup.addSeparator();
openTabItem.setText(LaunchRes.getString("Action.OpenTab")); //$NON-NLS-1$
popup.add(openTabItem);
}
popup.show(tab, e.getX()+4, e.getY()+12);
}
}
/**
* Overrides Launcher exit method.
*/
protected void exit() {
OSPRuntime.setAuthorMode(false);
if(!saveAllChanges()) {
// change default close operation to prevent window closing
final int op = frame.getDefaultCloseOperation();
frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
// restore default close operation
Runnable runner = new Runnable() {
public void run() {
frame.setDefaultCloseOperation(op);
}
};
SwingUtilities.invokeLater(runner);
return;
}
super.exit();
}
/**
* Returns true if tabset is writable.
*
* @return true if writable
*/
protected boolean isTabSetWritable() {
String path = XML.getResolvedPath(tabSetName, tabSetBasePath);
Resource res = ResourceLoader.getResource(path);
File file = (res==null) ? null : res.getFile();
boolean writable = (file==null) ? true : file.canWrite();
if(!selfContained) {
for(int i = 0; i<tabbedPane.getTabCount(); i++) {
LaunchNode root = getTab(i).getRootNode();
writable = writable&&isNodeWritable(root);
}
}
return writable;
}
/**
* Returns true if node is writable.
*
* @param node the node
* @return true if writable
*/
protected boolean isNodeWritable(LaunchNode node) {
File file = node.getFile();
boolean writable = (file==null) ? true : file.canWrite();
// check node's owned child nodes if not self contained
if(!node.isSelfContained()) {
LaunchNode[] nodes = node.getChildOwnedNodes();
for(int i = 0; i<nodes.length; i++) {
writable = writable&&isNodeWritable(nodes[i]);
}
}
return writable;
}
protected static class NodeSet {
ArrayList<Object[]> nodes;
private NodeSet(ArrayList<LaunchNode> list) {
nodes = new ArrayList<Object[]>();
for (LaunchNode next: list) {
Object[] data = new Object[] {next, next.getFileName()};
nodes.add(data);
}
}
private NodeSet(XMLControl control) {
nodes = new ArrayList<Object[]>();
ArrayList<?> input = (ArrayList<?>)control.getObject("nodes"); //$NON-NLS-1$
if (input != null) {
for (Object next: input) {
nodes.add((Object[])next);
}
}
}
/**
* Returns an ObjectLoader to save and load data for this class.
*
* @return the object loader
*/
public static XML.ObjectLoader getLoader() {
return new Loader();
}
/**
* A class to save and load data for this class.
*/
static class Loader implements XML.ObjectLoader {
/**
* Saves an object's data to an XMLControl.
*
* @param control the control to save to
* @param obj the object to save
*/
public void saveObject(XMLControl control, Object obj) {
NodeSet nodeSet = (NodeSet)obj;
control.setValue("nodes", nodeSet.nodes); //$NON-NLS-1$
}
/**
* Creates a new object.
*
* @param control the XMLControl with the object data
* @return the newly created object
*/
public Object createObject(XMLControl control) {
return new NodeSet(control);
}
/**
* Loads an object with data from an XMLControl.
*
* @param control the control
* @param obj the object
* @return the loaded object
*/
public Object loadObject(XMLControl control, Object obj) {
return obj;
}
}
}
}
/*
* Open Source Physics software is free software; you can redistribute
* it and/or modify it under the terms of the GNU General Public License (GPL) as
* published by the Free Software Foundation; either version 2 of the License,
* or(at your option) any later version.
*
* Code that uses any portion of the code in the org.opensourcephysics package
* or any subpackage (subdirectory) of this package must must also be be released
* under the GNU GPL license.
*
* This software 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; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA
* or view the license online at http://www.gnu.org/copyleft/gpl.html
*
* Copyright (c) 2007 The Open Source Physics project
* http://www.opensourcephysics.org
*/