Initial commit of everything.

This commit is contained in:
Alex Lin
2015-02-26 09:02:31 -06:00
parent 8370563634
commit f0c594f841
2807 changed files with 385768 additions and 0 deletions

View File

@ -0,0 +1,55 @@
/*
* $Id: Template.java 1065 2010-09-09 19:49:28Z hchen $
*
*/
//========================================
// Package
//========================================
package trick;
//========================================
// Imports
//========================================
/**
* Template class.
*
* @since Trick 7.2.2
*/
public class Template {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
//========================================
// Constructors
//========================================
/**
* Default constructor.
*/
public Template()
{
}
//========================================
// Set/Get methods
//========================================
//========================================
// Methods
//========================================
}

View File

@ -0,0 +1,715 @@
package trick.common;
import java.awt.BorderLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JSeparator;
import javax.swing.KeyStroke;
import javax.swing.border.TitledBorder;
import joptsimple.OptionParser;
import joptsimple.OptionSet;
import joptsimple.OptionSpec;
import org.jdesktop.swingx.JXButton;
import org.jdesktop.swingx.JXLabel;
import org.jdesktop.swingx.JXPanel;
import org.jdesktop.swingx.JXTextField;
import trick.common.ui.panels.ConnectionStatusBar;
import trick.common.utils.VariableServerConnection;
/**
* Abstract base class for Trick run time GUIs, providing basic connection/disconnection functionality.
*
* @author Derek Bankieris
* @since Trick 10
*/
public abstract class RunTimeTrickApplication extends TrickApplication {
/** enumeration for application behavior on disconnect */
protected enum DisconnectBehavior {Close, Notify, Nothing}
/** indicates that the target simulation has been specified */
protected boolean targetSpecified = false;
/** reconnect on lost connetions */
protected boolean autoReconnect = false;
/** reconnecting state */
private boolean reconnecting = false;
/** application behavior on disconnect */
protected DisconnectBehavior disconnectBehavior = DisconnectBehavior.Notify;
/** handles the sending and receiving of commands to and from the Variable Server */
protected VariableServerConnection variableServerConnection;
/** status bar displaying text fields for the host and port, and a connect/disconnect button */
private ConnectionStatusBar connectionStatusBar;
/** represents the current connection status */
private boolean connected = false;
/** update period in seconds */
private double cyclePeriod;
/** minimum update period in seconds */
private double minimumCyclePeriod;
/** the settings dialog */
protected SettingsDialog settingsDialog;
/** property keys */
protected static final String hostKey = "host";
protected static final String portKey = "port";
protected static final String autoReconnectKey = "autoReconnect";
protected static final String disconnectBehaviorKey = "disconnectBehavior";
protected static final String minimumCyclePeriodKey = "minCycle";
protected static final String cyclePeriodKey = "cycle";
protected static final String xKey = "x";
protected static final String yKey = "y";
protected static final String widthKey = "width";
protected static final String heightKey = "height";
/** attempts to connect to the simulation specified by the current host name and port */
protected void connect() throws IOException {
if (!connected) {
variableServerConnection = new VariableServerConnection(
getHostName(), getPort());
setConnectionState(true);
}
else {
throw new IOException("Already connected.");
}
}
/** attempts to disconnect from the simulation */
protected void disconnect() throws IOException {
disconnect(null);
}
/**
* attempts to disconnect from the simulation. If the disconnect behavior is
* <code>DisconnectBehavior.Notify</code> and <code>exception</code> is not
* <code>null</code>, it is displayed as the reason for the disconnection.
*
* @param exception (optional) the reason for the disconnection
*/
protected void disconnect(Exception exception) throws IOException {
if (connected) {
try {
variableServerConnection.close();
}
finally {
setConnectionState(false);
switch (disconnectBehavior) {
case Close:
exit();
break;
case Notify:
if (exception != null) {
JOptionPane.showMessageDialog(getMainFrame(), exception,
"Lost Connection", JOptionPane.ERROR_MESSAGE);
}
break;
}
if (autoReconnect && exception != null) {
reconnecting = true;
connectionStatusBar.autoConnect();
}
}
}
else {
throw new IOException("Not currently connected.");
}
}
/**
* sets the connection state for both this application and the connection status bar
*
* @param connected the connection state
*/
protected void setConnectionState(boolean connected) {
reconnecting = false;
this.connected = connected;
connectionStatusBar.setConnectionState(connected);
}
/**
* gets the connection state
*
* @return the connection state
*/
protected boolean getConnectionState() {
return connected;
}
/**
* gets the host name
*
* @return the host name
*/
protected String getHostName() {
return connectionStatusBar.getHostName();
}
/**
* gets the port
*
* @return the port
*/
protected int getPort() {
return connectionStatusBar.getPort();
}
/**
* sets the target simulation to which to connect
*
* @param hostName the name of the host machine
* @param port the port on which to connect
*/
public void setTargetSimulation(String hostName, int port) {
connectionStatusBar.setTarget(hostName, port);
}
/** sends the cycle period to the Variable Server */
protected void sendCyclePeriod() {
if (connected) {
try {
variableServerConnection.setCycle(cyclePeriod);
}
catch (Exception exception) {
try {
disconnect(exception);
}
catch (Exception anotherException) {}
}
}
}
/**
* sets the period at which updates are received
*
* @param cyclePeriod the cycle period in seconds
*/
public void setCyclePeriod(double cyclePeriod) {
this.cyclePeriod = cyclePeriod < minimumCyclePeriod ? minimumCyclePeriod : cyclePeriod;
sendCyclePeriod();
}
/**
* gets the period at which updates are received
*
* @return the cycle period in seconds
*/
public double getCyclePeriod() {
return cyclePeriod;
}
/**
* sets the minimum allowed period at which updates are received
*
* @param minimumCyclePeriod the minimum allowed cycle period in seconds
*/
public void setMinimumCyclePeriod(double minimumCyclePeriod) {
this.minimumCyclePeriod = minimumCyclePeriod;
if (cyclePeriod < minimumCyclePeriod) {
setCyclePeriod(minimumCyclePeriod);
}
}
@Override
protected void initialize(final String[] arguments) {
super.initialize(arguments);
connectionStatusBar = new ConnectionStatusBar(
new AbstractAction("Connect") {
{
putValue(SHORT_DESCRIPTION, "Connect to the simulation.");
putValue(MNEMONIC_KEY, KeyEvent.VK_C);
}
public void actionPerformed(ActionEvent actionEvent) {
try {
setEnabled(false);
connect();
}
catch (Exception exception) {
if (reconnecting) {
connectionStatusBar.autoConnect();
}
else {
JOptionPane.showMessageDialog(getMainFrame(), exception,
"Failed to Connect", JOptionPane.ERROR_MESSAGE);
exception.printStackTrace(System.err);
try {
disconnect();
}
catch (IOException ioException) {}
setEnabled(true);
}
}
}
},
new AbstractAction("Disconnect") {
{
putValue(SHORT_DESCRIPTION, "Disconnect from the simulation.");
putValue(MNEMONIC_KEY, KeyEvent.VK_C);
}
public void actionPerformed(ActionEvent actionEvent) {
try {
setEnabled(false);
disconnect();
}
catch (Exception exception) {
JOptionPane.showMessageDialog(getMainFrame(), exception,
"Error While Disconnecting", JOptionPane.ERROR_MESSAGE);
exception.printStackTrace(System.err);
setEnabled(true);
}
}
},
new AbstractAction("Stop") {
{
putValue(SHORT_DESCRIPTION, "Stop searching.");
}
@Override
public void actionPerformed(ActionEvent actionEvent) {
connectionStatusBar.cancelAutoConnect();
reconnecting = false;
}
}
);
autoReconnect = Boolean.parseBoolean(
trickProperties.getProperty(autoReconnectKey, Boolean.toString(autoReconnect)));
// Set up and parse all the options.
try {
parseArguments(arguments, new OptionParser());
}
catch (Exception exception) {
System.out.println(exception);
System.exit(0);
}
// Restore previous settings.
connectionStatusBar.setTarget(
trickProperties.getProperty(hostKey, getHostName()),
Integer.parseInt(trickProperties.getProperty(portKey, Integer.toString(getPort()))));
disconnectBehavior = Enum.valueOf(DisconnectBehavior.class,
trickProperties.getProperty(disconnectBehaviorKey, disconnectBehavior.toString()));
setMinimumCyclePeriod(Double.parseDouble(trickProperties.getProperty(minimumCyclePeriodKey, "0.1")));
setCyclePeriod(Double.parseDouble(trickProperties.getProperty(cyclePeriodKey, "0.5")));
}
/**
* parses the command line arguments
*
* @param arguments the arguments
* @param optionParser the option parser to use
*/
protected void parseArguments(String[] arguments, OptionParser optionParser) {
OptionSpec<String> hostSpec = optionParser.accepts(hostKey, "The name of the machine to connect to.")
.withRequiredArg().ofType(String.class);
OptionSpec<Integer> portSpec = optionParser.accepts(portKey, "The port to connect to.")
.withRequiredArg().ofType(Integer.class);
OptionSpec<Boolean> autoReconnectSpec = optionParser.accepts(autoReconnectKey, "Reestablish lost connections.")
.withRequiredArg().ofType(Boolean.class);
String description = "[";
for (DisconnectBehavior disconnectBehavior : DisconnectBehavior.values()) {
description += disconnectBehavior + ", ";
}
description = description.substring(0, description.length() - 2) + "] The action to take on disconnect.";
OptionSpec<DisconnectBehavior> disconnectBehaviorSpec = optionParser.accepts(disconnectBehaviorKey, description)
.withRequiredArg().ofType(DisconnectBehavior.class);
OptionSpec<Double> minimumCyclePeriodSpec = optionParser.accepts(minimumCyclePeriodKey,
"Minimum update cycle period (in seconds).").withRequiredArg().ofType(Double.class);
OptionSpec<Double> cyclePeriodSpec = optionParser.accepts(cyclePeriodKey,
"Update cycle period (in seconds).").withRequiredArg().ofType(Double.class);
OptionSpec<Integer> xSpec = optionParser.accepts(xKey, "X position of the window.")
.withRequiredArg().ofType(Integer.class);
OptionSpec<Integer> ySpec = optionParser.accepts(yKey, "Y position of the window.")
.withRequiredArg().ofType(Integer.class);
OptionSpec<Integer> widthSpec = optionParser.accepts(widthKey,"Width of the window.")
.withRequiredArg().ofType(Integer.class);
OptionSpec<Integer> heightSpec = optionParser.accepts(heightKey, "Height of the window.")
.withRequiredArg().ofType(Integer.class);
optionParser.accepts("help", "Print this help message.");
OptionSet options = optionParser.parse(arguments);
if (options.has("help") || !options.nonOptionArguments().isEmpty()) {
try {
System.out.println(
"Options may be abbreviated and use a single hyphen if unambiguous.");
optionParser.printHelpOn(System.out);
}
catch (IOException e) {}
System.exit(0);
}
if (options.has(autoReconnectKey)) {
autoReconnect = options.valueOf(autoReconnectSpec);
}
if (options.has(hostKey)) {
trickProperties.setProperty(hostKey, options.valueOf(hostSpec).toString());
targetSpecified = true;
}
if (options.has(portKey)) {
trickProperties.setProperty(portKey, (options.valueOf(portSpec).toString()));
targetSpecified = true;
}
if (options.has(disconnectBehaviorKey)) {
trickProperties.setProperty(disconnectBehaviorKey, options.valueOf(disconnectBehaviorSpec).toString());
}
if (options.has(minimumCyclePeriodKey)) {
Double minimumCyclePeriod = options.valueOf(minimumCyclePeriodSpec);
if (minimumCyclePeriod < 0) {
System.out.println("Argument of option ['" + minimumCyclePeriodKey + "'] must be non-negative");
System.exit(0);
}
trickProperties.setProperty(minimumCyclePeriodKey, minimumCyclePeriod.toString());
}
if (options.has(cyclePeriodKey)) {
Double cyclePeriod = options.valueOf(cyclePeriodSpec);
if (cyclePeriod < 0) {
System.out.println("Argument of option ['" + cyclePeriodKey + "'] must be non-negative");
System.exit(0);
}
trickProperties.setProperty(cyclePeriodKey, cyclePeriod.toString());
}
if (options.has(xKey)) {
trickProperties.setProperty(xKey, (options.valueOf(xSpec).toString()));
}
if (options.has(yKey)) {
trickProperties.setProperty(yKey, (options.valueOf(ySpec).toString()));
}
if (options.has(widthKey)) {
trickProperties.setProperty(widthKey, (options.valueOf(widthSpec).toString()));
}
if (options.has(heightKey)) {
trickProperties.setProperty(heightKey, (options.valueOf(heightSpec).toString()));
}
}
@Override
protected void startup() {
super.startup();
settingsDialog = new SettingsDialog();
getMainView().setStatusBar(createStatusBar());
}
@Override
protected void ready() {
super.ready();
if (targetSpecified) {
connectionStatusBar.connectAction.actionPerformed(null);
}
}
@Override
protected JMenuBar createMenuBar() {
JMenuBar menuBar = super.createMenuBar();
JMenu menu = menuBar.getMenu(0);
// Remove look and feel menu item.
for (int i = 0; i < 2; ++i) {
menu.remove(0);
}
menu.add(new JSeparator(), 0);
menu.add(new JMenuItem(new AbstractAction("Settings") {
{
putValue(MNEMONIC_KEY, KeyEvent.VK_G);
}
public void actionPerformed(ActionEvent actionEvent) {
settingsDialog.setVisible(true);
}
}), 0);
return menuBar;
}
@Override
protected JComponent createStatusBar() {
return connectionStatusBar;
}
@Override
protected void shutdown() {
try {
String hostName = getHostName();
int port = getPort();
trickProperties.setProperty(hostKey, hostName);
trickProperties.setProperty(portKey, Integer.toString(port));
}
catch (Exception exception) {}
trickProperties.setProperty(autoReconnectKey, Boolean.toString(autoReconnect));
trickProperties.setProperty(disconnectBehaviorKey, disconnectBehavior.toString());
trickProperties.setProperty(minimumCyclePeriodKey, Double.toString(minimumCyclePeriod));
trickProperties.setProperty(cyclePeriodKey, Double.toString(cyclePeriod));
Rectangle bounds = getMainFrame().getBounds();
trickProperties.setProperty(xKey, Integer.toString(bounds.x));
trickProperties.setProperty(yKey, Integer.toString(bounds.y));
trickProperties.setProperty(widthKey, Integer.toString(bounds.width));
trickProperties.setProperty(heightKey, Integer.toString(bounds.height));
if (variableServerConnection != null) {
try {
variableServerConnection.close();
}
catch (IOException e) {}
}
super.shutdown();
}
/**
* dialog for modifying settings
*/
protected class SettingsDialog extends JDialog {
ArrayList<CommitChangesListener> commitChangesListeners = new ArrayList<CommitChangesListener>();
ArrayList<BecomingVisibleListener> becomingVisibleListeners = new ArrayList<BecomingVisibleListener>();
/** weather or not to continuously attempt to reconnect after losing a connection */
JCheckBox autoReconnectCheckBox = new JCheckBox("Automatically Reconnect") {{
setToolTipText("Automatically attempt to reconnect after losing a connection.");
}};
/** the behavior to take on disconnect */
@SuppressWarnings("unchecked") // JComboBox is generic in Java 1.7+
JComboBox disconnectBehaviorComboBox =
new JComboBox(DisconnectBehavior.values()) {{
setToolTipText("The behavior to take when the connection to the simulation is lost.");
}};
/** text field for setting the cycle period */
JXTextField cycleField = new JXTextField() {{
setColumns(3);
setHorizontalAlignment(TRAILING);
setToolTipText("Update period in seconds.");
}};
JXPanel mainPanel = new JXPanel(new GridBagLayout()) {{
GridBagConstraints constraints = new GridBagConstraints() {{
gridx = 0;
fill = BOTH;
}};
add(new JXPanel(new GridBagLayout()) {{
setBorder(new TitledBorder("Application Behavior") {{
setTitleJustification(CENTER);
}});
GridBagConstraints constraints = new GridBagConstraints() {{
gridy = 1;
}};
add(new JXLabel("On Disconnect: "), constraints);
add(disconnectBehaviorComboBox, constraints);
constraints.gridx = constraints.gridy = 0;
constraints.gridwidth = 2;
add(autoReconnectCheckBox, constraints);
}}, constraints);
add(new JXPanel() {{
setBorder(new TitledBorder("Cycle Period") {{
setTitleJustification(CENTER);
}});
add(cycleField);
add(new JXLabel(" seconds"));
}}, constraints);
}};
/**
* constructor
*/
public SettingsDialog() {
super(getMainFrame(), "Settings", true);
final AbstractAction okAction = new AbstractAction("OK") {
{
putValue(SHORT_DESCRIPTION, "Apply changes.");
putValue(MNEMONIC_KEY, KeyEvent.VK_O);
}
public void actionPerformed(ActionEvent actionEvent) {
for (CommitChangesListener commitChangesListener : commitChangesListeners) {
if (!commitChangesListener.canCommitChanges()) {
return;
}
}
try {
double period = Double.parseDouble(cycleField.getText());
if (period < 0) {
throw new NumberFormatException("Period must be non-negative.");
}
setCyclePeriod(period);
}
catch (NumberFormatException numberFormatException) {
JOptionPane.showMessageDialog(getMainFrame(), numberFormatException,
"Invalid Value", JOptionPane.ERROR_MESSAGE);
cycleField.requestFocusInWindow();
cycleField.selectAll();
return;
}
autoReconnect = autoReconnectCheckBox.isSelected();
disconnectBehavior = (DisconnectBehavior)disconnectBehaviorComboBox.getSelectedItem();
for (CommitChangesListener commitChangesListener : commitChangesListeners) {
commitChangesListener.commitChanges();
}
setVisible(false);
}
};
final JXButton okButton = new JXButton(okAction);
final AbstractAction cancelAction = new AbstractAction("Cancel") {
{
putValue(SHORT_DESCRIPTION, "Discard changes.");
putValue(MNEMONIC_KEY, KeyEvent.VK_C);
}
public void actionPerformed(ActionEvent e) {
setVisible(false);
}
};
setContentPane(new JXPanel(new BorderLayout()) {{
add(mainPanel, BorderLayout.CENTER);
add(new JXPanel(new GridLayout(1, 4)) {{
add(Box.createHorizontalGlue());
add(okButton);
add(new JXButton(cancelAction));
add(Box.createHorizontalGlue());
}}, BorderLayout.SOUTH);
}});
JRootPane rootPane = getRootPane();
rootPane.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), "SettingsDialog.cancel");
rootPane.getActionMap().put("SettingsDialog.cancel", cancelAction);
rootPane.setDefaultButton(okButton);
pack();
}
@Override
public void setVisible(boolean visible) {
if (visible) {
autoReconnectCheckBox.setSelected(autoReconnect);
disconnectBehaviorComboBox.setSelectedItem(disconnectBehavior);
cycleField.setText(Double.toString(cyclePeriod));
getRootPane().getDefaultButton().requestFocusInWindow();
setLocationRelativeTo(getMainFrame());
for (BecomingVisibleListener becomingVisibleListener : becomingVisibleListeners) {
becomingVisibleListener.becomingVisible();
}
}
super.setVisible(visible);
}
/**
* adds <code>panel</code> to this dialog
*
* @param panel the panel to add
*/
public void addPanel(JPanel panel, GridBagConstraints constraints) {
mainPanel.add(panel, constraints);
pack();
}
/**
* registers <code>becomingVisibleListener</code> to be notified just
* before this dialog becomes visible
*
* @param becomingVisibleListener the listener to be notified
*/
public void addBecomingVisibleListener(BecomingVisibleListener becomingVisibleListener) {
becomingVisibleListeners.add(becomingVisibleListener);
}
/**
* registers <code>commitChangesListener</code> to be notified when this
* dialog's OK button is pressed
*
* @param commitChangesListener the listener to be notified
*/
public void addCommitChangesListener(CommitChangesListener commitChangesListener) {
commitChangesListeners.add(commitChangesListener);
}
}
/** a listener interface for when the settings dialog becomes visible */
public interface BecomingVisibleListener {
/** called just before the settings dialog becomes visible */
public void becomingVisible();
}
/** a listener interface for when the OK button on the settings dialog is pressed */
public interface CommitChangesListener {
/**
* called just before changes are to be committed, allowing listeners to
* veto the commit. If any listener returns <code>false<code>,
* <code>commitChanges()</code> will not be called.
*
* @return whether or not to proceed with the commit
*/
public boolean canCommitChanges();
/** called after all listeners have approved the commit request */
public void commitChanges();
}
}

View File

@ -0,0 +1,744 @@
/*
* $Id: TrickApplication.java 3785 2015-01-26 14:12:13Z alin $
*
*/
//========================================
// Package
//========================================
package trick.common;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Desktop;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.EventObject;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.swing.ActionMap;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JSeparator;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.EmptyBorder;
import org.jdesktop.application.Action;
import org.jdesktop.application.ResourceMap;
import org.jdesktop.application.SingleFrameApplication;
import org.jdesktop.application.View;
import org.jdesktop.application.session.PropertySupport;
import trick.common.ui.UIUtils;
/**
* The parent class which all other Trick Java GUI applications extend.
* This intends to define common properties to all other Trick Java applications.
* It is a subclass of {@link SingleFrameApplication}.
*
*
* @author Hong Chen
* @since Trick 10
*/
public abstract class TrickApplication extends SingleFrameApplication implements PropertySupport {
//========================================
// Public data
//========================================
/** User settable properties, such as default directories, etc. */
public Properties trickProperties;
/** The resource map for the application. */
public ResourceMap resourceMap;
/** The action map for the application. */
public ActionMap actionMap;
/** The exit listener for all applications */
public ExitListener exitListener;
public static String DEFAULT_TIME_NAME = "sys.exec.out.time";
//========================================
// Protected data
//========================================
/** This application's name. */
protected String applicationName;
/** The exit listener for all applications */
protected JCheckBoxMenuItem confirmExitSelection;
/** The property directory for all applications ($HOME/.trick) */
protected static String propDirectory;
/** The look and feel short name and its class name map */
protected static Map<String, String> lafMap;
/** The look and feel short name list */
protected static String[] lafShortNames;
//========================================
// Private Data
//========================================
private static int popupInvokerType;
// if we want to put the properties into a different location, change here.
static {
try {
propDirectory = System.getProperty("user.home") + System.getProperty("file.separator") + ".trick";
} catch (Exception e) {
propDirectory = System.getenv("TRICK_USER_HOME") + System.getProperty("file.separator") + ".trick";
}
}
static {
UIManager.LookAndFeelInfo looks[] = UIManager.getInstalledLookAndFeels();
if (looks != null && looks.length > 0) {
lafMap = new HashMap<String, String>();
lafShortNames = new String[looks.length+1];
for (int i = 0; i < looks.length; i++) {
if (looks[i].getName().equals("GTK+")) {
lafMap.put("GTK", looks[i].getClassName());
lafShortNames[i] = "GTK";
} else {
lafMap.put(looks[i].getName(), looks[i].getClassName());
lafShortNames[i] = looks[i].getName();
}
}
} else {
lafShortNames = new String[1];
}
lafShortNames[lafShortNames.length-1] = "Default";
}
private JDialog aboutBox = null;
//========================================
// Constructors
//========================================
//========================================
// Actions
//========================================
/**
* closes the application. Called when the "Exit" menu item is clicked.
*/
@Action
public void exitConfirmation() {
if (confirmExitSelection.isSelected()) {
addExitListener(exitListener);
}
else {
removeExitListener(exitListener);
}
}
@Action
public void helpContents() {
}
/**
* Show the about box dialog.
*/
@Action
public void showAboutBox() {
if (aboutBox == null) {
aboutBox = createAboutBox();
}
// all those components configured in this application resource
// property file are injected through this call.
show(aboutBox);
}
/**
* Close the about box dialog.
*/
@Action
public void closeAboutBox() {
if (aboutBox != null) {
aboutBox.setVisible(false);
aboutBox = null;
}
}
@Action
public void lookAndFeel() {
if (lafMap == null) {
JOptionPane.showMessageDialog(getMainFrame(),
"Currently, the system doesn't have any Look and Feel installed!",
"Look and Feel Not Found",
JOptionPane.WARNING_MESSAGE);
} else {
int choice = -1;
if (trickProperties.getProperty(applicationName + ".lookAndFeel") == null) {
choice = JOptionPane.showOptionDialog(getMainFrame(), "Change default to:",
"Change Look and Feel",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
lafShortNames,
"Default");
} else {
String laf = UIManager.getLookAndFeel().getName();
// due to the inconsistence between the name of LookAndFeel and UIManager.LookAndFeelInfo for GTK
if (laf.startsWith("GTK")) {
laf = "GTK";
}
choice = JOptionPane.showOptionDialog(getMainFrame(), "Change " + laf + " to:",
"Change Look and Feel",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE,
null,
lafShortNames,
laf);
}
if (choice > -1 && choice < lafShortNames.length) {
if (lafMap.get(lafShortNames[choice]) != null) {
changeLookAndFeel(lafMap.get(lafShortNames[choice]));
trickProperties.setProperty(applicationName + ".lookAndFeel", lafShortNames[choice]);
} else {
// if using default, the lookandfeel property doesn't need storing
if (lafShortNames[choice].equals("Default")) {
changeLookAndFeel(UIManager.getSystemLookAndFeelClassName());
trickProperties.remove(applicationName + ".lookAndFeel");
}
}
}
}
}
//========================================
// Set/Get methods
//========================================
public static void setPopupInvoker(int type) {
popupInvokerType = type;
}
public static int getPopupInvoker() {
return popupInvokerType;
}
//========================================
// Methods
//========================================
@Override
public Object getSessionState(Component component) {
if (component instanceof JToggleButton) {
return new Boolean(((JToggleButton)component).isSelected());
}
return null;
}
@Override
public void setSessionState(Component component, Object state) {
if (component instanceof JToggleButton && state instanceof Boolean) {
((JToggleButton)component).setSelected(((Boolean)state).booleanValue());
}
}
/**
* Helper method for changing the look and feel for the application.
*
*/
protected void changeLookAndFeel(String lafClassName) {
if (lafClassName != null) {
final String finalLafClassName = lafClassName;
Runnable runnable = new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(finalLafClassName);
SwingUtilities.updateComponentTreeUI(getMainFrame());
} catch (Exception exception) {
JOptionPane.showMessageDialog(getMainFrame(),
"Can't change look and feel",
"Invalid Look and Feel",
JOptionPane.ERROR_MESSAGE);
}
}
};
SwingUtilities.invokeLater(runnable);
}
}
/**
* Concatenates all of the strings in an array and each separated by the specified separator.
*
* @param arr The string array.
* @param separator The separator for separating each string in the array.
*
* @return The concatenated string for the string array separated by the separator.
*/
public static String arrayToString(String[] arr, String separator) {
StringBuffer result = new StringBuffer();
if (arr.length > 0) {
result.append(arr[0]);
for (int i=1; i<arr.length; i++) {
result.append(separator);
result.append(arr[i]);
}
}
return result.toString();
}
/**
* Makes initialization as needed. This is called before startup().
*
* @see #startup
*/
@Override
protected void initialize(String[] args) {
// the name of this application
applicationName = getContext().getApplicationClass().getSimpleName();
// set directory for session storage
getContext().getLocalStorage().setDirectory(new File(propDirectory + System.getProperty("file.separator") + "." + applicationName));
// register property for JToggleButton class so that its state can be saved
getContext().getSessionStorage().putProperty(JToggleButton.class, this);
actionMap = getContext().getActionMap();
resourceMap = getContext().getResourceMap(getClass());
// Load any saved user settable properties from properties file
trickProperties = new Properties();
try {
FileInputStream in = new FileInputStream(propDirectory + System.getProperty("file.separator") + applicationName + ".properties");
trickProperties.load(in);
in.close();
}
catch (IOException e) {}
exitListener = new ExitListener() {
@Override
public boolean canExit(EventObject e) {
return (JOptionPane.showConfirmDialog(getMainFrame(), "Do you really want to exit?", "Confirm Exit",
JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION);
}
@Override
public void willExit(EventObject e) {}
};
// Check look and feel property
String laf = trickProperties.getProperty(applicationName + ".lookAndFeel");
if (laf != null) {
changeLookAndFeel(lafMap.get(laf));
}
}
/**
* Starts building GUI. This is called after initialize.
* Once startup() is done, ready() is called.
*
* @see #initialize
* @see #ready
*/
@Override
protected void startup() {
// Add this exit listener if the sub class likes the confirmation dialog
String defaultValue = Boolean.toString(true);
boolean savedExitProperty = new Boolean(trickProperties.getProperty(
"confirmExit", defaultValue)).booleanValue();
if (( savedExitProperty == true ) && (getExitListeners().length==0)) {
// initialize gets called again if you reconnect, so don't add another exitlistener
addExitListener(exitListener);
}
confirmExitSelection = createCheckBoxMenuItem("exitConfirmation", savedExitProperty);
}
@Override
protected void shutdown() {
super.shutdown();
boolean confirmExit = false;
if (getExitListeners().length > 0) {
confirmExit = true;
}
trickProperties.setProperty("confirmExit", Boolean.toString(confirmExit));
// Save any user settable properties to properties file in user's home directory in .trick dir
try {
FileOutputStream out = new FileOutputStream(propDirectory + System.getProperty("file.separator") + applicationName +".properties");
trickProperties.store(out, "--- Trick User Properties ---");
out.close();
} catch (IOException e) {
}
}
/**
* Creates the main {@link JComponent} for the application main {@link View}.
* Subclasses must override it.
*
* @return a {@link JComponent}.
*/
protected abstract JComponent createMainPanel();
/**
* Creates a {@link JMenuBar} for the application.
* The default menu bar includes a File menu with an Exit menu item and a check box menu item allowing the user to
* disable the exit confirmation prompt.
*
* @return a {@link JMenuBar}.
*/
protected JMenuBar createMenuBar() {
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu();
menu.setName("fileMenu");
menu.add(createMenuItem("lookAndFeel"));
menu.add(new JSeparator());
menu.add(confirmExitSelection);
menu.add(createMenuItem("quit"));
menuBar.add(menu);
menuBar.add(Box.createHorizontalGlue());
menuBar.add(UIUtils.getSmallTrickIconLabel());
return menuBar;
}
/**
* Creates a {@link JToolBar} for the application.
* Subclasses need to override this if it needs to create a tool bar.
*
* @return a {@link JToolBar}.
*/
protected JToolBar createToolBar() {
return null;
}
/**
* Creates a status bar for the application.
* Subclasses need to override this if it needs to create a status bar.
*
* @return a {@link JComponent}.
*/
protected JComponent createStatusBar() {
return null;
}
/**
* Gets the action by its name.
*
* @param actionName The text name of the action.
*
* @return A {@link javax.swing.Action} of the specified action name.
*/
protected javax.swing.Action getAction(String actionName) {
return getContext().getActionMap().get(actionName);
}
/**
* Creates a button based on the specified action name with showing
* the text for the button optionally.
*
* @param actionName The name of the action.
* @param showText <code>true</code> if text of the button needs showing,
* <code>false</code> otherwise.
*
* @return An instance of {@link JButton}.
*/
protected JButton createButton(String actionName, boolean showText) {
JButton button = new JButton();
button.setVerticalTextPosition(JButton.BOTTOM);
button.setHorizontalTextPosition(JButton.CENTER);
button.setAction(getAction(actionName));
button.setFocusable(false);
if (!showText) {
button.setText(null);
// if button text is not showing, the mnemonic is not necessary either
button.setMnemonic(-1);
}
return button;
}
/**
* Help method. Returns a JMenu named menuName that contains a JMenuItem
* for each of the specified action names (see #getAction above).
* Actions named "---" are turned into JSeparators.
*
* @param menuName The name for the {@link JMenu}.
* @param actionNames An array of action names.
*
* @return A {@link JMenu} with specified name and action names for its menu items.
*/
protected JMenu createMenu(String menuName, String[] actionNames) {
JMenu menu = new JMenu();
menu.setName(menuName);
buildMenu(menu, actionNames);
return menu;
}
/**
* Adds radio button menu items to a specified menu for the specified actions,
* and always selects the first button in the group by default.
*
* @param menu An instance of {@link JMenu} which needs adding radio button menu itmes for.
* @param actions A list of actions that are for menu items.
*/
protected JRadioButtonMenuItem[] addRadioButtonMenuItems(JMenu menu, String[] actions) {
JRadioButtonMenuItem[] menuItems = new JRadioButtonMenuItem[actions.length];
ButtonGroup group = new ButtonGroup();
for (int i = 0; i < actions.length; i++) {
menuItems[i] = new JRadioButtonMenuItem();
group.add(menuItems[i]);
menuItems[i].setAction(getAction(actions[i]));
menuItems[i].setName(actions[i] + "MenuItem");
if (i == 0) {
menuItems[i].setSelected(true);
}
menu.add(menuItems[i]);
}
return menuItems;
}
/**
* Adds a group of radio button menu items to a specified menu.
*
* @param menu An instance of {@link JMenu} which needs adding radio button menu items for.
* @param items A group of radio button menu items that need adding to a menu.
*/
protected void addRadioButtonMenuItems(JMenu menu, JRadioButtonMenuItem[] items) {
ButtonGroup group = new ButtonGroup();
for (JRadioButtonMenuItem item : items) {
group.add(item);
menu.add(item);
}
}
/**
* Help method. Returns a JPopupMenu that contains a JMenuItem
* for each of the specified action names (see #getAction above).
* Actions named "---" are turned into JSeparators.
*
* @param actionNames An array of action names.
*
* @return A {@link JPopupMenu} with specified action names for its menu items.
*/
protected JPopupMenu createPopupMenu(String[] actionNames) {
JPopupMenu menu = new JPopupMenu();
buildMenu(menu, actionNames);
return menu;
}
/**
* Helper method for setting up the menu with specified action names.
*/
private void buildMenu(JComponent menu, String[] actionNames) {
for (String actionName : actionNames) {
if (actionName.equals("---")) {
menu.add(new JSeparator());
}
else {
menu.add(createMenuItem(actionName));
}
}
}
/**
* Creates a menu item via the specified action name
*
* @param actionName the name of the action
*
* @return the menu item
*/
protected JMenuItem createMenuItem(String actionName) {
JMenuItem menuItem = new JMenuItem(getAction(actionName));
menuItem.setName(actionName + "MenuItem");
// Don't set it to null so that the icon specified with the action would be honored
//menuItem.setIcon(null);
return menuItem;
}
/**
* Creates a checkbox menu item via the specified action name
*
* @param actionName the name of the action
*
* @return the checkbox menu item
*/
protected JCheckBoxMenuItem createCheckBoxMenuItem(String actionName, boolean b) {
JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(getAction(actionName));
menuItem.setName(actionName + "CheckBoxMenuItem");
menuItem.setSelected(b);
// Don't set it to null so that the icon specified with the action would be honored
//menuItem.setIcon(null);
return menuItem;
}
/**
* Creates a simple about box {@link JDialog} that displays the standard
* Application resources, like {@code Application.title} and
* {@code Application.description}. The about box's labels and fields
* are configured by resources that are injected when the about box
* is shown. All {@code Application.version}, {@code Application.vender},
* and {@code Application.homepage} are defiend in {@link TrickApplication}
* resource property file from which any sub-class can inherit. All sub-class
* needs to have its own {@code Application.id}, {@code Application.title}, and
* {@code Application.description} to distinguish it from others.
*/
protected JDialog createAboutBox() {
JPanel panel = new JPanel(new GridBagLayout());
panel.setBorder(new EmptyBorder(0, 28, 16, 28)); // top, left, bottom, right
JLabel titleLabel = new JLabel();
titleLabel.setName("aboutTitleLabel");
GridBagConstraints c = new GridBagConstraints();
initGridBagConstraints(c);
c.anchor = GridBagConstraints.WEST;
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 32;
c.weightx = 1.0;
panel.add(titleLabel, c);
String[] fields = {"description", "version", "vendor", "homepage"};
for(String field : fields) {
JLabel label = new JLabel();
label.setName(field + "Label");
JComponent textField = new JTextField();
((JTextField)textField).setHorizontalAlignment(JTextField.RIGHT);
textField.setName(field + "TextField");
((JTextField)textField).setEditable(false);
// if for homepage, using JButton instead of JTextField so that
// the user can click the homepage link.
if ("homepage".equals(field)) {
// gets the text from the resource file for homepageTextField
final String uriStr = resourceMap.getString("homepageTextField.text");
textField = new JButton("<html><body><a href='" + uriStr + "'>" + uriStr + "</a></body></html>");
try {
final URI uri = new URI(uriStr);
((JButton)textField).addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
open(uri);
}
});
} catch (URISyntaxException ue) {
((JButton)textField).setText(uriStr);
}
}
initGridBagConstraints(c);
c.anchor = GridBagConstraints.BASELINE_TRAILING; //1.6 ONLY
c.anchor = GridBagConstraints.EAST;
panel.add(label, c);
initGridBagConstraints(c);
c.weightx = 1.0;
c.gridwidth = GridBagConstraints.REMAINDER;
c.fill = GridBagConstraints.HORIZONTAL;
panel.add(textField, c);
}
JButton closeAboutButton = new JButton();
closeAboutButton.setAction(getAction("closeAboutBox"));
initGridBagConstraints(c);
c.anchor = GridBagConstraints.EAST;
c.gridx = 1;
panel.add(closeAboutButton, c);
JDialog dialog = new JDialog(getMainFrame());
dialog.setName("aboutDialog");
dialog.add(panel, BorderLayout.CENTER);
return dialog;
}
/**
* Helper method for launching the user-default browser to show the specified {@link URI}.
*/
private void open(URI uri) {
if (Desktop.isDesktopSupported()) {
Desktop desktop = Desktop.getDesktop();
try {
desktop.browse(uri);
} catch (IOException e) {
JOptionPane.showMessageDialog(getMainFrame(),
"There is no registered application for opening \n" + uri.toString(),
"Warning", JOptionPane.WARNING_MESSAGE);
}
} else {
JOptionPane.showMessageDialog(getMainFrame(),
"This desktop is not supported to open \n" + uri.toString(),
"Warning", JOptionPane.WARNING_MESSAGE);
}
}
/**
* Helper method for same {@link GridBagConstraints} settings.
*/
private void initGridBagConstraints(GridBagConstraints c) {
c.anchor = GridBagConstraints.CENTER;
c.fill = GridBagConstraints.NONE;
c.gridwidth = 1;
c.gridheight = 1;
c.gridx = GridBagConstraints.RELATIVE;
c.gridy = GridBagConstraints.RELATIVE;
c.insets = new Insets(0,0,0,0);
c.ipadx = 4; // not the usual default
c.ipady = 4; // not the usual default
c.weightx = 0.0;
c.weighty = 0.0;
}
/**
* Creates a help menu item via action names related Java help set file name.
*
* @param menuName the name of the menu
* @param actionNames all the action names for this help menu
* @param helpSetName the Jave help set file name
*
* @return the help menu
*
*/
protected JMenu createHelpMenu(String menuName, String[] actionNames, String helpSetName) {
JMenu helpMenu = createMenu(menuName, actionNames);
return helpMenu;
}
/**
* prepends <code>${TRICK_HOME}/bin</code> to <code>executable</code> and
* runs the command in a new process with the given <code>arguments</code>.
* Redirects the new process's standard and error outputs to the
* corresponding parent steams.
*
* @param executable the trick application script to run
* @param arguments the parameters to pass to the application
*/
protected static void launchTrickApplication(String executable, String arguments) {
try {
ProcessBuilder process = new ProcessBuilder(UIUtils.getTrickBin() +
File.separator + executable, arguments);
// TODO: Uncomment these when we move to Java 1.7 again
//process.redirectOutput(ProcessBuilder.Redirect.INHERIT);
//process.redirectError(ProcessBuilder.Redirect.INHERIT);
process.start();
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
}

View File

@ -0,0 +1,9 @@
#
# $Id: RunTimeTrickApplication.properties 1752 2011-07-12 14:52:03Z dbankie $
#
connect.Action.text = &Connect
connect.Action.shortDescription = Connect to the simulation.
disconnect.Action.text = Dis&connect
disconnect.Action.shortDescription = Disconnect from the simulation.

View File

@ -0,0 +1,96 @@
#
# $Id: TrickApplication.properties 2126 2012-01-17 22:08:56Z dbankie $
#
# resources/TrickApplication.properties, property file for TrickApplication
Application.id = TrickApplication
Application.title = [Application.title not specified]
Application.version = 10.0
Application.vendor = NASA
Application.homepage = http://trick.jsc.nasa.gov/
Application.description.short = [Application.description.short not specified]
Application.description = [Application.description not specified]
Application.icon = trick_icon.png
trick.logo = trick.gif
##Application.lookAndFeel = com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel
##Application.lookAndFeel = javax.swing.plaf.nimbus.NimbusLookAndFeel
##Application.lookAndFeel = javax.swing.plaf.metal.MetalLookAndFeel
## S_sie.resource
sie.resource.file = S_sie.resource
## File menu - can be used/override in any subclass
fileMenu.text = &File
exitConfirmation.Action.text = Show Exit Confirmation Prompt
exitConfirmation.Action.shortDescription = Turn On/Off popup box that verifies \
if the user really wants to close this application.
## Help menu
helpContents.Action.text = &Help Contents
helpContents.Action.shortDescription = Show Help Contents
## About
showAboutBox.Action.text = &About...
showAboutBox.Action.shortDescription = Show the application's about box dialog
closeAboutBox.Action.text = OK
closeAboutBox.Action.shortDescription = Close the about box dialog
# Resources for the AboutBox
aboutDialog.title = About ${Application.id}
aboutTitleLabel.font = Lucida-BOLD-18
aboutTitleLabel.text = ${Application.title}
aboutTitleLabel.icon = trick_small.gif
descriptionLabel.text = Description:
descriptionTextField.text = ${Application.description}
versionLabel.text = Version:
versionTextField.text = ${Application.version}
vendorLabel.text = Vendor:
vendorTextField.text = ${Application.vendor}
homepageLabel.text = Homepage:
homepageTextField.text = ${Application.homepage}
## Look and Feel
lookAndFeel.Action.text = &Look and Feel
lookAndFeel.Action.ShortDescription = Change Look and Feel
## Specify certain action icons here so that they can be put in common
## resources and shared by different applications
## For TrickDPApplication
# newSession action icon for TrickDPApplication
newSession.Action.icon = filenew.gif
# saveSession action icon for TrickDPApplication
saveSession.Action.icon = filesave.gif
# openSession action icon for TrickDPApplication
openSession.Action.icon = fileopen.gif
## For TrickQPApplication
# newDP action icon for TrickQPApplication
newDP.Action.icon = filenew.gif
# saveDP action icon for TrickQPApplication
saveDP.Action.icon = filesave.gif
# openDP action icon for TrickQPApplication
openDP.Action.icon = fileopen.gif
## For DreApplication
# openDR action icon for DreApplication
openDR.Action.icon = fileopen.gif
# saveDR action icon for DreApplication
saveDR.Action.icon = filesave.gif
treeNodeClosed.icon = firefox_folder_closed.gif
treeNodeOpen.icon = firefox_folder_open.gif
treeNodeLeaf.icon = gnome-fs-regular.gif

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 608 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 360 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 110 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 67 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 B

View File

@ -0,0 +1,156 @@
/*
* $Id: TrickFileFilter.java 3601 2014-07-23 21:13:49Z hchen3 $
*
*/
//========================================
// Package
//========================================
package trick.common.ui;
//========================================
// Imports
//========================================
import java.io.File;
import java.io.FileFilter;
/**
* A {@link FileFilter} that accepts specified file or directory name.
*
* @author Hong Chen
* @since Trick 10
*/
public class TrickFileFilter implements java.io.FileFilter {
//========================================
// Public data
//========================================
public final static int SIM_RUN = 1;
public final static int SIM_DP = 2;
public final static int LOG = 3;
public final static int XML = 4;
public final static int HEADER = 5;
public final static int TRK = 6;
public final static int CSV = 7;
public final static int H5 = 8;
// this includes all trick data record related files, .header, .trk, .csv and .h5
public final static int TRICK_DATA_RECORD = 9;
// for postscript files
public final static int PS = 10;
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
private int type;
private String filenameMatch = null;
//========================================
// Constructors
//========================================
/**
* Default constructor.
*/
public TrickFileFilter(int type) {
this.type = type;
}
//========================================
// Set/Get methods
//========================================
/**
* Gets the type of this {@link TrickFileFilter}.
*
* @return The type of the filter.
*/
public int getType() {
return type;
}
/**
* Sets file name mathing criteria for the filter.
*
* @param matching This filter cannot be accepted if {@link File} is a file and
* its name doesn't contain the matching string.
*/
public void setFilenameMatch(String matching) {
filenameMatch = matching;
}
//========================================
// Methods
//========================================
/**
* Required by {@link FileFilter}.
*
* @see javax.swing.filechooser.FileFilter#accept(java.io.File)
*/
public boolean accept(File f) {
boolean ret;
switch (type) {
case SIM_RUN:
// only directories are considered
if (f.isFile()) {
ret = false;
}
ret = f.getName().startsWith("SIM") || f.getName().startsWith("RUN") || f.getName().startsWith("SET") || f.getName().startsWith("MONTE_RUN");
// ignore all RUN dirs under another RUN dirs unless these RUN dirs are under SIM_, SET_, or MONTE_RUN
if (f.getName().startsWith("RUN") && f.getParentFile().getName().startsWith("RUN")) {
ret = false;
}
break;
case SIM_DP:
ret = (f.isDirectory() && f.getName().startsWith("SIM"))
|| (f.isFile() && f.getName().startsWith("DP"))
|| (f.isDirectory() && f.getName().startsWith("SET"))
|| (f.isDirectory() && f.getName().equals("DP_Product"))
|| (f.isDirectory() && f.getName().equals("DP_Products"));
break;
case LOG:
ret = f.isFile() && f.getName().toLowerCase().startsWith("log");
break;
case XML:
ret = f.isFile() && f.getName().toLowerCase().endsWith(".xml");
break;
case HEADER:
ret = f.isFile() && f.getName().toLowerCase().endsWith(".header");
break;
case TRK:
ret = f.isFile() && f.getName().toLowerCase().endsWith(".trk");
break;
case CSV:
ret = f.isFile() && f.getName().toLowerCase().endsWith(".csv");
break;
case H5:
ret = f.isFile() && f.getName().toLowerCase().endsWith(".h5");
break;
case TRICK_DATA_RECORD:
ret = f.isFile() &&
(f.getName().toLowerCase().endsWith(".header") ||
f.getName().toLowerCase().endsWith(".trk") ||
f.getName().toLowerCase().endsWith(".csv") ||
f.getName().toLowerCase().endsWith(".mat") ||
f.getName().toLowerCase().endsWith(".h5")
);
break;
case PS:
ret = f.isFile() && f.getName().toLowerCase().endsWith(".ps");
break;
default:
ret = true;
}
if (filenameMatch != null && filenameMatch.length() > 0) {
// only check the additional match when is a file
if (f.isFile()) {
ret = ret && f.getName().contains(filenameMatch);
}
}
return ret;
}
}

View File

@ -0,0 +1,864 @@
/*
* $Id: UIUtils.java 3771 2014-12-11 20:37:29Z hchen3 $
*
*/
//========================================
// Package
//========================================
package trick.common.ui;
//========================================
// Imports
//========================================
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.HeadlessException;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.net.URL;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.DefaultComboBoxModel;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFileChooser;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.ListSelectionModel;
import javax.swing.filechooser.FileNameExtensionFilter;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
import org.jdesktop.swingx.JXLabel;
import org.jdesktop.swingx.JXTitledPanel;
import trick.common.TrickApplication;
import trick.common.utils.TrickColors;
/**
* Utilities class for UI.
*
* @author Hong Chen
* @since Trick 7
*/
public class UIUtils {
//========================================
// Public data
//========================================
public final static String DOCUMENT_STYLE_REGULAR = "regular";
public final static String DOCUMENT_STYLE_REGULAR_ITALIC = "regularItalic";
public final static String DOCUMENT_STYLE_REGULAR_BOLD_BLUE = "regularBoldBlue";
public final static String DOCUMENT_STYLE_REGULAR_BOLD_BLUE_SHADE = "regularBoldBlueShade";
public final static String DOCUMENT_STYLE_REGULAR_LARGE_BOLD_BLUE_SHADE = "regularLargeBoldBlueShade";
public final static String DOCUMENT_STYLE_REGULAR_LARGE_BOLD_BLUE = "regularLargeBoldBlue";
public final static String DOCUMENT_STYLE_REGULAR_SMALL = "regularSmall";
// For numbers that only needs to 2 fraction points.
public static final NumberFormat TWO_FRACTION_FORMATTER = new DecimalFormat("0.00");
public final static int CANCEL_OPTION = 0;
public final static int OK_OPTION = 1;
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
// for env variables
private final static int HOME = 0;
private final static int TRICK_HOME = 1;
private final static int TRICK_USER_HOME = 2;
private final static int TRICK_VER = 3;
private final static int TRICK_HOST_CPU = 4;
private final static int TRICK_LOGO = 5;
//========================================
// Constructors
//========================================
//========================================
// Set/Get methods
//========================================
/**
* Gets the value of HOME environment variable.
*
* @return The value of HOME.
*/
public static String getUserHome() {
return getTrickEnv(HOME);
}
/**
* Gets the value of TRICK_USER_HOME environment variable.
*
* @return The value of TRICK_USER_HOME. If it is not defined, return
* the value of HOME.
*/
public static String getTrickUserHome() {
String ret = getTrickEnv(TRICK_USER_HOME);
if (ret == null) {
ret = getTrickEnv(HOME);
}
return ret;
}
/**
* Gets the value of TRICK_HOME environment variable.
*
* @return The value of TRICK_HOME. If it is not defined, return
* the value of HOME.
*/
public static String getTrickHome() {
String ret = getTrickEnv(TRICK_HOME);
if (ret == null) {
ret = getTrickEnv(HOME);
}
return ret;
}
/**
* Gets the text of $TRICK_HOME/bin.
*
* @return The text of $TRICK_HOME/bin. If it is not defined, return
* the text of $HOME/bin.
*/
public static String getTrickBin() {
String ret = getTrickEnv(TRICK_HOME) ;
if (ret == null) {
ret = getTrickEnv(HOME);
}
ret = ret + File.separator + "bin";
return ret;
}
/**
* Gets the value of TRICK_VER environment variable.
*
* @return The value of TRICK_VER.
*/
public static String getTrickVersion() {
return getTrickEnv(TRICK_VER);
}
/**
* Gets the value of TRICK_HOST_CPU environment variable.
*
* @return The value of TRICK_HOST_CPU.
*/
public static String getTrickHostCPU() {
return getTrickEnv(TRICK_HOST_CPU);
}
/**
* Gets the value of TRICK_LOGO environment variable.
*
* @return The value of TRICK_LOGO.
*/
public static String getTrickLogo() {
return getTrickEnv(TRICK_LOGO);
}
//========================================
// Methods
//========================================
/**
* Helper method for getting Trick environment variable value.
*
* @param type The type of the variable.
*
* @return The environment variable value.
*/
private static String getTrickEnv(int type) {
String value = null;
switch (type) {
case TRICK_HOME:
value = System.getenv("TRICK_HOME");
break;
case TRICK_USER_HOME:
value = System.getenv("TRICK_USER_HOME");
break;
case TRICK_VER:
value = System.getenv("TRICK_VER");
break;
case HOME:
value = System.getenv("HOME");
break;
case TRICK_HOST_CPU:
value = System.getenv("TRICK_HOST_CPU");
break;
case TRICK_LOGO:
value = System.getenv("TRICK_LOGO");
break;
default:
break;
}
return value;
}
/**
* Gets html hex for a {@link Color}.
*
* @param c An instance of {@link Color} which the hex number is getting from.
*
* @return "#" followed by exactly 6 hex digits.
*
*/
public final static String colorToHTMLHex(Color c) {
String s = Integer.toHexString( c.getRGB() & 0xffffff );
if ( s.length() < 6 ) { // pad on left with zeros
s = "000000".substring( 0, 6 - s.length() ) + s;
}
return '#' + s;
}
/**
* Gets the color based on the 6-digit html hex string or color name.
*
* @param colorStrOrCode The 6-digit hex leading by "#" in string or a supported name of a color.
*
* @return An instance of {@link Color}.
*/
public final static Color getColorFromHTMLHex(String colorStrOrCode) {
if (colorStrOrCode == null || "".equals(colorStrOrCode)) {
return null;
}
Color c = null;
try {
c = Color.decode(colorStrOrCode);
} catch (NumberFormatException nfe) {
c = TrickColors.getColor(colorStrOrCode);
}
return c;
}
/**
* Checks to see if a JComboBox contains an object.
*/
public static boolean comboBoxContains(DefaultComboBoxModel model, Object obj) {
for (int i = 0; i < model.getSize(); i++) {
if (obj.equals(model.getElementAt(i))) {
return true;
}
}
return false;
}
/**
* Returns whether the mouse click is a right click.
*
* @param e a {@link MouseEvent} to test.
*
* @return <code>true</code> if right button was pressed, <code>false</code> otherwise.
*/
public static boolean isRightMouseClick(MouseEvent e) {
boolean rval = false;
if( (e.getModifiers()&MouseEvent.BUTTON3_MASK)==MouseEvent.BUTTON3_MASK ) {
rval = true;
}
return rval;
}
/**
* Check to see if the mouse click is double click.
*
* @param e a {@link MouseEvent} to test.
*
* @return <code>true</code> if is double-clicking, <code>false</code> otherwise.
*/
public static boolean isDoubleClick(MouseEvent e) {
boolean rval = false;
if (e.getClickCount() == 2) {
rval = true;
}
return rval;
}
/**
* Check to see if the specified directory has "log" files.
*
* @param dir A file directory.
*
* @return <code>true</code> if the specified directory has log files, <code>false</code> otherwise.
*/
public static boolean hasLogFile(File dir) {
return hasSpecifiedFile(dir, TrickFileFilter.LOG);
}
/**
* Check to see if the specified directory has .header files.
*
* @param dir A file directory.
*
* @return <code>true</code> if the specified directory has .header files, <code>false</code> otherwise.
*/
public static boolean hasHeaderFile(File dir) {
return hasSpecifiedFile(dir, TrickFileFilter.HEADER);
}
/**
* Check to see if the specified directory has .trk files.
*
* @param dir A file directory.
*
* @return <code>true</code> if the specified directory has .trk files, <code>false</code> otherwise.
*/
public static boolean hasTRKFile(File dir) {
return hasSpecifiedFile(dir, TrickFileFilter.TRK);
}
/**
* Check to see if the specified directory has .csv files.
*
* @param dir A file directory.
*
* @return <code>true</code> if the specified directory has .csv files, <code>false</code> otherwise.
*/
public static boolean hasCSVFile(File dir) {
return hasSpecifiedFile(dir, TrickFileFilter.CSV);
}
/**
* Helper method for checking to see if a particular directory has certain files.
*
* @param dir A directory.
* @param type The Trick file type. See {@link TrickFileFilter} for all supported types.
*
* @return <code>true</code> if the specified directory has specified files, <code>false</code> otherwise.
*/
private static boolean hasSpecifiedFile(File dir, int type) {
File[] tmp = dir.listFiles(new TrickFileFilter(type));
if (tmp == null || tmp.length < 1) {
return false;
}
return true;
}
/**
* Returns a file's name without its extension. If no extension found, return
* the original file name.
*/
public static String getFileNameWithoutExtension(File file) {
String fileName = file.getName();
int dotLoc = fileName.lastIndexOf('.');
if (dotLoc > 0 && dotLoc <= fileName.length() - 2) {
return fileName.substring(0, dotLoc);
}
return fileName;
}
/**
* Returns an array of abstract pathnames denoting the files that satisfy the specified filter.
*
* @param dir A directory.
* @param type The Trick file type. See {@link TrickFileFilter} for all supported types.
*
* @return An array of abstract pathnames denoting the files, <code>null</code>
* if the specified dir is null or is not a directory.
*/
public static File[] getListFiles(File dir, int type) {
if (dir != null && dir.isDirectory()) {
return dir.listFiles(new TrickFileFilter(type));
}
return null;
}
/**
* Returns an instance of {@link JXLabel} that displays trick small icon for different GUIs
* with version information tool tip.
*
* @return An instance of {@link JXLabel} with its icon set to trick small icon and
* tool tip set to the trick version.
*/
public static JXLabel getSmallTrickIconLabel() {
JXLabel label = new JXLabel();
String desc = "Trick Version " + getTrickVersion();
label.setToolTipText(desc);
ImageIcon smallIcon = createImageIcon("trick_small.gif");
if (smallIcon != null) {
smallIcon.setDescription(desc);
label.setIcon(smallIcon);
}
return label;
}
/**
* Search to see if an input string has the search string.
* The search string can have "*". If there is no wildcard,
* it simply checks if inputStr string contians the searchStr string.
*
* @param inputStr - the input search string.
* @param searchStr - the search string which searching is based upon.
*
* @return - true if found, false otherwise.
*/
public static boolean searchWithWildcard(String inputStr, String searchStr) {
StringBuffer patternBuf = new StringBuffer();
if (searchStr.contains("*")) {
String[] parts = searchStr.split("\\*");
for (String part : parts) {
patternBuf.append(".*(");
patternBuf.append(part);
patternBuf.append(")");
}
patternBuf.append(".*");
Pattern pattern = Pattern.compile(patternBuf.toString());
Matcher matcher = pattern.matcher(inputStr);
return matcher.find();
} else {
return (inputStr.contains(searchStr));
}
}
/**
* Opens a directory only file chooser for a particular directory
* with specified dialog title.
*
* @param chooserTitle The title for the dialog.
* @param dir The directory for the file chooser.
* @param parent The parent component for opening the file chooser.
*
* @return The selected directory.
*/
public static File chooseDir(String chooserTitle, String dir, Component parent) {
JFileChooser chooser = new JFileChooser();
if (dir == null) {
chooser.setCurrentDirectory(new java.io.File("."));
} else {
File file = new java.io.File(dir);
if (!file.exists()) {
file = new java.io.File(".");
}
chooser.setCurrentDirectory(file);
}
chooser.setDialogTitle(chooserTitle);
chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
int chooserState = chooser.showDialog(parent, "Ok");
if (chooserState == JFileChooser.APPROVE_OPTION) {
return chooser.getSelectedFile();
} else {
return null;
}
}
/**
* Opens a file chooser and returns the selected file if available.
*
* @param dir The directory from which a file will be selected.
* @param fileName The initial file name that is prompted in the file field.
* @param fileNameExtension The desired file extension.
* @param parent The parent component that makes the call.
*
* @return An instance of {@link File} if the selection is successful, <code>null</code> otherwise.
*/
public static File chooseOpenFile(String dir, String fileName, String fileNameExtension, Component parent) {
JFileChooser chooser = new JFileChooser();
File selectedFile = null;
File fileDir = null;
// if dir is not specified or the dir doesn't exist, use the current directory
if (dir == null) {
fileDir = new File(".");
} else {
fileDir = new File(dir);
}
if (!fileDir.exists()) {
fileDir = new File(".");
}
chooser.setCurrentDirectory(fileDir);
if (fileName != null) {
chooser.setSelectedFile(new java.io.File(fileName));
}
if (fileNameExtension != null) {
chooser.setFileFilter(new FileNameExtensionFilter(fileNameExtension+" file", fileNameExtension));
}
chooser.setDialogTitle("Open File");
boolean isValid = true;
do {
int chooserState = chooser.showDialog(parent, "Ok");
if (chooserState == JFileChooser.APPROVE_OPTION) {
selectedFile = chooser.getSelectedFile();
if (!selectedFile.exists()) {
JOptionPane.showMessageDialog(parent,
selectedFile.getName()+" does not exist. Please choose another file!",
"File Not Found",
JOptionPane.WARNING_MESSAGE);
} else {
isValid = false;
}
} else {
return null;
}
} while (isValid);
return selectedFile;
}
/**
* Saves text to a specified file.
*
* @param contents The text contents that need to be saved.
* @param file The file which the text will be saved to.
*/
public static void saveTextFile(String contents, File file) {
try {
PrintWriter out = new PrintWriter(new FileWriter(file));
out.print(contents);
out.close();
} catch (IOException ioe) {
}
}
/**
* Opens a file chooser and let the user to either choose or specify a file for saving purpose.
*
* @param dir The directory which the file chooser works from initially.
* @param initialFile The file that is set initially.
* @param fileNameExtension The desired file extension.
* @param parent The parent component that wants to open the file chooser.
*
* @return The specified the file, <code>null</code> if canceled.
*/
public static File chooseSaveFile(String dir, String initialFile, String fileNameExtension, Component parent) {
JFileChooser chooser = new JFileChooser();
File selectedFile = null;
String selectedFileName = null;
File fileDir = null;
// if dir is not specified or the dir doesn't exist, use the current directory
if (dir == null) {
fileDir = new File(".");
} else {
fileDir = new File(dir);
}
if (!fileDir.exists()) {
fileDir = new File(".");
}
chooser.setCurrentDirectory(fileDir);
if (initialFile != null) {
chooser.setSelectedFile(new java.io.File(initialFile));
}
if (fileNameExtension != null) {
chooser.setFileFilter(new FileNameExtensionFilter(fileNameExtension + " file", fileNameExtension));
}
chooser.setDialogTitle("Save File");
boolean isValid = true;
do {
int chooserState = chooser.showDialog(parent, "Ok");
if (chooserState == JFileChooser.APPROVE_OPTION) {
selectedFile = chooser.getSelectedFile();
selectedFileName = selectedFile.getName();
if (fileNameExtension != null) {
// 1.append the specified file extension if there is no extension.
// 2.append the desired extension if there is an extension which is not the same as specified
if (selectedFileName.indexOf('.') == -1 ||
(selectedFileName.indexOf('.') != -1 && !selectedFileName.endsWith(fileNameExtension))) {
selectedFileName += "." + fileNameExtension;
}
selectedFile = new File(selectedFile.getParentFile(), selectedFileName);
}
if (selectedFile.exists()) {
int choice = JOptionPane.showConfirmDialog(parent,
selectedFileName + " already exists. Overwrite it?",
"Overwrite File",
JOptionPane.YES_NO_OPTION);
// If "Yes" is selected
if (choice == JOptionPane.YES_OPTION) {
isValid = false;
}
} else {
isValid = false;
}
} else {
return null;
}
} while (isValid);
return selectedFile;
}
/**
* Shows a warning dialog with specified message and title.
*
* @param title The title for the dialog window.
* @param msg The message text for the dialog window.
* @param parent The parent component that wants to open the dialog.
*
* @return The selected choice.
*/
public static int showOkCancelDialog(String title, String msg, Component parent) {
Object[] options = new Object[2];
options[OK_OPTION] = "Ok";
options[CANCEL_OPTION] = "Cancel";
int choice = JOptionPane.showOptionDialog(parent,
msg,
title,
JOptionPane.DEFAULT_OPTION,
JOptionPane.WARNING_MESSAGE,
null,
options,
options[CANCEL_OPTION]);
return choice;
}
/**
* Shows a list input dialog. Forces to use a {@link JList} for user to input.
*
* JOptionPane.showInputDialog with the same arguments as this method uses
* a component for user to input and it is upt to the UI to decide how best to represent the
* <code>selectionValues</code>.
* Normally, it's a {@link JComboBox} if less than 20 <code>selectionValues</code>,
* {@link JList} if equal or greater than 20 <code>selectionValues</code>, or
* {@link JTextField} if null <code>selectionValues</code>.
*/
public static Object showListInputDialog(Component parentComponent, Object message, String title, int messageType,
Icon icon, Object[] selectionValues, Object initialSelectionValue)
throws HeadlessException {
JOptionPane pane = new JOptionPane();
JList list = getSingleSelectionList(pane, selectionValues, initialSelectionValue);
JScrollPane sp = new JScrollPane(list);
list.ensureIndexIsVisible(list.getSelectedIndex());
pane.setMessage(new Object[] { message, sp});
pane.setMessageType(JOptionPane.QUESTION_MESSAGE);
pane.setOptionType(JOptionPane.OK_CANCEL_OPTION);
JDialog dialog = pane.createDialog(parentComponent, title);
dialog.setVisible(true);
dialog.dispose();
Object value = pane.getInputValue();
// this choice is either JOptionPane.OK_OPTION or JOptionPane.CANCEL_OPTION,
// if null, meaning the user closed the window without choosing anything
Object choice = pane.getValue();
if (choice == null || ((Integer)choice).intValue() == JOptionPane.CANCEL_OPTION) {
return initialSelectionValue;
}
if (value == JOptionPane.UNINITIALIZED_VALUE) {
return null;
}
return value;
}
/**
* Helper method and only used by <code>showListInputDialog</code> method.
*/
@SuppressWarnings("unchecked")
private static JList getSingleSelectionList(final JOptionPane optionPane, Object[] values, Object initialValue) {
JList list = new JList(values);
list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
if(initialValue != null) {
list.setSelectedValue(initialValue, true);
}
MouseListener mouseListener = new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
JList list = (JList)e.getSource();
int index = list.locationToIndex(e.getPoint());
optionPane.setInputValue(list.getModel().getElementAt(index));
if (isDoubleClick(e)) {
// close the pane once the user selects a value by double-clicking
optionPane.setValue(JOptionPane.CLOSED_OPTION);
}
}
};
list.addMouseListener(mouseListener);
return list;
}
/**
* Returns an {@link ImageIcon} for the specified full file path or
* a file in common/resources.
*
* @param fileName The name or the full path of the image file.
*
* @return an instance of {@link ImageIcon} for the specified image,
* null if the image file can't be found.
*/
public static ImageIcon createImageIcon(String fileName) {
ImageIcon imgIcon = null;
// if the fileName is a full path
if (fileName.indexOf(System.getProperty("file.separator")) != -1) {
imgIcon = new ImageIcon(fileName);
} else {
// if only a file name specified, try to find it at common resources folder
URL imgURL = TrickApplication.class.getResource("resources" + System.getProperty("file.separator") + fileName);
if (imgURL != null) {
imgIcon = new ImageIcon(imgURL);
}
}
if (imgIcon == null) {
System.err.println("Couldn't find file: " + fileName);
}
return imgIcon;
}
/**
* Returns a {@link InputStream} for the specified file path or a file
* in common/resources.
*
* @param fileName The name of a file in common/resources or a full file path.
*
* @return an instance of {@link InputStream} for the specified file,
* null if the specified file can't be found.
*/
public static InputStream getInputStreamForFile(String fileName) {
try {
InputStream ins = null;
// if the fileName is a full path
if (fileName.indexOf(System.getProperty("file.separator")) != -1) {
ins = new FileInputStream(fileName);
} else {
// if only a file name, then find it at common resources area
ins = TrickApplication.class.getResourceAsStream("resources" + System.getProperty("file.separator") + fileName);
}
return ins;
} catch (NullPointerException npe) {
return null;
} catch (FileNotFoundException fnfe) {
return null;
}
}
/**
* Creates titled panel with content view plus search capability if applicable.
*
* @param title The title of the panel.
* @param contentComponent The searchable component for the content.
* @param findPanel The panel for find/search function.
* If <code>null</code>, then only a titled panel is created.
*
* @return A titled panel with find bar for search feature.
*/
public static JPanel createSearchableTitledPanel(String title,
JComponent contentComponent,
JPanel findPanel) {
JXTitledPanel titledPanel = new JXTitledPanel();
titledPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(""));
titledPanel.setTitle(title);
titledPanel.add(new JScrollPane(contentComponent), BorderLayout.CENTER);
titledPanel.setMinimumSize(new Dimension(300, 250));
if (findPanel != null) {
titledPanel.add(findPanel, BorderLayout.SOUTH);
}
return titledPanel;
}
/**
* Creates a JTextPane that displays detail information and the information
* is StyledDocument.
*
* @return a JTextPane that has different document styles.
*/
public static JTextPane createReadingTextPane() {
JTextPane textPane = new JTextPane();
textPane.setEditable(false);
textPane.setPreferredSize(new Dimension(400, 200));
StyledDocument document = textPane.getStyledDocument();
addStylesToDocument(document);
return textPane;
}
/**
* Adds styles to a StyledDocument as specified doc.
*
* @param doc a StyledDocument to add styles to.
*/
private static void addStylesToDocument(StyledDocument doc) {
//Initialize some styles.
Style def = StyleContext.getDefaultStyleContext().getStyle(StyleContext.DEFAULT_STYLE);
Style regular = doc.addStyle(DOCUMENT_STYLE_REGULAR, def);
StyleConstants.setFontFamily(def, "SansSerif");
Style s = doc.addStyle(DOCUMENT_STYLE_REGULAR_ITALIC, regular);
StyleConstants.setItalic(s, true);
s = doc.addStyle(DOCUMENT_STYLE_REGULAR_BOLD_BLUE, regular);
StyleConstants.setBold(s, true);
StyleConstants.setForeground(s, Color.blue);
s = doc.addStyle(DOCUMENT_STYLE_REGULAR_SMALL, regular);
StyleConstants.setFontSize(s, 10);
s = doc.addStyle(DOCUMENT_STYLE_REGULAR_LARGE_BOLD_BLUE_SHADE, regular);
StyleConstants.setFontSize(s, 14);
StyleConstants.setBold(s, true);
StyleConstants.setBackground(s, Color.lightGray);
StyleConstants.setForeground(s, Color.blue);
s = doc.addStyle(DOCUMENT_STYLE_REGULAR_LARGE_BOLD_BLUE, regular);
StyleConstants.setFontSize(s, 14);
StyleConstants.setBold(s, true);
StyleConstants.setForeground(s, Color.blue);
s = doc.addStyle(DOCUMENT_STYLE_REGULAR_BOLD_BLUE_SHADE, regular);
StyleConstants.setBold(s, true);
StyleConstants.setBackground(s, Color.lightGray);
StyleConstants.setForeground(s, Color.blue);
}
}

View File

@ -0,0 +1,139 @@
/**
* $Id: CommonTreeNode.java 2243 2012-03-14 21:15:29Z hchen3 $
*
*/
//========================================
// Package
//========================================
package trick.common.ui.components;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;
/**
* This class that extends {@link DefaultMutableTreeNode}, which
* has needed information associated with tree in Trick GUI.
*
* @author Hong Chen
* @since Trick 7
*/
public class CommonTreeNode extends DefaultMutableTreeNode {
//========================================
// Public data
//========================================
public static final int NORMAL_NODE = 0;
public static final int X_NODE = 1;
public static final int Y_NODE = 2;
public static final int Z_NODE = 3;
public static final int PLOT_NODE = 4;
public static final int CURVE_NODE = 5;
public static final int VARCASE_NODE = 6;
public static final int PAGE_NODE = 7;
public static final int TABLE_NODE = 8;
public static final int COLUMN_NODE = 9;
public static final int VAR_NODE = 10;
public static final int PROGRAM_NODE = 11;
public static final int INPUT_NODE = 12;
public static final int OUTPUT_NODE = 13;
public static final int PLOTS_NODE = 14;
public static final int TABLES_NODE = 15;
public static final int PROGRAMS_NODE = 16;
public static final int INPUT_VAR_NODE = 17;
public static final int OUTPUT_VAR_NODE = 18;
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
private static final long serialVersionUID = 7211981327477779671L;
// By default, this tree node is a normal node.
private int nodeType = 0;
//========================================
// Constructors
//========================================
/**
* Default constructor.
*/
public CommonTreeNode()
{
super();
}
/**
* Constructor that takes argument {@link Object} for the tree node.
*
* @param obj An instance of {@link Object} that is used for the tree node.
*/
public CommonTreeNode(Object obj) {
super(obj);
}
/**
* Constructor that takes argument {@link Object} for the tree node.
*
* @param obj An instance of {@link Object} that is used for the tree node.
* @param type The type of the node.
*/
public CommonTreeNode(Object obj, int type) {
super(obj);
nodeType = type;
}
//========================================
// Set/Get methods
//========================================
/**
* Sets the type for this node.
*
* @param type The type of the node.
*/
public void setNodeType(int type) {
nodeType = type;
}
/**
* Gets this node type.
*
* @return The type of the node.
*/
public int getNodeType() {
return nodeType;
}
/**
* Gets the path for this tree node in String format. Each tree node in
* the path is separated by ".".
*
* @return a String that has all tree node names separated by ".".
*
*/
public String getPathString() {
StringBuffer buf = new StringBuffer();
TreeNode[] path = getPath();
if (path != null && path.length > 0) {
for ( int j = 1; j < path.length; j ++ ) {
buf.append(path[j].toString());
if (j < path.length - 1) {
buf.append(".");
}
}
}
return buf.toString();
}
//========================================
// Methods
//========================================
}

View File

@ -0,0 +1,268 @@
/**
* $Id: DoubleJSlider.java 1662 2011-05-31 13:15:17Z lin $
*
*/
//========================================
// Package
//========================================
package trick.common.ui.components;
import java.awt.Rectangle;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.JSlider;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.plaf.basic.BasicSliderUI;
/**
* An extension of JSlider that uses double for its values.
*
* @since Trick 10
*/
public class DoubleJSlider extends JSlider implements ChangeListener{
//========================================
// Public data
//========================================
//public final static double DOUBLE_FACTOR = 100.0;
public static double DOUBLE_FACTOR ;
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
private static final long serialVersionUID = 8104332457463381081L;
/** This border show the current value of the slider as its title. */
private TitledBorder border = new TitledBorder(new EtchedBorder());
//========================================
// Constructors
//========================================
/**
* Default constructor - initializes with 0.0,100.0,50.0
*/
public DoubleJSlider(){
super();
DOUBLE_FACTOR = 100.0 ;
setDoubleMinimum(0.0);
setDoubleMaximum(100.0);
setDoubleValue(50.0);
addChangeListener(this);
}
/**
* Constructor with specified minimum, maximum and init value.
*
* @param min The minimum double value for the slider.
* @param max The maximum double value for the slider.
* @param val The init value for the slider.
*/
public DoubleJSlider(double min, double max, double val) {
super();
DOUBLE_FACTOR = 100.0 ;
setUI(new DoubleJSliderUI(this));
setBorder(border);
setDoubleMinimum(min);
setDoubleMaximum(max);
setDoubleValue(val);
setLabel("Current Value: " + val);
addChangeListener(this);
}
public DoubleJSlider(double min, double max, double val, double factor ) {
super();
DOUBLE_FACTOR = factor ;
setUI(new DoubleJSliderUI(this));
setBorder(border);
setDoubleMinimum(min);
setDoubleMaximum(max);
setDoubleValue(val);
setLabel("Current Value: " + val);
addChangeListener(this);
}
/**
* Sets the title for the slider.
*
* @param s The specified title for the slider.
*/
public void setLabel(String s) {
border.setTitle(s);
}
//========================================
// Set/Get methods
//========================================
/**
* Returns the maximum value for the slider in double.
*
* @return The maximum value for the slider in double.
*/
public double getDoubleMaximum() {
return( getMaximum()/DOUBLE_FACTOR );
}
/**
* Returns the minimum value for the slider in double.
*
* @return The minimum value for the slider in double.
*/
public double getDoubleMinimum() {
return( getMinimum()/DOUBLE_FACTOR );
}
/**
* Returns the current value for the slider in double.
*
* @return The current value of the slider in double.
*/
public double getDoubleValue() {
return( getValue()/DOUBLE_FACTOR );
}
/**
* Sets maximum value for the slider in double.
*
* @param max The value which needs to be set as maximum value for the slider.
*/
public void setDoubleMaximum(double max) {
setMaximum((int)(max*DOUBLE_FACTOR));
}
/**
* Sets minimum value for the slider in double.
*
* @param min The value which needs to be set as minimum value for the slider.
*/
public void setDoubleMinimum(double min) {
setMinimum((int)(min*DOUBLE_FACTOR));
}
/**
* Sets current value for the slider in double.
*
* @param val The value which needs to be set as current value for the slider.
*/
public void setDoubleValue(double val) {
setValue((int)(val*DOUBLE_FACTOR));
setToolTipText(Double.toString(val));
}
//========================================
// Methods
//========================================
/**
* Required by ChangeListener.
*/
public void stateChanged(ChangeEvent e) {
DoubleJSlider slider = (DoubleJSlider)e.getSource();
if (!slider.getValueIsAdjusting()) {
setToolTipText(Double.toString(slider.getDoubleValue()));
slider.setLabel("Current Value: "+slider.getDoubleValue());
}
}
//========================================
// Inner classes
//========================================
/**
* The class for customized slider UI.
*/
class DoubleJSliderUI extends BasicSliderUI implements MouseMotionListener, MouseListener {
final JPopupMenu pop = new JPopupMenu();
JMenuItem item = new JMenuItem();
DoubleJSlider slider;
/**
* Constructor with specifed slider.
*
* @param slider The specified {@link DoubleJSlider}.
*/
public DoubleJSliderUI(DoubleJSlider slider)
{
super(slider);
slider.addMouseMotionListener(this);
slider.addMouseListener(this);
this.slider = slider;
pop.add(item);
pop.setDoubleBuffered(true);
}
/**
* Shows the tip text while mouse moving.
*
* @param me The mouse event of slider moving.
*/
public void showToolTip(MouseEvent me) {
item.setText(""+slider.getDoubleValue());
//limit the tooltip location relative to the slider
Rectangle b = me.getComponent().getBounds();
int x = me.getX();
x = (x > (b.x + b.width / 2) ? (b.x + b.width / 2) : (x < (b.x - b.width / 2) ? (b.x - b.width / 2) : x));
pop.show( me.getComponent(), x - 5, -5 );
item.setArmed( false );
}
/**
* Required by {@link MouseMotionListener}.
*/
public void mouseDragged(MouseEvent me) {
showToolTip(me);
}
/**
* Required by {@link MouseMotionListener}.
*/
public void mouseMoved(MouseEvent me) {
}
/**
* Required by {@MouseListener}.
*/
public void mousePressed(MouseEvent me) {
showToolTip(me);
}
/**
* Required by {@MouseListener}.
*/
public void mouseClicked(MouseEvent me) {
}
/**
* Required by {@MouseListener}.
*/
public void mouseReleased(MouseEvent me) {
pop.setVisible(false);
}
/**
* Required by {@MouseListener}.
*/
public void mouseEntered(MouseEvent me) {
}
/**
* Required by {@MouseListener}.
*/
public void mouseExited(MouseEvent me) {
}
}
}

View File

@ -0,0 +1,323 @@
/*
* $Id: FontChooser.java 2559 2012-09-05 16:25:43Z hchen3 $
*
*/
//========================================
// Package
//========================================
package trick.common.ui.components;
//========================================
// Imports
//========================================
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.GraphicsEnvironment;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.ListSelectionModel;
import javax.swing.border.EtchedBorder;
import javax.swing.border.LineBorder;
import javax.swing.border.TitledBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
/**
* Defines font chooser dialog.
*
* @author Hong Chen
* @since Trick 10
*/
public class FontChooser extends JDialog implements ActionListener, ListSelectionListener {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
private static final long serialVersionUID = 5290768624262666696L;
private final static String OK_OPTION = "Ok";
private final static String CANCEL_OPTION = "Cancel";
private final static String BOLD_OPTION = "Bold";
private final static String ITALIC_OPTION = "Italic";
private String[] fonts;
private Integer[] sizes;
private JList fontList;
private JList sizeList;
private JCheckBox boldBox;
private JCheckBox italicBox;
private Font currentFont;
private JButton okButton;
private JButton cancelButton;
private JLabel sampleLabel;
private int closeOption = JOptionPane.CLOSED_OPTION;
//========================================
// Constructors
//========================================
/**
* Custructor with specified owner.
*/
private FontChooser(Frame parent, String title, Font font) {
super(parent, title, true);
fonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
// the size list was obtained from tcl code, do we or can we support more?
sizes = new Integer[]{4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24};
buildGUI(parent);
setLocationRelativeTo(parent);
setCurrentFont(font);
}
//========================================
// Set/Get methods
//========================================
/**
* Sets the font for the dialog.
*
* @param font An instance of {@link Font} that needs to be set for the dialog.
*/
public void setCurrentFont(Font font) {
currentFont = font;
if (font != null) {
fontList.setSelectedValue(font.getName(), true);
sizeList.setSelectedValue(new Integer(font.getSize()), true);
if (font.getStyle() == Font.PLAIN) {
boldBox.setSelected(false);
italicBox.setSelected(false);
} else {
if (font.getStyle() == (Font.BOLD | Font.ITALIC)) {
boldBox.setSelected(true);
italicBox.setSelected(true);
} else {
if (font.getStyle() == Font.BOLD) {
boldBox.setSelected(true);
} else if (font.getStyle() == Font.ITALIC) {
italicBox.setSelected(true);
}
}
}
sampleLabel.setFont(font);
sampleLabel.setText(getCurrentFontText());
}
}
/**
* Gets the current font of the dialog.
*
* @return An instance of {@link Font}. <code>null</code> is returned if Ok is not selected.
*/
public Font getCurrentFont() {
if (closeOption == JOptionPane.CLOSED_OPTION || closeOption == JOptionPane.CANCEL_OPTION) {
return null;
}
return currentFont;
}
/**
* Gets the currently selected font in text.
*
* @return The currently selected font in preferred text format.
*/
public String getCurrentFontText() {
return currentFont.getFamily() + ":" + currentFont.getStyle() + ":" + currentFont.getSize();
}
//========================================
// Methods
//========================================
/**
* Handles clicks on the buttons or check box selections.
*
* Required by {@link ActionListener}.
*/
public void actionPerformed(ActionEvent e) {
if (OK_OPTION.equals(e.getActionCommand())) {
updateFont();
closeOption = JOptionPane.OK_OPTION;
setVisible(false);
dispose();
} else if (CANCEL_OPTION.equals(e.getActionCommand())) {
closeOption = JOptionPane.CANCEL_OPTION;
setVisible(false);
dispose();
} else {
updateFont();
}
}
/**
* Handles selections on the list.
*
* Required by {@link ListSelectionListener}.
*/
public void valueChanged(ListSelectionEvent e) {
updateFont();
}
/**
* Set up and show the font chooser dialog.
*
* @param parent The parent component for the dialog.
* @param title The title of the dialog.
* @param font The initial font.
*/
public static Font showDialog(Component parent, String title, Font font) {
Frame frame = JOptionPane.getFrameForComponent(parent);
FontChooser dialog = new FontChooser(frame, title, font);
dialog.setVisible(true);
return dialog.getCurrentFont();
}
/**
* Helper method for updating sample lable font for the purpose of showing
* the selected font.
*/
private void updateFont() {
// if during gui set up, don't need to update
if (fontList == null || fontList.getSelectedValue() == null ||
sizeList == null || sizeList.getSelectedValue() == null ||
boldBox == null || italicBox == null) {
return;
}
int currentStyle = Font.PLAIN;
if (boldBox.isSelected()) {
currentStyle += Font.BOLD;
}
if (italicBox.isSelected()) {
currentStyle += Font.ITALIC;
}
currentFont = new Font(fontList.getSelectedValue().toString(), currentStyle, ((Integer)sizeList.getSelectedValue()).intValue());
sampleLabel.setFont(currentFont);
sampleLabel.setText(getCurrentFontText());
sampleLabel.repaint();
}
/**
* Helper method for building the gui.
*
*/
//for Java 7, the type of elements of JComboBox needs to be specified to avoid the warning and it's not supported in Java 6
@SuppressWarnings("unchecked")
private void buildGUI(Frame parent) {
JPanel selectionPanel = new JPanel();
fontList = new JList(fonts);
fontList.getSelectionModel().addListSelectionListener(this);
sizeList = new JList(sizes);
sizeList.getSelectionModel().addListSelectionListener(this);
JPanel fontPanel = getListPanel("Font", fontList);
selectionPanel.add(fontPanel);
JPanel sizePanel = getListPanel("Size", sizeList);
selectionPanel.add(sizePanel);
JPanel stylePanel = new JPanel();
stylePanel.setLayout(new BoxLayout(stylePanel, BoxLayout.Y_AXIS));
JLabel styleLabel = new JLabel("Style");
boldBox = new JCheckBox(BOLD_OPTION);
boldBox.addActionListener(this);
italicBox = new JCheckBox(ITALIC_OPTION);
italicBox.addActionListener(this);
stylePanel.add(styleLabel);
stylePanel.add(Box.createRigidArea(new Dimension(0,5)));
stylePanel.add(boldBox);
stylePanel.add(italicBox);
stylePanel.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
stylePanel.setPreferredSize(new Dimension(stylePanel.getPreferredSize().width, fontPanel.getPreferredSize().height));
selectionPanel.add(stylePanel);
selectionPanel.setMinimumSize(selectionPanel.getPreferredSize());
JPanel samplePanel = new JPanel(new BorderLayout());
samplePanel.setBorder(new TitledBorder(new EtchedBorder(), "Preview"));
sampleLabel = new JLabel("", JLabel.CENTER);
sampleLabel.setBackground(Color.white);
sampleLabel.setBorder(new LineBorder(Color.black));
sampleLabel.setOpaque(true);
sampleLabel.setPreferredSize(new Dimension(120, 60));
samplePanel.add(sampleLabel, BorderLayout.CENTER);
JPanel buttonPanel = new JPanel();
okButton = new JButton(OK_OPTION);
okButton.addActionListener(this);
cancelButton = new JButton(CANCEL_OPTION);
cancelButton.addActionListener(this);
buttonPanel.setLayout(new BoxLayout(buttonPanel, BoxLayout.X_AXIS));
buttonPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
buttonPanel.add(Box.createHorizontalStrut(30));
buttonPanel.add(okButton);
buttonPanel.add(Box.createRigidArea(new Dimension(10, 0)));
buttonPanel.add(cancelButton);
getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
getContentPane().add(selectionPanel);
getContentPane().add(Box.createVerticalStrut(15));
getContentPane().add(samplePanel);
getContentPane().add(buttonPanel);
getContentPane().add(Box.createVerticalStrut(5));
pack();
}
/**
* Gets a panel that contains a list and associated title.
*
* @param labelText The title label for the list.
* @param list An instance of {@link JList}.
*/
private JPanel getListPanel(String labelText, JList list) {
JPanel ret = new JPanel();
list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
JScrollPane listScroller = new JScrollPane(list);
listScroller.setAlignmentX(LEFT_ALIGNMENT);
JLabel label = new JLabel(labelText);
ret.setLayout(new BoxLayout(ret, BoxLayout.Y_AXIS));
label.setLabelFor(list);
ret.add(label);
ret.add(Box.createRigidArea(new Dimension(0,5)));
ret.add(listScroller);
ret.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
return ret;
}
//========================================
// Inner Classes
//========================================
}

View File

@ -0,0 +1,193 @@
/**
* $Id: NumberTextField.java 1488 2011-04-07 17:37:19Z hchen $
*
*/
//========================================
// Package
//========================================
package trick.common.ui.components;
import javax.swing.JTextField;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
import javax.swing.text.PlainDocument;
/**
* An extension of {@link JTextField} that only accepts numbers.
*
*
* @since Trick 10
*/
public class NumberTextField extends JTextField {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
private static final long serialVersionUID = -9181145899991928113L;
// By default, this text field is good for double unless intOnly is set to be true.
// TODO: should support all Number types?
private boolean intOnly = false;
//========================================
// Constructors
//========================================
/**
* Default constructor.
*/
public NumberTextField() {
super();
}
/**
* Constructs a new empty text field only for integers.
*
* @param isIntOnly Whether this text field is only for integers.
*/
public NumberTextField(boolean isIntOnly) {
this();
intOnly = isIntOnly;
}
/**
* Constructs a new empty text field with the specified number of columns.
*
* @param columns The number of columns to use to calculate the preferred width.
*/
public NumberTextField(int columns) {
super(columns);
}
/**
* Constructs a new text field with the specified text. If the text represents
* an invalid double, only set text columns to a default number 5.
*
* @param text The text that represents a valid number to be displayed.
*/
public NumberTextField(String text) {
super(text);
if (getValue() == null) {
setColumns(5);
}
}
/**
* Constructs a new text field with the specified text. If the text represents
* an invalid double, only set text clolumns to the specified number of columns.
*
* @param text The text that represents a valid number to be displayed.
* @param columns The number of columns to use to calculate the preferred width.
*/
public NumberTextField(String text, int columns) {
super(text, columns);
}
//========================================
// Set/Get methods
//========================================
/**
* Limits the text field only for integers.
*/
public void setIntOnly(boolean intOnly) {
this.intOnly = intOnly;
}
/**
* Gets value of the text field.
*
* @return the {@link Number} of this text field if it's valid.
*/
public Number getValue() {
try {
if (intOnly) {
return Integer.valueOf(getText());
}
return Double.valueOf(getText());
} catch (NumberFormatException e) {
return null;
} catch (NullPointerException e) {
return null;
}
}
//========================================
// Methods
//========================================
/**
* Uses the number document for this number text field.
*/
@Override
protected Document createDefaultModel() {
return new NumberTextDocument();
}
/**
* Checks to see if any input is valid based on double data type.
*
* @return <code>true</code> if any input can be part of a number,
* <code>false</code> otherwise.
*/
@Override
public boolean isValid() {
try {
if (intOnly) {
Integer.parseInt(getText());
} else {
Double.parseDouble(getText());
}
return true;
} catch (NumberFormatException e) {
return false;
} catch (NullPointerException e) {
return false;
}
}
//========================================
// Inner classes
//========================================
/**
* Class for valid number document.
*/
class NumberTextDocument extends PlainDocument {
private static final long serialVersionUID = -6195020045069585237L;
@Override
public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
if (str == null) {
return;
}
String oldString = getText(0, getLength());
String newString = oldString.substring(0, offs) + str + oldString.substring(offs);
try {
if (intOnly) {
Integer.parseInt(newString + "0");
} else {
Double.parseDouble(newString + "0");
}
super.insertString(offs, str, a);
} catch (NumberFormatException e) {
}
}
}
}

View File

@ -0,0 +1,192 @@
/**
* $Id: AnimationPlayer.java 1641 2011-05-24 19:25:12Z hchen $
*
*/
//========================================
// Package
//========================================
package trick.common.ui.panels;
//========================================
// Imports
//========================================
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import trick.common.ui.UIUtils;
/**
* An extension of JPanel that displays an animation image with the control capability.
*
* @since Trick 10
*/
public class AnimationPlayer extends JPanel {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
private boolean paused;
private boolean finished;
private String animationFile;
private JLabel animationLabel;
private PlayAnimationTask animationTask;
private static final long serialVersionUID = 3705588596523798631L;
//========================================
// Constructors
//========================================
/**
* Default constructor.
*/
public AnimationPlayer(String fileName) {
animationFile = fileName;
buildGUI();
if (animationTask == null) {
animationTask = new PlayAnimationTask();
}
}
//========================================
// Set/Get methods
//========================================
//========================================
// Methods
//========================================
/**
* Starts the animation task. This method has to be called
* in order for the animation to be played.
*/
public void start() {
if (animationTask == null) {
animationTask = new PlayAnimationTask();
}
animationTask.execute();
}
/**
* Pauses the animation play.
*/
public void pause() {
paused = true;
}
/**
* Resumes the animation play.
*/
public void resume() {
paused = false;
}
/**
* Stops the animation play.
*/
public void stop() {
finished = true;
}
/**
* Builds the player GUI.
*/
private void buildGUI() {
setLayout(new BorderLayout());
animationLabel = new JLabel();
ImageIcon icon = UIUtils.createImageIcon(animationFile);
// set proper initial size for the label
if (icon != null) {
animationLabel.setPreferredSize(new Dimension(icon.getIconWidth(), icon.getIconHeight()));
}
add(animationLabel, BorderLayout.CENTER);
}
//========================================
// Inner Class
//========================================
/**
* Inner class for playing an animation image.
*/
private class PlayAnimationTask extends SwingWorker<Void, Void> {
ImageInputStream stream;
@Override
public Void doInBackground() {
if (animationFile == null) {
return null;
}
try {
InputStream input = UIUtils.getInputStreamForFile(animationFile);
stream = ImageIO.createImageInputStream(input);
Iterator readers = ImageIO.getImageReaders(stream);
if (!readers.hasNext()) {
throw new RuntimeException("no image reader found");
}
ImageReader reader = (ImageReader) readers.next();
reader.setInput(stream); // don't omit this line!
int n = reader.getNumImages(true); // don't use false!
for (int i = 0; i < n; i++) {
BufferedImage image = reader.read(i);
Image img = image;
animationLabel.setIcon(new ImageIcon(img));
do {
try {
Thread.sleep(150);
} catch (InterruptedException ie) {
}
} while (paused);
if (finished) {
break;
} else {
// rewind
if (i == n-1) {
i = 0;
}
}
}
} catch (IOException ioe) {
}
return null;
}
@Override
public void done() {
if (stream != null) {
try {
stream.close();
} catch (IOException ioe) { }
}
}
}
}

View File

@ -0,0 +1,338 @@
package trick.common.ui.panels;
import java.awt.Color;
import java.awt.Font;
import java.awt.Insets;
import javax.swing.Action;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.SwingUtilities;
import javax.swing.border.EmptyBorder;
import org.jdesktop.swingx.JXButton;
import org.jdesktop.swingx.JXLabel;
import org.jdesktop.swingx.JXStatusBar;
import org.jdesktop.swingx.plaf.basic.BasicStatusBarUI;
import trick.sniffer.SimulationInformation;
import trick.sniffer.SimulationListener;
import trick.sniffer.SimulationSniffer;
/**
* provides a common GUI element for connecting to the Variable Server on a given host and port
*
* @author Derek Bankieris
*/
public class ConnectionStatusBar extends JXStatusBar {
/** label describing the connection state */
protected JXLabel stateLabel = new JXLabel() {{
setFont(getFont().deriveFont(Font.BOLD));
}};
/** combo box which presents all the available sims on the network */
@SuppressWarnings("unchecked")
protected JComboBox simulationComboBox = new JComboBox() {
{
setEditable(true);
setSelectedItem(new SimulationInformation("localhost", "0"));
}
@Override
public void addItem(Object object) {
SimulationInformation simulationInformation = (SimulationInformation)object;
for (int i = 0; i < getItemCount(); ++i) {
if (simulationInformation.compareTo((SimulationInformation)getItemAt(i)) <= 0) {
super.insertItemAt(simulationInformation, i);
return;
}
}
super.addItem(object);
}
@Override
public void setSelectedItem(Object object) {
if (object instanceof SimulationInformation) {
SimulationInformation simulationInformation =
(SimulationInformation)object;
super.setSelectedItem(simulationInformation.machine + ":" +
simulationInformation.handshakePort);
}
}
};
/** toggles connection */
protected JXButton connectionButton;
/** action to be performed when the button is pressed while disconnected */
public final Action connectAction;
/** action to be performed when the button is pressed while connected */
public final Action disconnectAction;
/** action to be performed when the button is pressed while auto-connecting */
public final Action autoConnectingAction;
/** the connection state */
private boolean connected = false;
/** the auto-connecting state */
private boolean autoConnecting = false;
/** exception to be thrown in response to invalid host/port specification */
protected IllegalArgumentException illegalArgumentException =
new IllegalArgumentException("Connection specification must be of the form host:port");
/** the thread that listens on the multicast channel for simulations */
private SimulationSniffer simulationSniffer = new SimulationSniffer() {{
addSimulationListener(new SimulationListener() {
@Override
public void simulationAdded(final SimulationInformation simulationInformation) {
if (simulationInformation.getMajorVersionNumber() >= 10) {
SwingUtilities.invokeLater(new Runnable() {
@Override
@SuppressWarnings("unchecked")
public void run() {
simulationComboBox.addItem(simulationInformation);
}
});
}
}
@Override
public void simulationRemoved(final SimulationInformation simulationInformation) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
simulationComboBox.removeItem(simulationInformation);
}
});
}
@Override
public void exceptionOccurred(Exception exception) {
JOptionPane.showMessageDialog(ConnectionStatusBar.this, exception,
"Simulation List Error", JOptionPane.ERROR_MESSAGE);
}
});
start();
}};
/** a darker green */
protected Color darkGreen = new Color(0, 150, 0);
/** a darker yellow */
protected Color darkYellow = new Color(255, 165, 0);
/**
* constructor
*
* @param connectAction the action to execute when the button is pressed in
* the disconnected state
* @param disconnectAction the action to execute when the button is pressed
* in the connected state
* @param autoConnectingAction the action to execute when the button is pressed
* in the auto-connecting state
*/
public ConnectionStatusBar(Action connectAction, Action disconnectAction, Action autoConnectingAction) {
this.connectAction = connectAction;
this.disconnectAction = disconnectAction;
this.autoConnectingAction = autoConnectingAction;
simulationComboBox.getEditor().addActionListener(connectAction);
putClientProperty(BasicStatusBarUI.AUTO_ADD_SEPARATOR, false);
setBorder(new EmptyBorder(5, 5, 3, 5));
add(stateLabel);
add(simulationComboBox, new JXStatusBar.Constraint(
JXStatusBar.Constraint.ResizeBehavior.FILL, new Insets(0, 5, 0, 5)));
connectionButton = new JXButton(connectAction);
add(connectionButton);
updateState();
}
/**
* gets the host name
*
* @return the host name
*/
public String getHostName() {
Object object = simulationComboBox.getEditor().getItem();
if (object instanceof SimulationInformation) {
return ((SimulationInformation)object).machine;
}
if (object instanceof String) {
String string = (String)object;
int index = string.lastIndexOf(":");
if (index != -1) {
return string.substring(0, index).trim();
}
else {
throw illegalArgumentException;
}
}
return null;
}
/**
* gets the port
*
* @return the port
*/
public int getPort() {
Object object = simulationComboBox.getEditor().getItem();
if (object instanceof SimulationInformation) {
return Integer.parseInt(((SimulationInformation)object).handshakePort);
}
if (object instanceof String) {
String string = (String)object;
int index = string.lastIndexOf(":");
if (index != -1) {
return Integer.parseInt(string.substring(index + 1).trim());
}
else {
throw illegalArgumentException;
}
}
return -1;
}
/**
* set the target simulation
*
* @param hostName the name of the host machine
* @param port the port of the host machine
*/
public void setTarget(String hostName, int port) {
simulationComboBox.setSelectedItem(new SimulationInformation(
hostName, Integer.toString(port)));
}
/**
* returns the connection state
*
* @return the connection state
*/
public boolean getConnectionState() {
return connected;
}
/**
* sets the connection state, updating the display and action
* enabled states appropriately
*
* @param connected the connection state
*/
public void setConnectionState(boolean connected) {
if (this.connected != connected) {
this.connected = connected;
updateState();
}
}
/**
* updates the display and action enabled states based on the connection state
*/
protected void updateState() {
simulationSniffer.setPaused(connected);
connectionButton.setAction(connected ? disconnectAction : connectAction);
simulationComboBox.setEnabled(!connected);
connectAction.setEnabled(!connected);
disconnectAction.setEnabled(connected);
if (connected) {
stateLabel.setText("Connected To: ");
stateLabel.setForeground(darkGreen);
}
else {
stateLabel.setText("Not Connected ");
stateLabel.setForeground(Color.red);
}
}
/**
* continuously attempt to connect to the target simulation
*/
public void autoConnect() {
if (!autoConnecting) {
connected = false;
simulationSniffer.setPaused(false);
connectionButton.setAction(autoConnectingAction);
simulationComboBox.setEnabled(false);
connectAction.setEnabled(false);
disconnectAction.setEnabled(false);
stateLabel.setText("Searching For: ");
stateLabel.setForeground(darkYellow);
autoConnecting = true;
final String host = getHostName();
final int port = getPort();
new Thread() {
@Override
public void run() {
while(autoConnecting) {
try {
sleep(1000);
}
catch (InterruptedException interruptedException) {}
for (SimulationInformation simulationInformation :
simulationSniffer.getSimulationInformation()) {
if (simulationInformation.machine.equals(host) &&
simulationInformation.noHandshakePort.equals(Integer.toString(port)) &&
simulationInformation.getMajorVersionNumber() >= 10) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (autoConnecting) {
autoConnecting = false;
connectAction.actionPerformed(null);
}
}
});
return;
}
}
}
}
}.start();
}
}
/**
* stop continuously attempting to connect to the target simulation, if active
*/
public void cancelAutoConnect() {
if (autoConnecting) {
autoConnecting = false;
updateState();
}
}
/**
* returns whether or not this instance is currently attempting to
* automatically connect to the target simulation
*
* @return <code>true</code> if auto-connect is currently in progress
*/
public boolean isAutoConnecting() {
return autoConnecting;
}
}

View File

@ -0,0 +1,140 @@
/*
* $Id: DataPanel.java 1065 2010-09-09 19:49:28Z hchen $
*
*/
//========================================
// Package
//========================================
package trick.common.ui.panels;
//========================================
//Imports
//========================================
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
/**
* A {@link JPanel} that is for displaying data.
*
* @since Trick 10
*/
public abstract class DataPanel extends JPanel {
//========================================
// Public data
//========================================
public static final int SIM_RUN_TREE = 1;
public static final int RUN_LIST = 2;
public static final int SIM_DP_TREE = 3;
public static final int DP_LIST = 4;
public static final int VAR_LIST = 5;
//========================================
// Protected data
//========================================
/** The pop-up menu for the data panel. */
protected JPopupMenu popup = null;
//========================================
// Private Data
//=======================================
private static final long serialVersionUID = -8211915811050384782L;
/** The panel could have more than one popup menu. */
private JPopupMenu[] popupList;
/** The type of the panel so we know what kind of panel invokes the popup. */
private int panelType;
//========================================
// Constructors
//========================================
/**
* Default constructor.
*/
public DataPanel() {
popupList = new JPopupMenu[1];
}
/**
* The constructor that specifies total number of popup menus for the panel.
*
* @param popupNum The total popup menus for the panel.
*/
public DataPanel(int popupNum) {
if (popupNum > 0) {
popupList = new JPopupMenu[popupNum];
} else {
popupList = new JPopupMenu[1];
}
}
//========================================
// Set/Get methods
//========================================
/**
* Sets the panel type.
*
* @param type The type in integer for the panel.
*/
public void setType(int type) {
panelType = type;
}
/**
* Gets the panel type.
*
* @return The panel type in integer.
*/
public int getType() {
return panelType;
}
/**
* Gets the total number of popup menus.
*
* @return The number of popup menus.
*/
public int getPopupNum() {
if (popupList != null) {
return popupList.length;
}
return 0;
}
/**
* Sets the popup menu with specified index number.
*
* @param popup An instance of {@link JPopupMenu}.
* @param index The index number for the popup menu.
*/
public void setPopup(JPopupMenu popup, int index) {
if (index < popupList.length) {
popupList[index] = popup;
}
}
/**
* Gets the popup menu at specified index number.
*
* @param index The index number of the popup menu.
*
* @return An instance of {@link JPopupMenu}.
*/
public JPopupMenu getPopup(int index) {
if (index < popupList.length) {
return popupList[index];
}
return popupList[0];
}
//========================================
// Methods
//========================================
public abstract void removeSelectedData();
}

View File

@ -0,0 +1,372 @@
/*
* $Id: DynamicTree.java 3771 2014-12-11 20:37:29Z hchen3 $
*
*/
//========================================
// Package
//========================================
package trick.common.ui.panels;
//========================================
//Imports
//========================================
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.util.ArrayList;
import java.util.Enumeration;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import org.jdesktop.swingx.JXTree;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.HighlightPredicate;
import trick.common.ui.UIUtils;
import trick.common.ui.components.CommonTreeNode;
/**
* A {@link JPanel} that displays a dynamic {@link JTree}.
*
* @author Hong Chen
* @since Trick 10
*/
public class DynamicTree extends DataPanel {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
/** An instance of JXTree. */
protected JXTree tree;
/** The tree model for a JTree. */
protected DefaultTreeModel treeModel;
/** The root for a JTree. */
protected DefaultMutableTreeNode rootNode;
//========================================
// Private Data
//========================================
private static final long serialVersionUID = 7238523759496892652L;
//========================================
// Constructors
//========================================
/**
* Default constructor.
*/
public DynamicTree() {
super();
rootNode = new DefaultMutableTreeNode("Root Node");
treeModel = new DefaultTreeModel(rootNode);
tree = new JXTree(treeModel);
tree.setRolloverEnabled(true);
tree.addHighlighter(new ColorHighlighter(HighlightPredicate.ROLLOVER_ROW, null, Color.MAGENTA));
tree.putClientProperty("JTree.lineStyle", "Angled");
//tree.setEditable(true);
//tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setShowsRootHandles(true);
tree.setRootVisible(false);
tree.putClientProperty("JTree.lineStyle", "Horizontal");
DynamicTreeCellRenderer renderer = new DynamicTreeCellRenderer();
tree.setCellRenderer(renderer);
setup();
}
/**
* Constructor with specified the number of pop up menu.
*
* @param popNum The number of pop up menu.
*/
public DynamicTree(int popNum) {
super(popNum);
rootNode = new DefaultMutableTreeNode("Root Node");
treeModel = new DefaultTreeModel(rootNode);
tree = new JXTree(treeModel);
tree.setRolloverEnabled(true);
tree.addHighlighter(new ColorHighlighter(HighlightPredicate.ROLLOVER_ROW, null, Color.MAGENTA));
tree.putClientProperty("JTree.lineStyle", "Angled");
//tree.setEditable(true);
//tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setShowsRootHandles(true);
tree.setRootVisible(false);
tree.putClientProperty("JTree.lineStyle", "Horizontal");
DynamicTreeCellRenderer renderer = new DynamicTreeCellRenderer();
tree.setCellRenderer(renderer);
setup();
}
//========================================
// Set/Get methods
//========================================
/**
* Gets the instance of the {@link JXTree}.
*
* @return The instance of the tree.
*/
public JXTree getTree() {
return tree;
}
/**
* Gets the root of the tree.
*
* @return The root {@link DefaultMutableTreeNode} of the tree.
*/
public DefaultMutableTreeNode getRoot() {
return rootNode;
}
/**
* Gets the default tree model for the tree.
*
* @return The instance of {@link DefaultTreeModel} for the tree.
*/
public DefaultTreeModel getDefaultModel() {
return treeModel;
}
//========================================
// Methods
//========================================
/**
* Helper method.
*/
private void setup() {
setLayout(new BorderLayout());
JScrollPane scrollpane = new JScrollPane();
scrollpane.getViewport().add(tree);
add(BorderLayout.CENTER, scrollpane);
}
/**
* Removes all nodes except the root node.
*/
public void clear() {
rootNode.removeAllChildren();
treeModel.reload();
}
/**
* Adds a child node to a parent node.
*
* @param parent The parent {@link DefaultMutableTreeNode}.
* @param child The child object.
*/
public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent, Object child) {
return addObject(parent, child, false);
}
/**
* Adds a child node object to a parent node by specifying if it should be visible.
*
* @param parent The parent {@link DefaultMutableTreeNode}.
* @param child The child object.
* @param shouldBeVisible <code>true</code> the node should be visible, <code>false</code> otherwise.
*/
public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent, Object child, boolean shouldBeVisible) {
DefaultMutableTreeNode childNode = new DefaultMutableTreeNode(child);
if (parent == null) {
parent = rootNode;
}
//It is key to invoke this on the TreeModel, and NOT DefaultMutableTreeNode
treeModel.insertNodeInto(childNode, parent, parent.getChildCount());
//Make sure the user can see the lovely new node.
if (shouldBeVisible) {
tree.scrollPathToVisible(new TreePath(childNode.getPath()));
}
return childNode;
}
/**
* Adds a child node to a parent by specifying if it should be visible.
*
* @param parent The parent {@link DefaultMutableTreeNode}.
* @param child The child {@link DefaultMutableTreeNode}.
* @param shouldBeVisible <code>true</code> the node should be visible, <code>false</code> otherwise.
*/
public void addNode(DefaultMutableTreeNode parent, DefaultMutableTreeNode child, boolean shouldBeVisible) {
if (parent == null) {
parent = rootNode;
}
addNode(parent, child, parent.getChildCount(), shouldBeVisible);
}
/**
* Adds a child node to a parent by specifying if it should be visible and its index location.
*
* @param parent The parent {@link DefaultMutableTreeNode}.
* @param child The child {@link DefaultMutableTreeNode}.
* @param index The child location index in parent children nodes.
* @param shouldBeVisible <code>true</code> the node should be visible, <code>false</code> otherwise.
*
*/
public void addNode(DefaultMutableTreeNode parent, DefaultMutableTreeNode child, int index, boolean shouldBeVisible) {
if (index < 0 || index > parent.getChildCount()) {
//It is key to invoke this on the TreeModel, and NOT DefaultMutableTreeNode
treeModel.insertNodeInto(child, parent, parent.getChildCount());
} else {
treeModel.insertNodeInto(child, parent, index);
}
//Make sure the user can see the lovely new node.
if (shouldBeVisible) {
tree.scrollPathToVisible(new TreePath(child.getPath()));
}
}
/**
* Gets all child node of a specified node.
*
* @param parent A parent {@link DefaultMutableTreeNode}.
*
* @return A list of {@link DefaultMutableTreeNode} of the specified parent node.
*/
public ArrayList<DefaultMutableTreeNode> getAllChildren(DefaultMutableTreeNode parent) {
ArrayList<DefaultMutableTreeNode> childNodes = null;
int count = parent.getChildCount();
if (count > 0) {
childNodes = new ArrayList<DefaultMutableTreeNode>();
for (int i = 0; i < count; i++) {
DefaultMutableTreeNode eachChild = (DefaultMutableTreeNode)treeModel.getChild(parent, i);
childNodes.add(eachChild);
}
}
return childNodes;
}
/**
* Gets all selected nodes.
*
*/
public ArrayList<DefaultMutableTreeNode> getSelectedNodes() {
ArrayList<DefaultMutableTreeNode> selectedNodes = null;
TreePath[] selectedPaths = tree.getSelectionPaths();
if (selectedPaths != null && selectedPaths.length > 0) {
selectedNodes = new ArrayList<DefaultMutableTreeNode>();
for (int i = 0; i < selectedPaths.length; i ++) {
if (selectedPaths[i].getLastPathComponent() instanceof DefaultMutableTreeNode) {
DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode)selectedPaths[i].getLastPathComponent();
selectedNodes.add(treeNode);
}
}
}
return selectedNodes;
}
/**
* Removes all selected tree nodes.
*/
@Override
public void removeSelectedData() {
// TODO:
}
/**
* Expands the specified tree node.
*
* @param node A {@link DefaultMutableTreeNode} that needs expanding.
*/
@SuppressWarnings("rawtypes")
public void expandNode(DefaultMutableTreeNode node) {
Enumeration children = node.depthFirstEnumeration();
while (children.hasMoreElements()) {
DefaultMutableTreeNode child = (DefaultMutableTreeNode)children.nextElement();
if (child.isLeaf()) {
tree.scrollPathToVisible(new TreePath(child.getPath()));
}
}
}
//========================================
// Inner classes
//========================================
/**
* Class that extends {@link DefaultTreeCellRenderer}.
*
*/
public class DynamicTreeCellRenderer extends DefaultTreeCellRenderer {
private static final long serialVersionUID = 6474954896113266472L;
/**
* Configures the renderer based on the passed in components.
*/
@Override
public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel,
boolean expanded, boolean leaf, int row, boolean hasFocus) {
super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
if (value instanceof CommonTreeNode) {
CommonTreeNode node = (CommonTreeNode)value;
switch (node.getNodeType()) {
case CommonTreeNode.PAGE_NODE:
setIcon(UIUtils.createImageIcon("page2.gif"));
break;
case CommonTreeNode.PLOT_NODE:
case CommonTreeNode.CURVE_NODE:
case CommonTreeNode.VARCASE_NODE:
setIcon(UIUtils.createImageIcon("plot.gif"));
break;
case CommonTreeNode.X_NODE:
setIcon(UIUtils.createImageIcon("x_variable.gif"));
break;
case CommonTreeNode.Y_NODE:
setIcon(UIUtils.createImageIcon("y_variable.gif"));
break;
case CommonTreeNode.VAR_NODE:
case CommonTreeNode.INPUT_VAR_NODE:
case CommonTreeNode.OUTPUT_VAR_NODE:
setIcon(UIUtils.createImageIcon("variable.gif"));
break;
case CommonTreeNode.TABLE_NODE:
setIcon(UIUtils.createImageIcon("table_small.gif"));
break;
case CommonTreeNode.PROGRAM_NODE:
setIcon(UIUtils.createImageIcon("program.gif"));
break;
case CommonTreeNode.INPUT_NODE:
setIcon(UIUtils.createImageIcon("program_in.gif"));
break;
case CommonTreeNode.OUTPUT_NODE:
setIcon(UIUtils.createImageIcon("program_out.gif"));
break;
}
}
return this;
}
}
}

View File

@ -0,0 +1,197 @@
/*
* $Id: FindBar.java 2559 2012-09-05 16:25:43Z hchen3 $
*
*/
//========================================
// Package
//========================================
package trick.common.ui.panels;
//========================================
//Imports
//========================================
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.SwingConstants;
import org.jdesktop.swingx.AbstractPatternPanel;
import org.jdesktop.swingx.JXFindBar;
import org.jdesktop.swingx.JXFindPanel;
import org.jdesktop.swingx.search.Searchable;
/**
* A {@link JXFindBar} that is for allowing users to input search text.
*
* @since Trick 10
*/
public class FindBar extends JXFindBar implements ActionListener{
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private Data
//=======================================
private static final long serialVersionUID = 9092192049485321408L;
/** The initial search text for this find bar */
private String initialSearchText = null;
/** By default, this would not have search options as JXFindPanel, true otherwise. */
private boolean hasOptions = false;
// TODO: add pattern support
//private JCheckBox anchorCheck;
//========================================
// Constructors
//========================================
/**
* Default constructor.
*/
public FindBar() {
super();
setNotFoundForegroundColor();
}
/**
* The constructor that specifies total number of popup menus for the panel.
*
* @param searchable An instance of {@link Searchable} from a gui component which
* this search bar is for.
*/
public FindBar(Searchable searchable) {
super(searchable);
setNotFoundForegroundColor();
}
//========================================
// Set/Get methods
//========================================
/**
* Gets to see if case sensitive is checked.
*/
public boolean isCaseSensitive() {
return getPatternModel().isCaseSensitive();
}
/**
* Sets whether to have the options as {@link JXFindPanel}.
*/
public void setOptions(boolean b) {
hasOptions = b;
}
/**
* Updates the searchField that is defined in parent class {@link AbstractPatternPanel}
* if there is initial search text is defined.
*/
public void updateSearchField(String searchText) {
initialSearchText = searchText;
if (searchField != null) {
searchField.setText(searchText);
}
}
/**
* Gets the current search text shown in searchField.
*/
public String getSearchText() {
if (searchField != null) {
return searchField.getText();
}
return null;
}
/**
* Helper method for changing the forground color when the text is not found.
* Since notFoundForegroundColor is proteced in {@link JXFindBar}, extending
* it is the only way to be able to change it.
*
*/
private void setNotFoundForegroundColor() {
notFoundForegroundColor = Color.red;
}
//========================================
// Methods
//========================================
@Override
protected void build() {
if (hasOptions) {
buildBarWithOption();
} else {
buildBar();
}
if (initialSearchText != null) {
updateSearchField(initialSearchText);
}
}
private void buildBar() {
setLayout(new FlowLayout(SwingConstants.LEADING));
add(searchLabel);
add(new JLabel(":"));
add(new JLabel(" "));
add(searchField);
add(findNext);
add(findPrevious);
}
private void buildBarWithOption() {
//anchorCheck = new JCheckBox("Anchor");
//anchorCheck.addActionListener(this);
wrapCheck = new JCheckBox();
backCheck = new JCheckBox();
Box lBox = new Box(BoxLayout.LINE_AXIS);
//lBox.add(anchorCheck);
lBox.add(matchCheck);
lBox.add(wrapCheck);
lBox.add(backCheck);
lBox.setAlignmentY(Component.TOP_ALIGNMENT);
Box mBox = new Box(BoxLayout.LINE_AXIS);
mBox.add(searchLabel);
mBox.add(new JLabel(": "));
mBox.add(searchField);
mBox.add(findNext);
mBox.add(findPrevious);
mBox.setAlignmentY(Component.TOP_ALIGNMENT);
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
add(lBox);
add(mBox);
}
public void actionPerformed(ActionEvent e) {
/*if (e.getSource() == anchorCheck) {
if (anchorCheck.isSelected()) {
getPatternModel().setRegexCreatorKey(PatternModel.REGEX_ANCHORED);
} else {
getPatternModel().setMatchRule(PatternModel.REGEX_MATCH_RULES);
}
}*/
}
}

View File

@ -0,0 +1,311 @@
/*
* $Id: ListPanel.java 2835 2013-03-04 15:06:44Z hchen3 $
*
*/
//========================================
// Package
//========================================
package trick.common.ui.panels;
//========================================
//Imports
//========================================
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.AbstractListModel;
import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.swing.JScrollPane;
import javax.swing.event.ListDataListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import org.jdesktop.swingx.JXList;
import org.jdesktop.swingx.decorator.ColorHighlighter;
import org.jdesktop.swingx.decorator.HighlightPredicate;
import trick.common.TrickApplication;
import trick.common.ui.UIUtils;
import trick.common.utils.SortedListModel;
/**
* A class that extends {@link DataPanel} for displaying a list of data using {@link JXList}.
* All contents are unique.
*
* @author Hong Chen
* @since Trick 10
*/
public class ListPanel extends DataPanel implements ListSelectionListener{
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
/** The model for the data list. */
protected AbstractListModel dataListModel;
//========================================
// Private Data
//========================================
private static final long serialVersionUID = 929091003093241018L;
/** An instance of JXList to represent a list of data shown on the panel. */
private JXList dataList;
//========================================
// Constructors
//========================================
/**
* Default constructor.
*/
public ListPanel() {
super();
dataListModel = new DefaultListModel();
setup();
}
/**
* Constructor with specified list model.
*/
public ListPanel(AbstractListModel model) {
super();
dataListModel = model;
setup();
}
//========================================
// Set/Get methods
//========================================
/**
* Gets the instance of the {@link JList}.
*
* @return The instance of the JList.
*/
public JList getJList() {
return dataList;
}
//========================================
// Methods
//========================================
/**
* Sets up the list with a scroll pane.
*/
protected void setup() {
if (dataListModel == null) {
dataListModel = new DefaultListModel();
}
dataList = new JXList(dataListModel);
setLayout(new BorderLayout());
dataList.setRolloverEnabled(true);
dataList.addHighlighter(new ColorHighlighter(HighlightPredicate.ROLLOVER_ROW, null, Color.MAGENTA));
// Put the JList into a JScrollPane.
JScrollPane scrollpane = new JScrollPane(dataList);
dataList.addListSelectionListener(this);
dataList.addMouseListener(new ListMouseListener());
add(BorderLayout.CENTER, scrollpane);
}
/**
* Adds a {@link MouseListener} to the data list.
*
* @param listener An instance of {@link MouseListener} needs adding the list.
*/
public void addListMouseListener(MouseListener listener) {
if (dataList != null) {
dataList.addMouseListener(listener);
}
}
/**
* Adds data array to the list.
*
* @param items An array of {@link Object} that need adding to the list.
*/
public void addData(Object[] items) {
if (items == null) {
return;
}
for (int i = 0; i < items.length; i++) {
addData(items[i]);
}
}
/**
* Adds one data to the list if it doesn't exist.
*
* @param item The {@link Object} that needs adding to the list.
*/
@SuppressWarnings("unchecked")
public void addData(Object item) {
if (item == null) {
return;
}
if (dataListModel instanceof SortedListModel) {
if (!((SortedListModel)dataListModel).contains(item)) {
((SortedListModel)dataListModel).add(item);
}
} else {
if (!((DefaultListModel)dataListModel).contains(item)) {
((DefaultListModel)dataListModel).addElement(item);
}
}
}
/**
* Removes all of the selected data from the list.
*/
public void removeSelectedData() {
Object[] values = dataList.getSelectedValues();
if (values != null) {
for (int i = 0; i < values.length; i++) {
if (dataListModel instanceof SortedListModel) {
((SortedListModel)dataListModel).removeElement(values[i]);
} else {
((DefaultListModel)dataListModel).removeElement(values[i]);
}
}
}
}
/**
* Removes all specified data from the list.
*
* @param dataArray The specified data array that need removing from the list.
*/
public void removeData(Object[] dataArray) {
if (dataArray != null && dataArray.length > 0) {
for (int i = 0; i < dataArray.length; i++) {
removeData(dataArray[i]);
}
}
}
/**
* Removes one data from the list.
*
* @param item The specified data that needs removing from the list.
*/
public void removeData(Object item) {
if (item==null) {
return;
}
if (dataListModel instanceof SortedListModel) {
((SortedListModel)dataListModel).removeElement(item);
} else {
((DefaultListModel)dataListModel).removeElement(item);
}
}
/**
* Gets all selected data from the list.
*/
public Object[] getSelectedData() {
return dataList.getSelectedValues();
}
/**
* Gets the first selected value, or <code>null</code> if the selection is empty.
*/
public Object getSelectedFirstData() {
return dataList.getSelectedValue();
}
/**
* Gets all data from the list.
*/
public Object[] getAllData() {
if (dataListModel instanceof SortedListModel) {
return ((SortedListModel)dataListModel).toArray();
}
return ((DefaultListModel)dataListModel).toArray();
}
/**
* Removes all data from the list.
*/
public void removeAllData() {
if (dataListModel instanceof SortedListModel) {
((SortedListModel)dataListModel).clear();
} else {
((DefaultListModel)dataListModel).clear();
}
}
/**
* Required by {@link ListSelectionListener} interface.
*/
public void valueChanged(ListSelectionEvent evt) {
evt.getSource();
}
public void addListDataListener(ListDataListener listener) {
dataListModel.addListDataListener(listener);
}
//========================================
// Inner classes
//========================================
/**
* Using an inner class to define MouseListener to help organize code better.
* The goal of this class is to handle mouse calls and forward them
* to the interested parties.
*/
private class ListMouseListener extends MouseAdapter {
//========================================
// MouseListener methods
//========================================
/**
* Invoked when the mouse button has been clicked (pressed
* and released) on a component.
*
* @param e MouseEvent sent from system.
*/
public void mouseClicked(MouseEvent e)
{
// there is nothing shown or the list is empty, return without doing anything.
if (dataListModel.getSize() < 1) {
return;
}
if( UIUtils.isRightMouseClick(e) ) {
int index = dataList.locationToIndex(e.getPoint());
if (index > -1) {
int[] selectedIndices = dataList.getSelectedIndices();
int[] extendedIndices = new int[selectedIndices.length+1];
System.arraycopy(selectedIndices, 0, extendedIndices, 0, selectedIndices.length);
// Adds the right-clicked one to the selected list
extendedIndices[extendedIndices.length-1] = index;
dataList.setSelectedIndices(extendedIndices);
}
if (getPopup(0) != null && !getPopup(0).isVisible()) {
TrickApplication.setPopupInvoker(getType());
getPopup(0).show(e.getComponent(), e.getX(), e.getY());
}
}
}
}
}

View File

@ -0,0 +1,33 @@
//========================================
// Package
//========================================
package trick.common.ui.panels;
//========================================
// Package
//========================================
import java.net.URL;
import javax.swing.ImageIcon;
import org.jdesktop.swingx.JXLabel;
import trick.common.TrickApplication;
public class SmallTrickIconLabel extends JXLabel {
private static final long serialVersionUID = -1272978741978959753L;
/**
* creates a label displaying a small Trick icon with version information tool tip
*/
public SmallTrickIconLabel() {
URL imageURL = TrickApplication.class.getResource("resources/trick_small.gif");
if (imageURL != null) {
String description = "Trick Version " + System.getenv("TRICK_VER");
setIcon(new ImageIcon(imageURL, description));
setToolTipText(description);
}
}
}

View File

@ -0,0 +1,335 @@
/*
* $Id: BinaryDataReader.java 3544 2014-05-30 21:00:01Z hchen3 $
*
*/
//========================================
// Package
//========================================
package trick.common.utils;
//========================================
// Imports
//========================================
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import trick.common.utils.LogVar.DisplayType;
import trick.common.utils.LogVar.TrickType;
import trick.dataproducts.trickqp.utils.ProductVar;
/**
* This data reader is for retrieving the recorded variable list out of Trick recorded binary data.
*
*
* @since Trick 10
*/
public class BinaryDataReader extends DataReader {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
private int numParams;
private long headerBytes;
private boolean isLittleEndian;
private FileInputStream fileInputStream;
//========================================
// Constructors
//========================================
/**
* Constructs a reader with specified file name.
*
* @param fileName The name of the file.
*/
public BinaryDataReader(String fileName) {
super(fileName);
}
/**
* Constructs a reader with specified file.
*
* @param file An instance of {@link File} for the reader to read.
*/
public BinaryDataReader(File file) {
super(file);
}
//========================================
// Set/Get methods
//========================================
//========================================
// Methods
//========================================
/**
* Processes the recorded data. Required by {@link DataReader}.
*/
@Override
protected void processHeader() throws FileNotFoundException, IOException {
FileInputStream inFile = new FileInputStream(dataFile);
// 10 bytes are for endian spec
String endianStr = readBytesToString(inFile, 10);
headerBytes += 10;
if (endianStr.endsWith("-L")) {
isLittleEndian = true;
}
numParams = readBytesToInt(inFile, 4);
headerBytes += 4;
// now go through the header for this data file
for (int k = 0; k < numParams; k++) {
// 4 bytes for the length of this param name
int paramNameLen = readBytesToInt(inFile, 4);
headerBytes += 4;
// paramNameLen bytes for the param name
String paramName = readBytesToString(inFile, paramNameLen);
headerBytes += paramNameLen;
LogVar varObj = new LogVar(paramName);
// 4 bytes for the length of the units
int unitsLen = readBytesToInt(inFile, 4);
headerBytes += 4;
// unitsLen bytes for the units
// TODO: unit conversion for Trick-05*
varObj.setUnits(readBytesToString(inFile, unitsLen));
headerBytes += unitsLen;
// 4 bytes for the type id
int typeId = readBytesToInt(inFile, 4);
headerBytes += 4;
int size = readBytesToInt(inFile, 4);
headerBytes += 4;
TrickType varType = TrickType.TRICK_DOUBLE;
//varObj.setType(getType(typeId));
if (typeId > -1 && typeId < TrickType.values().length) {
varType = TrickType.values()[typeId];
}
varObj.setType(varType);
varObj.setSize(size);
varObj.setDisplay(DisplayType.NORMAL);
varObj.setLevel(0);
varObj.setCount(1);
varObj.setIsFromLog(true);
varObj.setRunDir(dataFile.getParent());
recordedVarList.add(varObj);
}
if (inFile != null) {
inFile.close();
}
}
/**
* Helper method for reading specified number of bytes from a binary file and convert it to an int.
*/
private int readBytesToInt(FileInputStream inFile, int numBytes) throws IOException {
ByteBuffer byteBuf = readBytes(inFile, numBytes);
return byteBuf.getInt();
}
/**
* Helper method for reading specified number of bytes from a binary file with correct format.
*/
private ByteBuffer readBytes(FileInputStream inFile, int numBytes) throws IOException {
byte[] bytes = new byte[numBytes];
inFile.read(bytes);
ByteBuffer byteBuf = ByteBuffer.wrap(bytes);
// Java native format is big endian, no need to set the order for bit endian.
if (isLittleEndian) {
byteBuf.order(ByteOrder.LITTLE_ENDIAN);
}
return byteBuf;
}
/**
* Helper method for reading specified number bytes from a binary file and convert it to a string.
*/
private String readBytesToString(FileInputStream inFile, int numBytes) throws IOException {
byte[] bytes = new byte[numBytes];
inFile.read(bytes);
return new String(bytes);
}
@Override
public void beginRead(ProductVar var) throws IOException {
super.beginRead(var);
fileInputStream = new FileInputStream(dataFile);
fileInputStream.skip(headerBytes);
}
@Override
public double getVarValue() throws IOException {
double varData = Double.NaN;
boolean isDone = false;
while (true) {
boolean varFound = false;
boolean timeFound = false;
boolean goodTime = true;
for (int j = 0; j < numParams; j++) {
LogVar thisVar = (LogVar)recordedVarList.get(j);
byte[] bytes = new byte[thisVar.getSize()];
if (fileInputStream.read(bytes) == -1) {
isDone = true;
break;
}
ByteBuffer byteBuf = ByteBuffer.wrap(bytes);
// Java native format is big endian, no need to set the order for bit endian.
if (isLittleEndian) {
byteBuf.order(ByteOrder.LITTLE_ENDIAN);
}
if (j == timeIndex) {
timeFound = true;
theTimeValue = byteBuf.getDouble();
goodTime = isTimeInRange(theTimeValue);
}
if (j == theVarIndex) {
if (timeIndex == theVarIndex) {
varData = theTimeValue;
} else {
if (thisVar.getType() != null) {
switch (thisVar.getType()) {
//case TRICK_VOID:
//case TRICK_CHARACTER:
//case TRICK_UNSIGNED_CHARACTER:
//case TRICK_STRING:
case TRICK_SHORT:
case TRICK_UNSIGNED_SHORT:
varData = byteBuf.getShort();
break;
case TRICK_INTEGER:
case TRICK_UNSIGNED_INTEGER:
varData = byteBuf.getInt();
break;
case TRICK_LONG:
case TRICK_UNSIGNED_LONG:
case TRICK_LONG_LONG:
case TRICK_UNSIGNED_LONG_LONG:
varData = byteBuf.getLong();
break;
case TRICK_FLOAT:
varData = byteBuf.getFloat();
break;
case TRICK_DOUBLE:
varData = byteBuf.getDouble();
break;
case TRICK_BITFIELD:
case TRICK_UNSIGNED_BITFIELD:
if (thisVar.getSize() == 1) {
varData = byteBuf.getChar();
} else if (thisVar.getSize() == 2) {
varData = byteBuf.getShort();
} else if (thisVar.getSize() == 4) {
varData = byteBuf.getInt();
}
break;
default:
break;
//case TRICK_FILE_PTR:
//case TRICK_BOOLEAN:
//case TRICK_WCHAR:
//case TRICK_WSTRING:
//case TRICK_VOID_PTR:
//case TRICK_ENUMERATED:
//case TRICK_STRUCTURED:
//case TRICK_USER_DEFINED_TYPE:
//case TRICK_NUMBER_OF_TYPES:
}
}
}
varFound = true;
}
if (varFound && timeFound) {
if (goodTime) {
try {
varData = applyVarProperties(varData);
isDone = true;
} catch (UnitType.IllegalUnitConversionException e) {
System.out.println(e.getMessage());
System.out.println(e.getCause());
// set varFound false as no need to go through all log data
// if unit conversion can't be performed for the variable
varFound = false;
break;
}
}
int needToSkipNum = Math.max(timeIndex, theVarIndex);
for (int k = needToSkipNum + 1; k < recordedVarList.size(); k ++) {
LogVar theVar = (LogVar)recordedVarList.get(k);
fileInputStream.skip(theVar.getSize());
}
break;
}
}
if (!varFound || isDone) {
break;
}
}
return varData;
}
@Override
public boolean isEnd() {
boolean ret = false;
if (fileInputStream == null) {
ret = true;
}
try {
if (fileInputStream.available() < 1) {
ret = true;
}
} catch (IOException e) {
e.printStackTrace();
}
return ret;
}
@Override
public void endRead() {
if (fileInputStream != null) {
try {
fileInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

View File

@ -0,0 +1,189 @@
/*
* $Id: CSVDataReader.java 3536 2014-05-22 19:38:33Z hchen3 $
*
*/
//========================================
// Package
//========================================
package trick.common.utils;
//========================================
// Imports
//========================================
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Scanner;
import trick.common.utils.LogVar.DisplayType;
import trick.common.utils.UnitType.IllegalUnitConversionException;
import trick.dataproducts.trickqp.utils.ProductVar;
/**
* This data reader is for retrieving the recorded variable list out of Trick recorded csv data.
*
*
* @since Trick 10
*/
public class CSVDataReader extends DataReader {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
private BufferedReader bufferedDataReader = null;
//========================================
// Constructors
//========================================
/**
* Constructs a reader with specified file name.
*
* @param fileName The name of the file.
*/
public CSVDataReader(String fileName) {
super(fileName);
}
/**
* Constructs a reader with specified file.
*
* @param file An instance of {@link File} for the reader to read.
*/
public CSVDataReader(File file) {
super(file);
}
//========================================
// Set/Get methods
//========================================
//========================================
// Methods
//========================================
/**
* Processes the recorded data. Required by {@link DataReader}.
*/
@Override
protected void processHeader() throws FileNotFoundException, IOException {
Scanner scanner = new Scanner(dataFile);
try {
String headerLine = scanner.nextLine();
headerLine = headerLine.replaceAll("[{}]", "");
String[] tokens = headerLine.split(",");
for (String eachToken : tokens) {
String[] varPair = eachToken.split("\\s+");
LogVar varObj = new LogVar(varPair[0]);
if (varPair.length > 1) {
varObj.setUnits(varPair[1]);
}
// TODO: type?
varObj.setDisplay(DisplayType.NORMAL);
varObj.setLevel(0);
varObj.setCount(1);
varObj.setIsFromLog(true);
varObj.setRunDir(dataFile.getParent());
recordedVarList.add(varObj);
}
}
finally {
if (scanner != null) {
scanner.close();
}
}
}
/**
* Starts the process for getting variable value.
*
* @param var the variable name which need retrieving value for.
* @throws IOException
*/
@Override
public void beginRead(ProductVar var) throws IOException {
super.beginRead(var);
bufferedDataReader = new BufferedReader(new InputStreamReader(new FileInputStream(dataFile)));
bufferedDataReader.readLine(); // ignore header
}
/**
* Ends the process for getting value.
*/
@Override
public void endRead() {
if (bufferedDataReader != null) {
try {
bufferedDataReader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@Override
public double getVarValue() throws IOException {
String oneLine = bufferedDataReader.readLine();
while (oneLine != null && !oneLine.isEmpty()) {
String[] dataStrList = oneLine.split(",");
// if time stamp is not recorded, no need to verify it
if (timeIndex > -1) {
theTimeValue = Double.parseDouble(dataStrList[timeIndex]);
if (!isTimeInRange(theTimeValue)){
oneLine = bufferedDataReader.readLine();
continue;
}
}
double varData = Double.parseDouble(dataStrList[theVarIndex]);
try {
varData = applyVarProperties(varData);
} catch (IllegalUnitConversionException e) {
break;
}
return varData;
}
return Double.NaN;
}
@Override
public boolean isEnd() {
boolean ret = false;
if (bufferedDataReader == null) {
ret = true;
}
try {
if (bufferedDataReader.readLine() == null) {
ret = true;
}
} catch (IOException e) {
e.printStackTrace();
}
return ret;
}
}

View File

@ -0,0 +1,339 @@
/*
* $Id: DataReader.java 3536 2014-05-22 19:38:33Z hchen3 $
*/
//========================================
// Package
//========================================
package trick.common.utils;
//========================================
// Imports
//========================================
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import trick.common.TrickApplication;
import trick.dataproducts.trickqp.utils.ProductVar;
/**
* This data reader is for reading recorded data from different type of files.
*
*
* @since Trick 10
*/
public abstract class DataReader {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
protected File dataFile;
protected List<Object> recordedVarList;
protected double theTimeValue = Double.NaN;
protected int theVarIndex = -1;
protected ProductVar theVar;
protected Double tstart;
protected Double tstop;
protected Double frequency;
// the index number of time name in the recordedVarList, by default, it's the 1st variable on the list
protected int timeIndex = 0;
protected String timename = TrickApplication.DEFAULT_TIME_NAME;
//========================================
// Private Data
//========================================
private static double EPSILON = 1e-9;
//========================================
// Constructors
//========================================
/**
* Constructs the reader with specified file name.
* Once the reader is created, its header is always
* processed so that the recorded variable list is
* ready to use.
*
* @param fileName The name of the file for the reader to read.
*/
public DataReader(String fileName) {
this(new File(fileName));
}
/**
* Constructs the reader with specified {@link File}.
* Once the reader is created, its header is always
* processed so that the recorded variable list is
* ready to use.
*
* @param file An instance of {@link File} for the reader to read.
*/
public DataReader(File file) {
dataFile = file;
init();
try {
processHeader();
} catch (FileNotFoundException e) {
System.out.println("Error: " + file.getPath() + " can not be found!");
} catch (IOException e) {
System.out.println("I/O Exception: " + file.getPath());
}
timeIndex = locateVarIndex(timename);
}
//========================================
// Set/Get methods
//========================================
/**
* Gets the variable list that is recorded either from the header file or the data file.
*
* @return A {@link List} of variables that are recorded.
*/
public List<Object> getRecordedVarList() {
return recordedVarList;
}
/**
* Sets the variable which the reader needs reading data for.
*
* @param var An instance of {@link ProductVar} for the variable.
*/
public void setVar(ProductVar var) {
theVar = var;
}
/**
* Sets the start time object for the XY data series.
*
* @param start The start time object.
*/
public void setTStart(Double start) {
tstart = start;
}
/**
* Sets the stop time object for the XY data series.
*
* @param stop The stop time object;
*/
public void setTStop(Double stop) {
tstop = stop;
}
/**
* Sets the time name for this data reader.
*
* @param name The time name for the data reader.
*/
public void setTimename(String name) {
// if name is null, name keeps its default that is DEFAULT_TIME_NAME(sys.exec.out.time)
if (name != null && !name.equals(timename)) {
timename = name;
timeIndex = locateVarIndex(timename);
// if can't find the specified timename, go back to the default one
if (timeIndex == -1) {
timename = TrickApplication.DEFAULT_TIME_NAME;
timeIndex = locateVarIndex(timename);
}
}
}
/**
* Gets the log variable for the specified variable.
*/
public LogVar getLogVar(String varName) {
LogVar logVar = null;
if (recordedVarList != null) {
for (Object thisVar : recordedVarList) {
if (thisVar instanceof LogVar) {
if (((LogVar)thisVar).getName().equals(varName)) {
logVar = (LogVar)thisVar;
break;
}
}
}
}
return logVar;
}
//========================================
// Methods
//========================================
/**
* Initialize.
*/
private void init() {
recordedVarList = new ArrayList<Object>();
}
/**
* Starts the process for getting value.
*
* @param var the variable name which need retrieving value for.
* @throws IOException
*/
public void beginRead(ProductVar var) throws IOException {
theVarIndex = locateVarIndex(var.getName());
theVar = var;
}
/**
* Gets the variable value.
*
* @return The variable value.
*
* @throws IOException
*/
public abstract double getVarValue() throws IOException;
/**
* Ends the process for getting value.
*/
public abstract void endRead();
/**
* Checks to see if this reader reaches its end.
*
* @return True if the reader reaches its end, false otherwise.
*/
public boolean isEnd() {
return false;
}
/**
* Returns the index number of a variable in the list based on its name.
*/
public int locateVarIndex(String varName) {
int idx = -1;
for (int i = 0; i < recordedVarList.size(); i++) {
LogVar thisVar = (LogVar)recordedVarList.get(i);
if (thisVar.getName().equals(varName)) {
idx = i;
}
if (idx != -1) {
break;
}
}
return idx;
}
/**
* Checks to see if the time is in the range of specified tstart and tstop if applicable.
* If the range is not specified, true is always returned.
*
* @see #tstart
* @see #tstop
*/
public boolean isTimeInRange(double timeData) {
boolean ret = true;
if (tstart != null || tstop != null) {
ret = false;
if (tstart != null) {
if (timeData >= tstart.doubleValue()) {
ret = true;
} else {
ret = false;
}
}
if (tstop != null) {
if (timeData <= tstop.doubleValue()) {
ret = ret && true;
} else {
ret = false;
}
}
}
return ret;
}
/**
* Gets the time stamp for the specified variable value retrieved.
*/
public double getTimeValue() {
return theTimeValue;
}
/**
* Abstract method for processing the data recording file.
* This method needs to be called after a {@link DataReader} instance
* is created in order for recordedVarList to be filled in.
*/
protected abstract void processHeader() throws FileNotFoundException, IOException;
/**
* Checks to see if 2 doubles are almost equal with specified Epsilon.
*/
public static boolean nearlyEqual(double a, double b, double eps) {
if (a == b) {
return true;
}
return Math.abs(a - b) < eps * Math.max(Math.abs(a), Math.abs(b));
}
/**
* Checks to see if 2 doubles are almost equal with the default Epsilon.
*/
public static boolean nearlyEqual(double a, double b) {
return nearlyEqual(a, b, EPSILON);
}
/**
* Updates the value of the variable properties such as scale, bias, and units.
*/
protected double applyVarProperties(double varData) throws UnitType.IllegalUnitConversionException {
if (theVar.getScale() != null) {
varData = theVar.getScale().doubleValue() * varData;
}
if (theVar.getBias() != null) {
varData = varData + theVar.getBias().doubleValue();
}
if (theVar.getUnits() != null) {
varData = convertUnits(varData, getLogVar(theVar.getName()), theVar);
}
return varData;
}
/**
* Converts log variable value to product variable value based on their units.
*
* @throws UnitType.IllegalUnitConversionException if units conversion error.
*/
private double convertUnits(double fromValue, LogVar fromVar, ProductVar toVar) throws UnitType.IllegalUnitConversionException {
double toValue = fromValue;
String fromUnits = null;
if (fromVar.getUnits() == null && toVar.getFromUnits() != null && !toVar.getFromUnits().isEmpty()) {
fromUnits = toVar.getFromUnits();
} else {
fromUnits = fromVar.getUnits();
}
if (fromUnits != null && !fromUnits.equals(toVar.getUnits())) {
try {
toValue = UnitType.convertUnits(fromValue, fromVar.getUnits(), toVar.getUnits());
} catch (UnitType.IllegalUnitConversionException e) {
throw new UnitType.IllegalUnitConversionException("===" + fromVar.getName() + ": [" + fromVar.getUnits() + "]", toVar.getName() + ": [" + toVar.getUnits() + "]");
}
}
return toValue;
}
}

View File

@ -0,0 +1,85 @@
/*
* $Id: ErrorChecker.java 1306 2010-12-07 19:16:33Z hchen $
*
*/
//========================================
// Package
//========================================
package trick.common.utils;
//========================================
// Imports
//========================================
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
/**
* Defines erro handler to deal with irregularities that come up
* during the parsing of a XML document.
*
*
* @since Trick 10
*/
public class ErrorChecker extends DefaultHandler{
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
// Exception message
private String exceptionMessage;
//========================================
// Constructors
//========================================
public ErrorChecker(){
}
//========================================
// Set/Get methods
//========================================
//========================================
// Methods
//========================================
public void error(SAXParseException e) {
exceptionMessage = "Parsing error: " + e.getMessage();
//System.out.println(exceptionMessage);
}
public void warning(SAXParseException e) {
exceptionMessage = "Parsing error: " + e.getMessage();
//System.out.println(exceptionMessage);
}
public void fatalError(SAXParseException e) {
exceptionMessage = "Parsing error: " + e.getMessage();
//System.out.println(exceptionMessage);
//System.out.println("Cannot continue.");
//System.exit(1);
}
/**
* Gets the exception message.
*
* @return a text message describing the exception.
*/
public String getExceptionMessage() {
return exceptionMessage;
}
}

View File

@ -0,0 +1,168 @@
/*
* $Id: LogHeaderReader.java 3544 2014-05-30 21:00:01Z hchen3 $
*
*/
//========================================
// Package
//========================================
package trick.common.utils;
//========================================
// Imports
//========================================
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Scanner;
import trick.common.utils.LogVar.DisplayType;
/**
* This data reader is for reading Trick log header data.
*
*
* @since Trick 10
*/
public class LogHeaderReader extends DataReader{
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
//========================================
// Constructors
//========================================
/**
* Constructs a reader with specified file name.
*
* @param fileName The name of the file.
*/
public LogHeaderReader(String fileName) {
super(fileName);
}
/**
* Constructs a reader with specified file.
*
* @param file An instance of {@link File} for the reader to read.
*/
public LogHeaderReader(File file) {
super(file);
}
//========================================
// Set/Get methods
//========================================
//========================================
// Methods
//========================================
/**
* Processes the recorded data. Required by {@link DataReader}.
*/
@Override
protected void processHeader() throws FileNotFoundException, IOException {
parseContents();
}
/**
* Gets the contents from the file as a {@link List}.
*
* @return A {@link List} of data objects representing all needed data in the recorded file.
*/
private void parseContents() throws FileNotFoundException {
Scanner scanner = new Scanner(dataFile);
try {
//first use a Scanner to get each line
while ( scanner.hasNextLine() ){
Object eachLine = processLine(scanner.nextLine());
if (eachLine != null) {
recordedVarList.add(eachLine);
}
}
}
finally {
//ensure the underlying stream is always closed
scanner.close();
}
}
/**
* Processes a line of text. Required by {@link DataReader}.
*
* @return An object of {@link LogVar} to represent a line of recorded header data,
* <code>null</code> if non-related data found in this line.
*/
private Object processLine(String theLine) {
if (theLine.endsWith("ASCII")) {
return null;
}
LogVar varObj = null;
//use a second Scanner to parse the content of each line
Scanner scanner = new Scanner(theLine);
// by default, the scanner uses whitespace for the delimiter
// and this is what in recorded data
if ( scanner.hasNext() ) {
scanner.next(); // ignore the first item at each line
String type = null;
String units = null;
String name = null;
if (scanner.hasNext()) {
type = scanner.next();
}
if (scanner.hasNext()) {
units = scanner.next();
}
if (scanner.hasNext()) {
name = scanner.next();
if ( ! type.equals("byte_order")) {
varObj = new LogVar(name);
varObj.setUnits(units);
varObj.setRunDir(dataFile.getParent());
varObj.setDisplay(DisplayType.NORMAL);
varObj.setLevel(0);
varObj.setCount(1);
varObj.setIsFromLog(true);
}
}
}
//no need for finally here, since String is source
scanner.close();
return varObj;
}
@Override
public double getVarValue() throws IOException {
// there is no value in the header file
return Double.NaN;
}
@Override
public void endRead() {
// do nothing
}
}

View File

@ -0,0 +1,402 @@
/*
* $Id: LogVar.java 3772 2015-01-06 18:23:32Z hchen3 $
*
*/
//========================================
// Package
//========================================
package trick.common.utils;
//========================================
// Imports
//========================================
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Defines each variable object for recorded data.
*
*
* @since Trick 10
*/
public class LogVar implements Comparable<LogVar>, Serializable {
//========================================
// Public data
//========================================
public enum DisplayType { NORMAL, EXPANDED, CONTRACTED, HIDDEN }
public static enum TrickType {
TRICK_VOID,
TRICK_CHARACTER,
TRICK_UNSIGNED_CHARACTER,
TRICK_STRING,
TRICK_SHORT,
TRICK_UNSIGNED_SHORT,
TRICK_INTEGER,
TRICK_UNSIGNED_INTEGER,
TRICK_LONG,
TRICK_UNSIGNED_LONG,
TRICK_FLOAT,
TRICK_DOUBLE,
TRICK_BITFIELD,
TRICK_UNSIGNED_BITFIELD,
TRICK_LONG_LONG,
TRICK_UNSIGNED_LONG_LONG,
TRICK_FILE_PTR,
TRICK_BOOLEAN,
TRICK_WCHAR,
TRICK_WSTRING,
TRICK_VOID_PTR,
TRICK_ENUMERATED,
TRICK_STRUCTURED,
TRICK_USER_DEFINED_TYPE,
TRICK_NUMBER_OF_TYPES
}
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
private static final long serialVersionUID = 1136627204616267499L;
private String name;
private String units;
private String runDir; // for when run dir of this var is needed such as delta plot
private TrickType type; // only needed when reading data out of a binary data file
private int size; // needed when reading data out of a binary data file
private DisplayType display; // tell how to display variable in list
private int level; // number indicating what level of expansion this is for an arrayed variable
private String sort_name; // name used for sorting in displayed varlist
private int count; // count how many RUN dirs this variable is in
private boolean isFromLog; // flag to indicate if this var is really from the log file, not by gui creation
private DisplayType prevDisplay; // the place holder for previous display type of this variable, used if searching variable is performed
//========================================
// Constructors
//========================================
/**
* Constructor with specified variable name.
*
* @param name The name of the sim variable.
*/
public LogVar(String name) {
this.name = name;
this.setSortName(name);
}
/**
* Copy constructor.
*
* @param obj The LogVar object to copy.
*/
public LogVar(Object obj) {
if (! (obj instanceof LogVar)) {
this.name = "";
return;
}
LogVar source = (LogVar)obj;
this.name = source.name;
this.setSortName(source.name);
this.units = source.units;
this.runDir = source.runDir;
this.type = source.type;
this.display = source.display;
this.level = source.level;
this.count = source.count;
}
//========================================
// Set/Get methods
//========================================
/**
* Sets the name for the variable.
*
* @param name The variable name.
*/
public void setName(String name) {
this.name = name;
this.setSortName(name);
}
/**
* Sets the unit for the variable.
*
* @param units The variable unit.
*/
public void setUnits(String units) {
this.units = units;
}
/**
* Sets the run directory which the recorded data is in.
*
* @param dir The run directory.
*/
public void setRunDir(String dir) {
runDir = dir;
}
/**
* Sets the isFromLog flag.
*/
public void setIsFromLog(boolean b) {
isFromLog = b;
}
/**
* Sets the variable data type.
*
* @param type The type of the variable.
*/
public void setType(TrickType type) {
this.type = type;
}
/**
* Sets how to display this variable in list.
*
* @param display true or false.
*/
public void setDisplay(DisplayType display) {
this.display = display;
}
/**
* Sets expand level of this variable.
*
* @param level The expand level of the variable.
*/
public void setLevel(int level) {
this.level = level;
}
/**
* Sets the variable's sort name.
* (if it's an expanded variable, name contains parent array name; any indices get leading zeros)
*
* @param name The sort name variable.
*/
public void setSortName(String name) {
this.sort_name = name;
// add leading zeros to all array indices (e.g. so x[10] does not come before x[2])
// is this slow? seems to work ok
String regex;
Pattern p;
Matcher m;
regex = "\\[(\\d\\d\\d)\\]"; // [nnn] -> [0nnn]
p = Pattern.compile(regex);
m = p.matcher(this.sort_name);
this.sort_name = m.replaceAll("\\[00$1\\]");
regex = "\\[(\\d\\d)\\]"; // [nn] -> [00nn]
p = Pattern.compile(regex);
m = p.matcher(this.sort_name);
this.sort_name = m.replaceAll("\\[00$1\\]");
regex = "\\[(\\d)\\]"; // [n] -> [000n]
p = Pattern.compile(regex);
m = p.matcher(this.sort_name);
this.sort_name = m.replaceAll("\\[000$1\\]");
}
/**
* Sets how many RUN dirs this variable belongs to.
*
* @param count The RUN dir count of the variable.
*/
public void setCount(int count) {
this.count = count;
}
/**
* Sets the size of for this variable.
*
* @param size The size of this variable in bytes.
*/
public void setSize(int size) {
this.size = size;
}
/**
* Remembers the previous display type.
*
* @param prevDisplay The previous {@link LogVar.DisplayType} of this variable.
*/
public void setPrevDisplay(DisplayType prevDisplay) {
this.prevDisplay = prevDisplay;
}
/**
* Gets the previous display type.
*
* @return The previous {@link LogVar.DisplayType} of this variable.
*/
public DisplayType getPrevDisplay() {
return prevDisplay;
}
/**
* Gets the size of this variable.
*
* @return The size of this variable in bytes.
*/
public int getSize() {
return size;
}
/**
* Gets the name of the variable.
*
* @return The name of the variable.
*/
public String getName() {
return name;
}
/**
* Gets the units of the variable.
*
* @return The units of the variable.
*/
public String getUnits() {
return units;
}
/**
* Gets the type of the variable
*
* @return The type of the variable.
*/
public TrickType getType() {
return type;
}
/**
* Gets the run directory which the recorded data is in.
*
* @return The run directory.
*/
public String getRunDir() {
return runDir;
}
/**
* Gets the flag of isFromLog.
*/
public boolean getIsFromLog() {
return isFromLog;
}
/**
* Return if how th variable is to be displayed in list.
*
* @return true or false.
*/
public DisplayType getDisplay() {
return display;
}
/**
* Gets expand level of this variable.
*
* @return The expand level of the variable.
*/
public int getLevel() {
return level;
}
/**
* Gets the variable's sort name.
*
* @return The sort name variable.
*/
public String getSortName() {
return sort_name;
}
/**
* Gets how many RUN dirs this variable belongs to.
*
* @return The count of the variable.
*/
public int getCount() {
return count;
}
//========================================
// Methods
//========================================
/**
* Overrides toString() method in Object class so that it returns the value
* as desired instead of the value of
* <blockquote>
* <pre>
* getClass().getName() + '@' + Integer.toHexString(hashCode())
* </pre></blockquote>
*
* @return a string representation of the object.
*/
@Override
public String toString() {
return name + " (" + units + ")";
}
/**
* Required by Comparable interface. When two LogVar objects compare, only
* name gets compared.
*
* @param o the object to be compared.
* @return a negative integer, zero, or a positive integer as this object
* is less than, equal to, or greater than the specified object.
*/
// this is what is used when sorting items in varlist
public int compareTo(LogVar o) {
if (name != null && o.name != null) {
// sort name makes expanded variables be shown directly below their parent
// also indices have leading zeros so components shown in numerical order
String compare1 = sort_name;
String compare2 = o.sort_name;
return compare1.compareTo(compare2);
} else {
return 0;
}
}
// must override equals so that calling contains for list of LogVars will work
@Override
public boolean equals(Object o) {
if (!(o instanceof LogVar)) {
return false;
}
LogVar varObj = (LogVar) o;
if (name != null && varObj.name != null) {
return name.equals(varObj.name);
} else {
return false;
}
}
// Serializable writeObject method - without this you get a NotSerializableException during drag/drop
private void writeObject(
ObjectOutputStream aOutputStream
) throws IOException {
//perform the default serialization for all non-transient, non-static fields
aOutputStream.defaultWriteObject();
}
}

View File

@ -0,0 +1,222 @@
/*
* $Id: SortedListModel.java 2266 2012-03-29 15:58:38Z hchen3 $
*
*/
//========================================
// Package
//========================================
package trick.common.utils;
//========================================
//Imports
//========================================
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.SortedSet;
import java.util.TreeSet;
import javax.swing.AbstractListModel;
import org.jdesktop.swingx.JXList;
/**
* A class that extends {@link AbstractListModel} for providing a {@link JXList} with
* sorted contents with uniqueness.
*
* @author Hong Chen
* @since Trick 10
*/
public class SortedListModel extends AbstractListModel {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
private static final long serialVersionUID = -4554077303172728923L;
/** For holding the data of the list. */
private SortedSet<Object> set;
//========================================
// Constructors
//========================================
/**
* Constructs a SortedListModel.
*/
public SortedListModel() {
set = new TreeSet<Object>();
}
//========================================
// Set/Get methods
//========================================
/**
* Gets the size of the list.
*
* @return The size of the list.
*/
public int getSize() {
return set.size();
}
/**
* Gets an element from the list based the index number.
*
* @param index The index number of the data from the list.
*
* @return An element at the specified index number from the list if possible, otherwise <code>null</code> is returned.
*/
public Object getElementAt(int index) {
// in case, index is out of bound
if (index < getSize()) {
return set.toArray()[index];
}
return null;
}
/**
* Gets object from list with same name as the given element.
*
* @param element The element to get.
*
* @return The object with same name as element, or null if not in list.
*/
public Object getElement(Object element) {
//if (set.contains(element)) {
Object[] objs = set.toArray();
String element_string;
for (int ii=0; ii<objs.length; ii++) {
if (element instanceof LogVar) {
// ignore variable units
element_string = ((LogVar)element).getName();
} else {
element_string = element.toString();
}
if (objs[ii].toString().startsWith(element_string)) {
return objs[ii];
}
}
//}
return null;
}
//========================================
// Methods
//========================================
/**
* Returns the list as an array.
*
* @return The array of the data.
*/
public Object[] toArray() {
return set.toArray();
}
/**
* Adds one element to the list if it is not already present.
*/
public void add(Object element) {
if (set.add(element)) {
fireContentsChanged(this, 0, getSize());
}
}
/**
* Adds all of the elements to the list.
*/
public void addAll(Object elements[]) {
Collection<Object> c = Arrays.asList(elements);
set.addAll(c);
fireContentsChanged(this, 0, getSize());
}
/**
* Removes all of the elements from the list.
*/
public void clear() {
set.clear();
fireContentsChanged(this, 0, getSize());
}
/**
* Redraw all elements of list -- need this when hiding rows.
*/
public void refresh() {
fireContentsChanged(this, 0, getSize());
}
/**
* Checks to see if the list contains the sepcified element.
*
* @param element Element whose presence in this list is to be tested.
*
* @return <code>true</code> if the list contains the specified element, <code>false</code> otherwise.
*/
public boolean contains(Object element) {
return set.contains(element);
}
/**
* Returns the first element from the list.
*
* @return The first element of the list.
*/
public Object firstElement() {
return set.first();
}
/**
* Returns the iterator over the elements in this list.
*
* @return An iterator over the elements in this list.
*/
public Iterator iterator() {
return set.iterator();
}
/**
* Returns the last element from the list.
*
* @return The last element of the list.
*/
public Object lastElement() {
return set.last();
}
/**
* Removes the specified element from this list if it is present.
*
* @param element Element to be removed from this list, if present.
*
* @return <code>true</code> if this list contains the specified element, <code>false</code> otherwise.
*/
public boolean removeElement(Object element) {
if (getSize() < 0) {
return false;
}
boolean removed = set.remove(element);
if (removed) {
fireContentsChanged(this, 0, getSize());
}
return removed;
}
//========================================
// Inner classes
//========================================
}

View File

@ -0,0 +1,288 @@
/*
* $Id: TrickColors.java 3535 2014-05-22 19:25:51Z hchen3 $
*
*/
//========================================
// Package
//========================================
package trick.common.utils;
//========================================
//Imports
//========================================
import java.awt.Color;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* Provides all colors supported for using its names.
* Otherwise, the color code needs using.
*
* @author Hong Chen
* @since Trick 13
*/
public class TrickColors {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
/** Map between color names and colors */
private static Map<String, Color> name2color = new HashMap<String, Color>();
/** Map between colors and color names */
private static Map<Color, String> color2name = new HashMap<Color, String>();
//========================================
// Constructors
//========================================
//========================================
// Methods
//========================================
/**
* Initialize colors map.
*/
private static void initColorsMap() {
Field[] fields = TrickColors.class.getFields();
for (Field field : fields) {
if (field.getType().isAssignableFrom(Color.class)) {
addColor(field.getName());
}
}
}
/**
* Used to initialize the map.
*/
private static void addColor(String colorName, Color color) {
name2color.put(colorName, color);
color2name.put(color, colorName);
}
/**
* Used to initialize the map.
*/
private static void addColor(String colorName) {
addColor(colorName, getColorFromField(colorName));
}
/**
* Returns a color with the specified case-insensitive name.
*/
private static Color getColorFromField(String name) {
try {
Field colorField = TrickColors.class.getField(name.toLowerCase());
return (Color) colorField.get(TrickColors.class);
}
catch (NoSuchFieldException exc) {
}
catch (SecurityException exc) {
}
catch (IllegalAccessException exc) {
}
catch (IllegalArgumentException exc) {
}
return null;
}
/**
* Returns a color with the specified case-insensitive name.
*/
public static String getName(Color color) {
return color2name.get(color);
}
/**
* Returns a color with the specified case-insensitive name.
*/
public static Color getColor(String name) {
return name2color.get(name.toLowerCase());
}
/**
* Returns a collection of all color names.
*/
public static Collection<String> colors() {
return name2color.keySet();
}
/** Transform a color string into a color object.
*
* @param s the color string
* @return the color object
*/
public static Color decodeColor(String s) {
if (s == null) {
return null;
}
Color c;
try {
c = Color.decode(s);
}
catch (NumberFormatException exc) {
c = TrickColors.getColor(s);
}
return c;
}
public static final Color aliceblue = new Color(0xf0f8ff);
public static final Color antiquewhite = new Color(0xfaebd7);
public static final Color aqua = new Color(0x00ffff);
public static final Color aquamarine = new Color(0x7fffd4);
public static final Color azure = new Color(0xf0ffff);
public static final Color beige = new Color(0xf5f5dc);
public static final Color bisque = new Color(0xffe4c4);
public static final Color black = new Color(0x000000);
public static final Color blanchedalmond = new Color(0xffebcd);
public static final Color blue = new Color(0x0000ff);
public static final Color blueviolet = new Color(0x8a2be2);
public static final Color brown = new Color(0xa52a2a);
public static final Color burlywood = new Color(0xdeb887);
public static final Color cadetblue = new Color(0x5f9ea0);
public static final Color chartreuse = new Color(0x7fff00);
public static final Color chocolate = new Color(0xd2691e);
public static final Color coral = new Color(0xff7f50);
public static final Color cornflowerblue = new Color(0x6495ed);
public static final Color cornsilk = new Color(0xfff8dc);
public static final Color crimson = new Color(0xdc143c);
public static final Color cyan = new Color(0x00ffff);
public static final Color darkblue = new Color(0x00008b);
public static final Color darkcyan = new Color(0x008b8b);
public static final Color darkgoldenrod = new Color(0xb8860b);
public static final Color darkgray = new Color(0xa9a9a9);
public static final Color darkgreen = new Color(0x006400);
public static final Color darkkhaki = new Color(0xbdb76b);
public static final Color darkmagenta = new Color(0x8b008b);
public static final Color darkolivegreen = new Color(0x556b2f);
public static final Color darkorange = new Color(0xff8c00);
public static final Color darkorchid = new Color(0x9932cc);
public static final Color darkred = new Color(0x8b0000);
public static final Color darksalmon = new Color(0xe9967a);
public static final Color darkseagreen = new Color(0x8fbc8f);
public static final Color darkslateblue = new Color(0x483d8b);
public static final Color darkslategray = new Color(0x2f4f4f);
public static final Color darkturquoise = new Color(0x00ced1);
public static final Color darkviolet = new Color(0x9400d3);
public static final Color deeppink = new Color(0xff1493);
public static final Color deepskyblue = new Color(0x00bfff);
public static final Color dimgray = new Color(0x696969);
public static final Color dodgerblue = new Color(0x1e90ff);
public static final Color firebrick = new Color(0xb22222);
public static final Color floralwhite = new Color(0xfffaf0);
public static final Color forestgreen = new Color(0x228b22);
public static final Color fuchsia = new Color(0xff00ff);
public static final Color gainsboro = new Color(0xdcdcdc);
public static final Color ghostwhite = new Color(0xf8f8ff);
public static final Color gold = new Color(0xffd700);
public static final Color goldenrod = new Color(0xdaa520);
public static final Color gray = new Color(0x808080);
public static final Color green = new Color(0x008000);
public static final Color greenyellow = new Color(0xadff2f);
public static final Color honeydew = new Color(0xf0fff0);
public static final Color hotpink = new Color(0xff69b4);
public static final Color indianred = new Color(0xcd5c5c);
public static final Color indigo = new Color(0x4b0082);
public static final Color ivory = new Color(0xfffff0);
public static final Color khaki = new Color(0xf0e68c);
public static final Color lavender = new Color(0xe6e6fa);
public static final Color lavenderblush = new Color(0xfff0f5);
public static final Color lawngreen = new Color(0x7cfc00);
public static final Color lemonchiffon = new Color(0xfffacd);
public static final Color lightblue = new Color(0xadd8e6);
public static final Color lightcoral = new Color(0xf08080);
public static final Color lightcyan = new Color(0xe0ffff);
public static final Color lightgoldenrodyellow = new Color(0xfafad2);
public static final Color lightgreen = new Color(0x90ee90);
public static final Color lightgrey = new Color(0xd3d3d3);
public static final Color lightpink = new Color(0xffb6c1);
public static final Color lightsalmon = new Color(0xffa07a);
public static final Color lightseagreen = new Color(0x20b2aa);
public static final Color lightskyblue = new Color(0x87cefa);
public static final Color lightslategray = new Color(0x778899);
public static final Color lightsteelblue = new Color(0xb0c4de);
public static final Color lightyellow = new Color(0xffffe0);
public static final Color lime = new Color(0x00ff00);
public static final Color limegreen = new Color(0x32cd32);
public static final Color linen = new Color(0xfaf0e6);
public static final Color magenta = new Color(0xff00ff);
public static final Color maroon = new Color(0x800000);
public static final Color mediumaquamarine = new Color(0x66cdaa);
public static final Color mediumblue = new Color(0x0000cd);
public static final Color mediumorchid = new Color(0xba55d3);
public static final Color mediumpurple = new Color(0x9370db);
public static final Color mediumseagreen = new Color(0x3cb371);
public static final Color mediumslateblue = new Color(0x7b68ee);
public static final Color mediumspringgreen = new Color(0x00fa9a);
public static final Color mediumturquoise = new Color(0x48d1cc);
public static final Color mediumvioletred = new Color(0xc71585);
public static final Color midnightblue = new Color(0x191970);
public static final Color mintcream = new Color(0xf5fffa);
public static final Color mistyrose = new Color(0xffe4e1);
public static final Color moccasin = new Color(0xffe4b5);
public static final Color navajowhite = new Color(0xffdead);
public static final Color navy = new Color(0x000080);
public static final Color oldlace = new Color(0xfdf5e6);
public static final Color olive = new Color(0x808000);
public static final Color olivedrab = new Color(0x6b8e23);
public static final Color orange = new Color(0xffa500);
public static final Color orangered = new Color(0xff4500);
public static final Color orchid = new Color(0xda70d6);
public static final Color palegoldenrod = new Color(0xeee8aa);
public static final Color palegreen = new Color(0x98fb98);
public static final Color paleturquoise = new Color(0xafeeee);
public static final Color palevioletred = new Color(0xdb7093);
public static final Color papayawhip = new Color(0xffefd5);
public static final Color peachpuff = new Color(0xffdab9);
public static final Color peru = new Color(0xcd853f);
public static final Color pink = new Color(0xffc0cb);
public static final Color plum = new Color(0xdda0dd);
public static final Color powderblue = new Color(0xb0e0e6);
public static final Color purple = new Color(0x800080);
public static final Color red = new Color(0xff0000);
public static final Color rosybrown = new Color(0xbc8f8f);
public static final Color royalblue = new Color(0x4169e1);
public static final Color saddlebrown = new Color(0x8b4513);
public static final Color salmon = new Color(0xfa8072);
public static final Color sandybrown = new Color(0xf4a460);
public static final Color seagreen = new Color(0x2e8b57);
public static final Color seashell = new Color(0xfff5ee);
public static final Color sienna = new Color(0xa0522d);
public static final Color silver = new Color(0xc0c0c0);
public static final Color skyblue = new Color(0x87ceeb);
public static final Color slateblue = new Color(0x6a5acd);
public static final Color slategray = new Color(0x708090);
public static final Color snow = new Color(0xfffafa);
public static final Color springgreen = new Color(0x00ff7f);
public static final Color steelblue = new Color(0x4682b4);
public static final Color tan = new Color(0xd2b48c);
public static final Color teal = new Color(0x008080);
public static final Color thistle = new Color(0xd8bfd8);
public static final Color tomato = new Color(0xff6347);
public static final Color turquoise = new Color(0x40e0d0);
public static final Color violet = new Color(0xee82ee);
public static final Color wheat = new Color(0xf5deb3);
public static final Color white = new Color(0xffffff);
public static final Color whitesmoke = new Color(0xf5f5f5);
public static final Color yellow = new Color(0xffff00);
public static final Color yellowgreen = new Color(0x9acd32);
static {
initColorsMap();
}
}

View File

@ -0,0 +1,228 @@
/*
* $Id: UnitInfixExpression.java 3288 2013-11-07 18:33:42Z hchen3 $
*
*/
//========================================
// Package
//========================================
package trick.common.utils;
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
public class UnitInfixExpression {
//========================================
// Public data
//========================================
public static final String OPERATORS="/*+-()123"; //ignore the "(" as an operator
public static final Map<Character, Integer> OPERATOR_LEVELS = new HashMap<Character, Integer>();
static {
OPERATOR_LEVELS.put(')', 0);
OPERATOR_LEVELS.put('1', 1);
OPERATOR_LEVELS.put('2', 1);
OPERATOR_LEVELS.put('3', 1);
OPERATOR_LEVELS.put('*', 2);
OPERATOR_LEVELS.put('/', 2);
OPERATOR_LEVELS.put('+', 3);
OPERATOR_LEVELS.put('-', 3);
OPERATOR_LEVELS.put('(', 4);
}
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
private String inputExpression = null;
//========================================
// Constructors
//========================================
public UnitInfixExpression(String expression) {
inputExpression = expression;
}
//========================================
// Methods
//========================================
/**
* Returns a derived unit based on for the unit expression.
*/
public UnitType.Unit getUnit() {
UnitType.Unit ret = null;
Stack<UnitType.Unit> unitStack = new Stack<UnitType.Unit>();
Stack<Character> operationStack = new Stack<Character>();
StringBuffer unitBuf = new StringBuffer();
for (int i = 0; i < inputExpression.length(); i++ ) {
char eachChar = inputExpression.charAt(i);
if (eachChar==' '){
//ignore
}
else if (isValidOperator(eachChar)){
if (!isLeftParen(eachChar) && unitBuf.length() > 0) {
unitStack.push(UnitType.getPrimitiveUnit(unitBuf.toString()));
unitBuf.setLength(0);
}
if (operationStack.isEmpty() || isLeftParen(eachChar)){ //first item or left parenthesis
operationStack.push(eachChar);
}
// if right parenthesis, evaluating the expression within the parenthesizes
else if (isRightParen(eachChar)){
evaluateUntilLeftParenthesis(unitStack, operationStack);
}
//if the current operator has higher level than the first item in the stack, insert it
else if (getHigherPrecedenceOperator(eachChar, operationStack.peek()) == eachChar){
operationStack.push(eachChar);
}
//if the current operator has lower level, then the previous higher level of operation needs evaluating
else{
evaluateAndPushDerivedUnit(unitStack, operationStack);
//after evaluation of the higher pair, insert current operator
operationStack.push(eachChar);
}
} else if (Character.isLetter(eachChar) || eachChar == '.' || eachChar == '-') { // if the character is a letter, appends to the unit string buffer
unitBuf.append(eachChar);
if ( i == inputExpression.length()-1){
unitStack.push(UnitType.getPrimitiveUnit(unitBuf.toString())) ; //the last element
}
}
}
//System.out.println("After all Unit Stack : "+unitStack);
//System.out.println("After all Operation Stack : "+operationStack);
while (!operationStack.empty()){
evaluateAndPushDerivedUnit(unitStack, operationStack);
}
if (unitStack != null && unitStack.size() > 0) {
return unitStack.pop();
}
return ret;
}
/**
* Helper method to check if the specified character is a right parenthesis.
*/
private boolean isRightParen(Character operator) {
return operator == ')' ? true : false;
}
/**
* Helper method to check if the specified character is a left parenthesis.
*/
private boolean isLeftParen(Character operator) {
return operator == '(' ? true : false;
}
/**
* Helper method for evaluating units and pushing the intermediate unit to the unit stack.
*/
private void evaluateAndPushDerivedUnit(Stack<UnitType.Unit> unitStack, Stack<Character> operationStack) {
UnitType.Unit unit1 = null;
UnitType.Unit unit2 = null;
String derivedUnitName = "";
UnitType.Unit derivedUnit = null;
Character operator = operationStack.pop();
switch (operator) {
case '2':
case '3':
unit1 = unitStack.pop();
derivedUnitName = unit1.abbreviation + operator;
derivedUnit = new UnitType.Unit(derivedUnitName, derivedUnitName, false);
derivedUnit.factor1 = unit1.factor1;
if (operator == '2') {
derivedUnit.factor1 = unit1.factor1 * unit1.factor1;
derivedUnit.factor2 = unit1.factor2 * unit1.factor2;
} else {
derivedUnit.factor1 = unit1.factor1 * unit1.factor1 * unit1.factor1;
derivedUnit.factor2 = unit1.factor2 * unit1.factor2 * unit1.factor2;
}
break;
case '*':
case '/':
unit2 = unitStack.pop();
unit1 = unitStack.pop();
derivedUnitName = unit1.abbreviation + operator + unit2.abbreviation;
derivedUnit = new UnitType.Unit(derivedUnitName, derivedUnitName, false);
if (operator == '*' ) {
derivedUnit.factor1 = unit1.factor1 * unit2.factor1;
derivedUnit.factor2 = unit1.factor2 * unit2.factor2;
} else {
if (unit2.factor1 == 0.0) {
derivedUnit.factor1 = unit1.factor1;
} else {
derivedUnit.factor1 = unit1.factor1 / unit2.factor1;
}
if (unit2.factor2 == 0.0) {
derivedUnit.factor2 = unit1.factor2;
} else {
derivedUnit.factor2 = unit1.factor2 / unit2.factor2;
}
}
break;
}
if (derivedUnit != null) {
unitStack.push(derivedUnit);
//System.out.println("derived unit " + derivedUnit.abbreviation + " factor1=" + derivedUnit.factor1 + "; factor2="+derivedUnit.factor2);
}
}
/**
* Helper method for evaluating the expression until a left parenthesis.
*/
private void evaluateUntilLeftParenthesis(Stack<UnitType.Unit> unitStack, Stack<Character> operationStack) {
while (!operationStack.empty()){
if (isLeftParen(operationStack.peek())){ //if the left parenthesis has been reached, then pop it up and exit
operationStack.pop();
break;
}
evaluateAndPushDerivedUnit(unitStack,operationStack);
}
}
/**
* Helper method to check if the specified character is a valid operator.
*/
private boolean isValidOperator(char input) {
if (OPERATORS.indexOf(input) != -1) {
return true;
}
return false;
}
/**
* Helper method for getting a higher level operator based on the predefined operator levels.
*/
private Character getHigherPrecedenceOperator(Character firstOperator, Character secondOperator){
return OPERATOR_LEVELS.get(firstOperator)<OPERATOR_LEVELS.get(secondOperator) ? firstOperator : secondOperator;
}
}

View File

@ -0,0 +1,395 @@
/*
* $Id$
*
*/
//========================================
// Package
//========================================
package trick.common.utils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* enumerates the available categories of units. Each catagory contains the
* specific units appropriate to its measure.
*
* @author Derek Bankieris
*/
public enum UnitType {
Angle(new ArrayList<Unit>() {{
add(new Unit("radians", "r", false, 0.0, 1.0));
add(new Unit("pico-radians", "pr", false, 0.0, 1.0 * PICO));
add(new Unit("nano-radians", "nr", false, 0.0, 1.0 * NANO));
add(new Unit("micro-radians", "ur", false, 0.0, 1.0 * MICRO));
add(new Unit("milli-radians", "mr", false, 0.0, 1.0 * MILLI));
add(new Unit("centi-radians", "cr", false, 0.0, 1.0 * CENTI));
add(new Unit("deci-radians", "dr", false, 0.0, 1.0 * DECI));
add(new Unit("degrees", "d", false, 0.0, 0.0174532925199433));
add(new Unit("arc-seconds", "as", false, 0.0, 4.848136811095362e-06));
add(new Unit("arc-minutes", "am", false, 0.0, 0.000290888208666));
add(new Unit("revolutions", "rev", false, 0.0, 6.28318530717958647));
}}),
Current(new ArrayList<Unit>() {{
add(new Unit("amperes", "amp", true, 0.0, 1.0));
}}),
Distance(new ArrayList<Unit>() {{
add(new Unit("meters", "m", true, 0.0, 1.0));
add(new Unit("inches", "in", false, 0.0, 0.0254));
add(new Unit("feet", "ft", false, 0.0, 0.3048));
add(new Unit("kilo-feet", "kft", false, 0.0, 0.3048 * KILO));
add(new Unit("yards", "yd", false, 0.0, 0.9144));
add(new Unit("miles", "mi", false, 0.0, 1609.344));
add(new Unit("nautical-miles", "n.m.", false, 0.0, 1852.0));
}}),
Energy(new ArrayList<Unit>() {{
add(new Unit("joules", "J", true, 0.0, 1.0));
add(new Unit("british-thermal-units", "BTU", false, 0.0, 1055.056));
add(new Unit("tons-tnt", "TNT", false, 0.0, 4.184 * GIGA));
}}),
Force(new ArrayList<Unit>() {{
add(new Unit("newtons", "N", true, 0.0, 1.0));
add(new Unit("ounces", "oz", false, 0.0, 0.27801385));
add(new Unit("pounds-force", "lbf", false, 0.0, 4.4482216152605));
}}),
Frequency(new ArrayList<Unit>() {{
add(new Unit("hertz", "Hz", true, 0.0, 1.0));
}}),
Gain(new ArrayList<Unit>() {{
add(new Unit("decibels", "dB", false, 0.0, 1.0));
}}),
Mass(new ArrayList<Unit>() {{
add(new Unit("grams", "g", true, 0.0, MILLI));
add(new Unit("metric-tons", "mt", false, 0.0, 1000.0));
add(new Unit("slugs", "sl", false, 0.0, 14.5939029372064));
add(new Unit("pounds-mass", "lbm", false, 0.0, 0.4535923697760192));
}}),
Power(new ArrayList<Unit>() {{
add(new Unit("watts", "W", true, 0.0, 1.0));
add(new Unit("horse-power", "hp", false, 0.0, 745.69987));
}}),
Pressure(new ArrayList<Unit>() {{
add(new Unit("atmospheres", "atm", false, 0.0, 101325.00000));
add(new Unit("pascals", "Pa", true, 0.0, 1.0));
add(new Unit("milli-meters-mercury", "mmHg", false, 0.0, MILLI*133322.387415));
add(new Unit("inches-mercury", "inHg", false, 0.0, 3386.389));
add(new Unit("milli-meters-water", "mmWater", false, 0.0, MILLI*9806.65));
add(new Unit("inches-water", "inWater", false, 0.0, 249.08891));
}}),
Resistance(new ArrayList<Unit>() {{
add(new Unit("ohms", "ohm", true, 0.0, 1.0));
}}),
Temperature(new ArrayList<Unit>() {{
add(new Unit("degrees-Celsius", "C", false, 0.0, 1.0));
add(new Unit("degrees-Kelvin", "K", false, -273.15, 1.0));
add(new Unit("degrees-Fahrenheit", "F", false, -17.777777777777778, 0.55555555555555556));
add(new Unit("degrees-Rankine", "R", false, -273.15, 0.55555555555555556));
}}),
Time(new ArrayList<Unit>() {{
add(new Unit("seconds", "s", true, 0.0, 1.0));
add(new Unit("minutes", "min", false, 0.0, 60.0));
add(new Unit("hours", "hr", false, 0.0, 3600.0));
add(new Unit("days", "day", false, 0.0, 86400.0));
}}),
Unitless(new ArrayList<Unit>() {{
add(new Unit("unitless", "--", false, 0.0, 1.0));
add(new Unit("count", "cnt", false, 0.0, 1.0));
add(new Unit("one", "one", false, 0.0, 1.0));
add(new Unit("moles", "mol", false, 0.0, 6.02214179e+23));
}}),
Voltage(new ArrayList<Unit>() {{
add(new Unit("volts", "v", true, 0.0, 1.0));
}}),
Volume(new ArrayList<Unit>() {{
add(new Unit("liters", "l", true, 0.0, 1.0));
add(new Unit("gallons", "gal", false, 0.0, 3.785412));
add(new Unit("fluid-ounces", "floz", false, 0.0, 0.02957353));
}});
public static final double PICO = 1e-12;
public static final double NANO = 1e-09;
public static final double MICRO = 1e-06;
public static final double MILLI = 1e-03;
public static final double CENTI = 1e-02;
public static final double DECI = 1e-01;
public static final double DECA = 1e+01;
public static final double HECTO = 1e+2;
public static final double KILO = 1e+3;
public static final double MEGA = 1e+6;
public static final double GIGA = 1e+9;
public static final double TERA = 1e+12;
/** SI unit prefixes */
private final Unit[] prefixes = {
new Unit("pico-", "p", false, 0.0, PICO),
new Unit("nana-", "n", false, 0.0, NANO),
new Unit("micro-", "u", false, 0.0, MICRO),
new Unit("milli-", "m", false, 0.0, MILLI),
new Unit("centi-", "c", false, 0.0, CENTI),
new Unit("deci-", "d", false, 0.0, DECI),
new Unit("deca-", "da", false, 0.0, DECA),
new Unit("hecto-", "h", false, 0.0, HECTO),
new Unit("kilo-", "k", false, 0.0, KILO),
new Unit("mega-", "M", false, 0.0, MEGA),
new Unit("giga-", "G", false, 0.0, GIGA),
new Unit("tera-", "T", false, 0.0, TERA)
};
public static final String OPERATORS="+-/*()^"; //ignore the "(" as an operator
public static final Map<Character, Integer> OPERATOR_LEVELS = new HashMap<Character, Integer>();
static {
OPERATOR_LEVELS.put(')', 0);
OPERATOR_LEVELS.put('^', 1);
OPERATOR_LEVELS.put('*', 2);
OPERATOR_LEVELS.put('/', 2);
OPERATOR_LEVELS.put('+', 3);
OPERATOR_LEVELS.put('-', 3);
OPERATOR_LEVELS.put('(', 4);
}
/** valid units for this type */
private final ArrayList<Unit> units;
/**
* constructs the type and adds prefixes to units that accept SI prefixes
*
* @param units the units appropriate to this type
*/
private UnitType(ArrayList<Unit> units) {
this.units = units;
ListIterator<Unit> iterator = units.listIterator();
while (iterator.hasNext()) {
Unit unit = iterator.next();
if (unit.isPrefixable) {
for (Unit prefix : prefixes) {
iterator.add(new Unit(prefix.name + unit.name,
prefix.abbreviation + unit.abbreviation, false, unit.factor1, prefix.factor2 * unit.factor2));
}
}
}
}
/**
* gets all units appropriate for this <code>UnitType</code>
*
* @return the units available for this type
*/
public List<Unit> getAll() {
return Collections.unmodifiableList(units);
}
/**
* Converts the value of a specified units to the preferred units.
*
* @param fromValue
* @param fromUnitStr
* @param toUnitStr
* @return new value based on the new units
* @throws IllegalUnitConversionException
*/
public static double convertUnits(double fromValue, String fromUnitStr, String toUnitStr) throws IllegalUnitConversionException {
Unit fromUnit = getExpressionUnit(fromUnitStr);
Unit toUnit = getExpressionUnit(toUnitStr);
if (!isConvertible(fromUnitStr, toUnitStr)) {
throw new IllegalUnitConversionException(fromUnitStr, toUnitStr);
}
double derivedFactor1 = fromUnit.factor1 - toUnit.factor1 / toUnit.factor2;
double derivedFactor2 = fromUnit.factor2 / toUnit.factor2;
return (fromValue * derivedFactor2 + derivedFactor1);
}
/**
* gets the <code>UnitType</code> of which <code>abbreviation</code> is a
* member. This method handles only simple units, not compound units
* resulting from multiplication, division, or exponentiation.
*
* @return the corresponding type, or null if none exists
*/
public static UnitType getType(String abbreviation) {
for (UnitType type : UnitType.values()) {
for (Unit unit : type.getAll()) {
if (unit.abbreviation.equals(abbreviation)) {
return type;
}
}
}
return null;
}
/**
* Returns the primitive unit if it is a primitive units,
* otherwise return a complex units that is made out of primitive units.
*
* @param expression
* @return an instance of {@link Unit}
*/
public static Unit getExpressionUnit(String expression) {
Unit ret = null;
ret = getPrimitiveUnit(expression);
if (ret != null) {
return ret;
}
UnitInfixExpression unitExpression = new UnitInfixExpression(expression);
ret = unitExpression.getUnit();
return ret;
}
/**
* Gets the {@link Unit} based on its abbreviation.
*
* @param abbreviation the units abbreviation.
* @return the corresponding Unit, or null if the abbreviation doesn't exist.
*/
public static Unit getPrimitiveUnit(String abbreviation) {
Unit ret = null;
for (UnitType type : UnitType.values()) {
for (Unit unit : type.getAll()) {
if (unit.abbreviation.equals(abbreviation)) {
ret = unit;
}
}
}
return ret;
}
/**
* gets all valid unit alternatives for <code>expression</code>.
* This method handles compound units resulting from multiplication,
* division, or exponentiation.
*/
public static List<String> getAll(String expression) {
ArrayList<String> results = new ArrayList<String>();
Matcher matcher = Pattern.compile("([^\\d\\*/]+)(\\d*)").matcher(expression);
if (matcher.find()) {
UnitType type = UnitType.getType(matcher.group(1));
if (type != null) {
for (Unit unit : type.getAll()) {
getAll(unit + matcher.group(2), expression.substring(matcher.end()), results);
}
}
}
return results;
}
/**
* gets all valid unit alternatives for <code>tail</code>, concatenating
* each result to <code>head<code>, and appending each concatenation to
* <code>results</code>. This method handles compound units resulting
* from multiplication, division, or exponentiation.
*
* @param head the (already processed) head of the units expression
* @param tail the (not yet processed) tai of the units expression
* @param results the list to which to append results
*/
private static void getAll(String head, String tail, List<String> results) {
Matcher matcher = Pattern.compile("(\\*|/)([^\\d\\*/]+)(\\d*)").matcher(tail);
if (matcher.find()) {
UnitType type = UnitType.getType(matcher.group(2));
if (type != null) {
for (Unit unit : type.getAll()) {
getAll(head + matcher.group(1) + unit + matcher.group(3), tail.substring(matcher.end()), results);
}
}
}
else {
results.add(head);
}
}
/**
* Determines if <code>fromUnits</code> can legally be converted to
* </code>toUnits</code>. This method handles compound units resulting
* from multiplication, division, or exponentiation.
*
* @param fromUnits the unit expression from which to convert
* @param toUnits the unit expression to which to convert
*
* @return whether or not such a conversion is valid
*/
public static boolean isConvertible(String fromUnits, String toUnits) {
return getAll(fromUnits).contains(toUnits);
}
/**
* represents a unit
*/
public static class Unit {
/** represents default units */
public static final Unit DEFAULT_UNITS = new Unit("default", "xx", false);
/** the full name */
public final String name;
/** the abbreviation to use following a value */
public final String abbreviation;
public double factor1;
public double factor2;
/** whether or not metric prefixes are valid */
final boolean isPrefixable;
public Unit(String name, String abbreviation, boolean isPrefixable, double factor1, double factor2) {
this(name, abbreviation, isPrefixable);
this.factor1 = factor1;
this.factor2 = factor2;
}
/** constructor */
public Unit(String name, String abbreviation, boolean isPrefixable) {
this.name = name;
this.abbreviation = abbreviation;
this.isPrefixable = isPrefixable;
}
@Override
public String toString() {
return abbreviation;
}
}
/**
* Exception for handling illegal unit conversion.
*/
public static class IllegalUnitConversionException extends Exception {
private static final long serialVersionUID = 2800176399857985431L;
public IllegalUnitConversionException(String fromUnit, String toUnit) {
super("Illegal Unit Conversion", new Throwable("Can't convert " + fromUnit + " -> " + toUnit));
}
}
}

View File

@ -0,0 +1,449 @@
/*
* $Id: VariableServerConnection.java 3760 2014-12-04 17:23:32Z dbankier $
*/
package trick.common.utils;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* a generic variable server client that provides for sending commands and
* receiving responses. Currently only handles a subset of Trick types in binary
* mode.
*
* @author Derek Bankieris
*/
public class VariableServerConnection {
/** maximum binary packet size sent by the Variable Server */
public static final int maximumPacketSize = 8192;
/** Variable Server data mode */
public enum DataMode {ASCII, BINARY, BINARY_NO_NAMES};
/** This really shouldn't be necessary. MTV needs to retrieve Variable Server data better. */
public String results;
/** connection to the Variable Server */
protected Socket socket;
/** Variable Server data mode */
protected DataMode dataMode = DataMode.ASCII;
/** Variable Server synchronized mode */
protected boolean sync = false;
/** tracks the paused status of the Variable Server */
protected boolean isPaused = false;
/** receives commands from the Variable Server */
protected BufferedReader inputStream;
/** sends commands to the Variable Server */
protected DataOutputStream outputStream;
/**
* attempts to connect to the Variable Server on the given host and port
*
* @param host Variable Server machine name
* @param port Variable Server port number
*/
public VariableServerConnection(String host, int port) throws UnknownHostException, IOException, SecurityException {
socket = new Socket(host, port);
inputStream = new BufferedReader(new InputStreamReader(socket.getInputStream()));
outputStream = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
}
/**
* sends the given command and any commands in the output stream's buffer
* to the Variable Server. The command is written to the output stream,
* and the buffer is flushed. A newline is automatically appended to the
* given command.
*
* @param command the Variable Server command to be sent
*/
public void put(String command) throws IOException {
outputStream.writeBytes(command + "\n");
outputStream.flush();
}
/**
* writes the command to the output stream. A newline is
* automatically appended. The buffer is not flushed.
*
* @param command the Variable Server command to be written
*/
public void write(String command) throws IOException {
outputStream.writeBytes(command + "\n");
}
/**
* flushes the buffer, sending any pending commands to the Variable
* Server
*/
public void flush() throws IOException {
outputStream.flush();
}
/**
* commands the Variable Server to send variable data in ASCII
*/
public void setAscii() throws IOException {
if (dataMode != DataMode.ASCII) {
put("trick.var_ascii()");
dataMode = DataMode.ASCII;
}
}
/**
* commands the Variable Server to send variable data in binary
*/
public void setBinary() throws IOException {
if (dataMode != DataMode.BINARY) {
put("trick.var_binary()");
dataMode = DataMode.BINARY;
}
}
/**
* commands the Variable Server to send variable data in binary and to
* omit names
*/
public void setBinaryNoNames() throws IOException {
if (dataMode != DataMode.BINARY_NO_NAMES) {
put("trick.var_binary_nonames()");
dataMode = DataMode.BINARY_NO_NAMES;
}
}
/**
* sets the Variable Server to synchronized mode
*/
public void setSync() throws IOException {
if (!sync) {
put("trick.var_sync(1)");
sync = true;
}
}
/**
* commands the Variable Server to stop sending data
*/
public void pause() throws IOException {
put("trick.var_pause()");
isPaused = true;
}
/**
* commands the Variable Server to resume sending data
*/
public void unpause() throws IOException {
put("trick.var_unpause()");
isPaused = false;
}
/**
* returns the paused state of the Variable Server
*
* return whether or not the Variable Server is paused
*/
public boolean isPaused() {
return isPaused;
}
/**
* adds the named variable to the Variable Server
*
* @param name the name of the variable to be added
*/
public void add(String name) throws IOException {
put("trick.var_add(\"" + name + "\")");
}
/**
* adds the named variable to the Variable Server
*
* @param name the name of the variable to be added
* @param units the units to use
*/
public void add(String name, String units) throws IOException {
boolean invalidUnits = units == null || units.isEmpty();
put("trick.var_add(\"" + name + (invalidUnits ? "" : "\", \"" + units) + "\")");
}
/**
* removes the named variable from the Variable Server
*
* @param name the name of the variable to be removeed
*/
public void remove(String name) throws IOException {
put("trick.var_remove(\"" + name + "\")");
}
/**
* clears all variables from the Variable Server
*/
public void clear() throws IOException {
put("trick.var_clear()");
}
/**
* sets the period at which the Variable Server sends updates
*
* @param period the update period
*/
public void setCycle(double period) throws IOException {
put("trick.var_cycle(" + period + ")");
}
/**
* requests a single update from the Variable Server
*/
public void poll() throws IOException {
put("trick.var_send()");
}
/**
* attempts to resolve all invalid variables
*/
public void resolveInvalidReferences() throws IOException {
put("trick.var_retry_bad_ref()");
}
/**
* sends a freeze command to the simulation
*/
public void freeze() throws IOException {
put("trick.exec_freeze()");
}
/**
* sends a run command to the simulation
*/
public void run() throws IOException {
put("trick.exec_run()");
}
/**
* sends an enable or disable real time command to the simulation
*/
public void setRealTimeEnabled(boolean enabled) throws IOException {
put("trick.real_time_" + (enabled ? "enable" : "disable") + "()");
}
/**
* sets the Variable Server's debug level
*
* @param level the debug level
*/
public void setDebugLevel(int level) throws IOException {
put("trick.var_debug(" + level + ")");
}
/**
* sets this client's tag
*
* @param tag the tag that the Variable Server will associate with this client
*/
public void setClientTag(String tag) throws IOException {
put("trick.var_set_client_tag(\"" + tag + "\")");
}
// in binary mode, must convert C types (little endian) to java types (big endian)
// return a java long (64bits) for bytes in buffer starting at i, size = 4 or 8
/**
* converts incoming binary data from little to big endian
*/
private long convertBinaryData(byte[] buffer, int index, int size) {
long byte1, byte2, byte3, byte4, byte5, byte6, byte7, byte8;
// int is size 4, longlong and double are size 8
byte1 = (0xFF & ((int)buffer[index]));
byte2 = (0xFF & ((int)buffer[index+1]));
byte3 = (0xFF & ((int)buffer[index+2]));
byte4 = (0xFF & ((int)buffer[index+3]));
if (size==8) {
byte5 = (0xFF & ((int)buffer[index+4]));
byte6 = (0xFF & ((int)buffer[index+5]));
byte7 = (0xFF & ((int)buffer[index+6]));
byte8 = (0xFF & ((int)buffer[index+7]));
// little -> big endian
return (long) (byte8<<56 | byte7<<48 | byte6<<40 | byte5<<32 | byte4<<24 | byte3<<16 |
byte2<<8 | byte1);
} else {
// little -> big endian
return (long) (byte4<<24 | byte3<<16 | byte2<<8 | byte1);
}
}
/**
* Reads characters into a portion of an array. This method will block until some input is available,
* an I/O error occurs, or the end of the stream is reached.
*
* @param buffer destination buffer
* @param index index within the buffer at which to start storing characters
* @param maxCount maximum numbers of characters to read
*
* @return the number of characters read, or -1 if the end of the stream is reached
*/
public int read(char[] buffer, int index, int maxCount) throws IOException {
return inputStream.read(buffer, index, maxCount);
}
/**
* reads a line of data from the Variable Server. Values are tab-delimited.
*
* @return a tab-delimited line of data
*/
public String get() throws IOException {
return get(1);
}
/**
* reads the specified number of variables from the Variable Server. This
* supports multiple binary packets.
*
* @return the tab-delimited data
*/
public String get(int num_variables) throws IOException {
// num_variables (optional) is number of variables you expect to get (needed for binary multiple packet support)
int bytes_read, index, msg_size, len, type, size;
int num_vars_processed, num_vars_in_msg;
int ival;
double dval;
String name, typename, val;
byte[] buffer = new byte[maximumPacketSize];
String vals[] = new String[1000];
int packet_count = 0;
if (dataMode == DataMode.ASCII) {
results = inputStream.readLine();
} else { // binary
// handle multiple packets (continue reading if more variables and not eof of socket)
num_vars_processed = 0;
bytes_read = 0;
results = "";
while ((num_vars_processed < num_variables) && (bytes_read != -1)) {
vals[packet_count] = "";
// read binary header
bytes_read = socket.getInputStream().read(buffer, 0, 12);
if (bytes_read == -1) { // eof
throw new IOException("Connection closed");
}
if ((int)buffer[0]==3) { // message indicator for send_event_data
// simply a message header where msg_size=0 and num_vars_in_msg = number of event variables
results += (int)convertBinaryData(buffer, 8, 4);
return results;
} else if ((int)buffer[0] != 0) {
System.out.println("VarClient: Bad binary message indicator : " +(int)buffer[0]+ ".");
return "";
}
msg_size = (int)convertBinaryData(buffer, 4, 4);
//System.out.println("msg size=" + msg_size);
num_vars_in_msg = (int)convertBinaryData(buffer, 8, 4);
//System.out.println("numvars=" + num_vars_in_msg);
if (num_variables==1) {
// if user did not specify num_variables, get all vars in this message
num_variables = num_vars_in_msg;
}
// read binary data
bytes_read = socket.getInputStream().read(buffer, 0, msg_size-8);
//System.out.println("bytes_read=" + bytes_read);
index = 0;
while (index < bytes_read) {
if (num_vars_processed > 0) {
vals[packet_count] += "\t";
}
if (dataMode != DataMode.BINARY_NO_NAMES) {
len = (int)convertBinaryData(buffer, index, 4);
index += 4;
name = new String(buffer, index, len);
index += len;
}
type = (int)convertBinaryData(buffer, index, 4);
index += 4;
size = (int)convertBinaryData(buffer, index, 4);
// Trick10 type of char* is CHAR, change it to CHARSTRING
if ((type == 1) && (size > 1)) {
type = 3 ;
}
//System.out.println("type=" + type + " size=" +size);
index += 4;
switch (type) {
case 1 : // CHAR
case 17 : // BOOLEAN
//typename = "CHAR";
ival = (char)buffer[index];
vals[packet_count] += ival;
break;
case 3 : // CHARSTRING
//typename = "CHARSTRING";
vals[packet_count] += new String(buffer, index, size-1); // do not include null terminator
break;
case 6 : // INT
case 7 : // UNSIGNED INT
case 21 : // ENUMERATED
//typename = "INT";
ival = (int)convertBinaryData(buffer, index, 4);
vals[packet_count] += ival;
break;
case 11 : // DOUBLE
//typename = "DOUBLE";
dval = Double.longBitsToDouble(convertBinaryData(buffer, index, 8));
vals[packet_count] += dval;
break;
case 14 : // LONGLONG
//typename = "LONGLONG";
dval = (double)convertBinaryData(buffer, index, 8);
vals[packet_count] += dval;
break;
default :
//typename = "???";
System.out.println("VarClient: Unknown type " +type+ " in get().");
break;
}
index += size;
num_vars_processed++;
} // while message data being parsed
results += vals[packet_count];
packet_count++;
//System.out.println("pkt " +packet_count+ " : numvars_processed= "+num_vars_processed + " / " +num_variables);
} // end while num_vars_processed < num_variables
} // end binary
return results;
}
/**
* flushes any data that is still on the input stream
*/
public void flushInput() throws IOException {
byte[] buffer = new byte[maximumPacketSize];
int numAvailableBytes = socket.getInputStream().available();
if (numAvailableBytes > 0) {
int numBytesRead = socket.getInputStream().read(buffer, 0, numAvailableBytes);
System.out.println("Flushed " + numBytesRead + " of " + numAvailableBytes +
" available bytes.");
}
}
/**
* closes the connection to the Variable Server
*/
public void close() throws IOException {
try {
put("trick.var_exit()");
}
finally {
socket.close();
}
}
}

View File

@ -0,0 +1,237 @@
/*
* $Id: XMLCreator.java 3375 2014-01-08 19:37:28Z hchen3 $
*
*/
//========================================
// Package
//========================================
package trick.common.utils;
//========================================
// Imports
//========================================
import java.io.FileOutputStream;
import java.io.IOException;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
/**
* This XML creator using Java API for XML Processing.
*
*
* @since Trick 10
*/
public abstract class XMLCreator {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
protected Document dom;
protected Object rootObj;
//========================================
// Private Data
//========================================
private String xmlFile;
private String dtdFile;
private String publicID;
private JFrame callerMainFrame;
//========================================
// Constructors
//========================================
public XMLCreator(){
createDocument();
}
//========================================
// Set/Get methods
//========================================
/**
* Sets the XML file for parsing.
*
* @param xmlFile The XML file name.
*/
public void setXMLFile(String xmlFile) {
this.xmlFile = xmlFile;
}
/**
* Sets the root object of the XML.
*
* @param obj The root object.
*/
public void setRoot(Object obj) {
rootObj = obj;
}
/**
* Sets the DTD file for the XML.
*
* @param dtdFile The DTD file name for the XML.
*/
public void setDTDFile(String dtdFile){
this.dtdFile = dtdFile;
}
/**
* Sets the DTD public identifier.
*
* @param publicID The public identifier for the XML file.
*/
public void setPublicID(String publicID) {
this.publicID = publicID;
}
/**
* Sets the frame that calls the XMLCreator to generate XML file.
*/
public void setCallerFrame(JFrame frame) {
callerMainFrame = frame;
}
//========================================
// Methods
//========================================
/**
* Runs the XML creator to generate the XML file.
*
* @return True if the file is generated successfully, false otherwise.
*/
public boolean runCreator() {
if (createDOMTree()) {
printToFile();
return true;
} else {
if (callerMainFrame != null) {
JOptionPane.showMessageDialog(callerMainFrame,
xmlFile + " could not be saved \n" + "because it doesn not have any plottable plot(s) or table(s) defined !",
"File Not Created",
JOptionPane.WARNING_MESSAGE);
} else {
System.out.println(xmlFile + " could not be saved because it doesn not have any plottable plot(s) or table(s) defined !");
}
return false;
}
}
/**
* Using JAXP in implementation independent manner create a document object
* using which we create a xml tree in memory.
*/
private void createDocument() {
//get an instance of factory
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
//get an instance of builder
DocumentBuilder db = dbf.newDocumentBuilder();
//create an instance of DOM
dom = db.newDocument();
} catch(ParserConfigurationException pce) {
System.out.println("Error while trying to instantiate DocumentBuilder " + pce);
System.exit(1);
}
}
/**
* Creates a child {@link Element} of the specified parent {@link Element}.
*
* @param parentElem The parent element which needs creating a child element for.
* @param tagName The tag name of the child element.
* @param tagText The text for the child element.
*
* @return A newly created element.
*/
protected Element createChildElement(Element parentElem, String tagName, String tagText) {
if (tagText == null || "".equals(tagText.trim())) {
return null;
}
Element childElem = dom.createElement(tagName);
Text childText = dom.createTextNode(tagText);
childElem.appendChild(childText);
if (parentElem != null) {
parentElem.appendChild(childElem);
}
return childElem;
}
/**
* Creates a child {@link Element} of the specified parent {@link Element}.
*
* @param parentElem The parent element which needs creating a child element for.
* @param tagName The tag name of the child element.
* @param tagObject The object for the child element.
*
* @return A newly created element.
*/
protected Element createChildElement(Element parentElem, String tagName, Object tagObject) {
if (tagObject == null) {
return null;
}
return createChildElement(parentElem, tagName, tagObject.toString());
}
/**
* This shall create the desired XML structure.
*/
protected abstract boolean createDOMTree();
/**
* Helper method which uses Java API for XML Processing
* to print the XML document to file.
*/
private void printToFile(){
try
{
Transformer tr = TransformerFactory.newInstance().newTransformer();
tr.setOutputProperty(OutputKeys.INDENT, "yes");
tr.setOutputProperty(OutputKeys.METHOD,"xml");
tr.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4");
tr.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");
tr.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, publicID);
tr.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, dtdFile);
//to send the output to a file
tr.transform( new DOMSource(dom),new StreamResult(new FileOutputStream(xmlFile)));
//to send the output to console
//tr.transform( new DOMSource(dom),new StreamResult(System.out));
} catch(IOException ie) {
ie.printStackTrace();
} catch (TransformerException te) {
}
}
}

View File

@ -0,0 +1,37 @@
package trick.common.utils.vs;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class VSBoolean extends VSValue {
private static final long serialVersionUID = 3720173025885361193L;
public boolean value;
public VSBoolean() {}
public VSBoolean(boolean value) {
this.value = value;
}
public boolean getValue() {
return value;
}
@Override
public void fromVariableServer(String string) {
value = Integer.parseInt(string.trim()) != 0;
}
@Override
public String toVariableServer() {
return value ? "1" : "0";
}
@Override
public String toString() {
return Boolean.toString(value);
}
}

View File

@ -0,0 +1,39 @@
package trick.common.utils.vs;
import java.math.BigInteger;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class VSByte extends VSValue {
private static final long serialVersionUID = 8405472938103497097L;
public byte value;
public VSByte() {}
public VSByte(byte value) {
this.value = value;
}
public byte getValue() {
return value;
}
@Override
public void fromVariableServer(String string) {
value = new BigInteger(string.trim(), 10).byteValue();
}
@Override
public String toVariableServer() {
return Byte.toString(value);
}
@Override
public String toString() {
return Byte.toString(value);
}
}

View File

@ -0,0 +1,37 @@
package trick.common.utils.vs;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class VSDouble extends VSValue {
private static final long serialVersionUID = -2895628958106970334L;
public double value;
public VSDouble() {}
public VSDouble(double value) {
this.value = value;
}
public double getValue() {
return value;
}
@Override
public void fromVariableServer(String string) {
value = Double.parseDouble(string.trim());
}
@Override
public String toVariableServer() {
return Double.toString(value);
}
@Override
public String toString() {
return Double.toString(value);
}
}

View File

@ -0,0 +1,37 @@
package trick.common.utils.vs;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class VSFloat extends VSValue {
private static final long serialVersionUID = -4629816234119061148L;
public float value;
public VSFloat() {}
public VSFloat(float value) {
this.value = value;
}
public float getValue() {
return value;
}
@Override
public void fromVariableServer(String string) {
value = Float.parseFloat(string.trim());
}
@Override
public String toVariableServer() {
return Float.toString(value);
}
@Override
public String toString() {
return Float.toString(value);
}
}

View File

@ -0,0 +1,39 @@
package trick.common.utils.vs;
import java.math.BigInteger;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class VSInteger extends VSValue {
private static final long serialVersionUID = 1314788741378939173L;
public int value;
public VSInteger() {}
public VSInteger(int value) {
this.value = value;
}
public int getValue() {
return value;
}
@Override
public void fromVariableServer(String string) {
value = new BigInteger(string.trim(), 10).intValue();
}
@Override
public String toVariableServer() {
return Integer.toString(value);
}
@Override
public String toString() {
return Integer.toString(value);
}
}

View File

@ -0,0 +1,39 @@
package trick.common.utils.vs;
import java.math.BigInteger;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class VSLong extends VSValue {
private static final long serialVersionUID = -7792501925528852232L;
public long value;
public VSLong() {}
public VSLong(long value) {
this.value = value;
}
public long getValue() {
return value;
}
@Override
public void fromVariableServer(String string) {
value = new BigInteger(string.trim(), 10).longValue();
}
@Override
public String toVariableServer() {
return Long.toString(value);
}
@Override
public String toString() {
return Long.toString(value);
}
}

View File

@ -0,0 +1,39 @@
package trick.common.utils.vs;
import java.math.BigInteger;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class VSShort extends VSValue {
private static final long serialVersionUID = 5431648313760456676L;
public short value;
public VSShort() {}
public VSShort(short value) {
this.value = value;
}
public short getValue() {
return value;
}
@Override
public void fromVariableServer(String string) {
value = new BigInteger(string.trim(), 10).shortValue();
}
@Override
public String toVariableServer() {
return Short.toString(value);
}
@Override
public String toString() {
return Short.toString(value);
}
}

View File

@ -0,0 +1,37 @@
package trick.common.utils.vs;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class VSString extends VSValue {
private static final long serialVersionUID = 2238385297450301960L;
public String value;
public VSString() {}
public VSString(String value) {
this.value = value;
}
public String getValue() {
return value;
}
@Override
public void fromVariableServer(String string) {
value = string;
}
@Override
public String toVariableServer() {
return "\"" + value + "\"";
}
@Override
public String toString() {
return value;
}
}

View File

@ -0,0 +1,15 @@
package trick.common.utils.vs;
public abstract class VSValue implements VariableServerFluent, Cloneable {
@Override
public VSValue clone() {
try {
return (VSValue)super.clone();
}
catch (CloneNotSupportedException cloneNotSupportedException) {
return null;
}
}
}

View File

@ -0,0 +1,228 @@
package trick.common.utils.vs;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlElementRefs;
import trick.common.utils.VariableServerConnection;
/**
* @author Derek Bankieris
*
* encapsulates the data necessary to represent a Variable Server variable
*/
public class Variable<T extends VariableServerFluent> implements Serializable, Cloneable {
private static final long serialVersionUID = 4529167759720494026L;
/** possible states */
public enum State {Unknown, Invalid, Valid};
/** name */
@XmlElement(required = true)
public final String name;
/** value */
@XmlElementRefs({
@XmlElementRef(type=VSValue.class),
@XmlElementRef(type=VSBoolean.class),
@XmlElementRef(type=VSByte.class),
@XmlElementRef(type=VSDouble.class),
@XmlElementRef(type=VSFloat.class),
@XmlElementRef(type=VSInteger.class),
@XmlElementRef(type=VSLong.class),
@XmlElementRef(type=VSShort.class),
@XmlElementRef(type=VSString.class)
})
public final T value;
/** units */
String units;
/** state */
State state = State.Unknown;
/**
* constructor
*
* @param name the name
* @param value the initial value
* @param units the initial units
*/
public Variable(String name, T value, String units) {
this.name = name;
this.value = value;
this.units = units;
}
/**
* constructor
*
* @param name the name
* @param value the initial value
*/
public Variable(String name, T value) {
this(name, value, null);
}
/**
* provided for JAXB compatibility
*/
private Variable() {
name = null;
value = null;
}
/**
* sets this <code>Variable</code>'s value to <code>value</code>
*
* @param value the value to be set, expressed in Variable Server format
*/
public void setValue(String value) {
if (value.equals("BAD_REF")) {
state = State.Invalid;
}
else {
this.value.fromVariableServer(value);
state = State.Valid;
}
}
/**
* sets this <code>Variable</code>'s units to <code>units</code>
*
* @param units the units to be set
*/
public void setUnits(String units) {
this.units = units;
}
/**
* commands the Variable Server to set the variable's value to <code>value</code>
*
* @param value the value to be sent
*/
public void sendValueToVariableServer(T value,
VariableServerConnection variableServerConnection) throws IOException {
boolean invalidUnits = units == null || units.isEmpty();
variableServerConnection.put("trick.var_set(\"" +
name + "\", " + value.toVariableServer() +
(invalidUnits ? "" : ", \"" + units + "\"") + ")");
}
/**
* commands the Variable Server to set the variable's value to its current value
*/
public void sendValueToVariableServer(VariableServerConnection variableServerConnection)
throws IOException {
sendValueToVariableServer(value, variableServerConnection);
}
/**
* commands the Variable Server to set the variable's units to <code>units</code>
*
* @param units the units to be sent
*/
public void sendUnitsToVariableServer(String units,
VariableServerConnection variableServerConnection) throws IOException {
if (units != null && !units.isEmpty()) {
variableServerConnection.put("trick.var_units(\"" + name + "\", \"" + units + "\")");
}
}
/**
* commands the Variable Server to set the variable's units to its current units
*/
public void sendUnitsToVariableServer(VariableServerConnection variableServerConnection)
throws IOException {
sendUnitsToVariableServer(units, variableServerConnection);
}
/**
* Equality among <code>Variable</code>s requires only that their names
* be equal as implemented by <code>String.equals</code>.
*
* @param object the object to compare
*
* @return the equality of <code>object</code> to this <code>Variable</code>
*/
@Override
public boolean equals(Object object) {
return object != null && object instanceof Variable &&
name.equals(((Variable)object).name);
}
/**
* a <code>Variable</code>'s hashcode is equal to the hashcode of its name
*
* @return a hashcode for this object
*/
@Override
public int hashCode() {
return name.hashCode();
}
/**
* returns the value
*
* @return the value
*/
public T getValue() {
return value;
}
/**
* returns the state
*
* @return the state
*/
public State getState() {
return state;
}
/**
* returns the name
*
* @return the name
*/
public String getName() {
return name;
}
/**
* returns the units
*
* @return the units
*/
@XmlElement(required = true)
public String getUnits() {
return units;
}
@Override
@SuppressWarnings("unchecked")
public Variable<T> clone() {
try {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
new ObjectOutputStream(byteArrayOutputStream).writeObject(this);
return (Variable<T>)new ObjectInputStream(new ByteArrayInputStream(
byteArrayOutputStream.toByteArray())).readObject();
}
catch (Exception e) {
return null;
}
}
@Override
public String toString() {
return name;
}
}

View File

@ -0,0 +1,15 @@
package trick.common.utils.vs;
/**
* designates a class as being capable receiving variable events
*
* @author Derek Bankieris
*/
public interface VariableListener {
/** invoked after the variables have been updated */
public void variablesUpdated();
/** invoked if an exception is thrown during variable tracking */
public void variableUpdateFailed(Exception exception);
}

View File

@ -0,0 +1,33 @@
package trick.common.utils.vs;
import java.io.Serializable;
/**
* designates a class as being compatible with Trick's Variable Server protocol
*
* @author Derek Bankieirs
*/
public interface VariableServerFluent extends Serializable {
/**
* sets the state to reflect the value specified by the Variable Server <code>string</code>
*
* @param string the value from the Variable Server
*/
public void fromVariableServer(String string);
/**
* returns the state formatted as a Variable Server string
*
* @return the state appropriately formatted for transmission to the Variable Server
*/
public String toVariableServer();
/**
* returns a deep copy of this instance
*
* @return a deep copy of this instance
*/
public VariableServerFluent clone();
}

View File

@ -0,0 +1,137 @@
package trick.common.utils.vs;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.SwingWorker;
import trick.common.utils.VariableServerConnection;
/**
* @author Derek Bankieris
*/
public class VariableTracker extends SwingWorker<Void, String[]> {
/** connection to the Variable Server */
VariableServerConnection variableServerConnection;
/** variables being tracked */
LinkedHashSet<Variable> variables = new LinkedHashSet<Variable>(10);
/** listeners to be informed of updates the the variables */
ArrayList<VariableListener> variableListeners = new ArrayList<VariableListener>();
/** regular expression for finding units */
Pattern pattern = Pattern.compile("^(.*?)\\s*(?:\\{(.*)\\})?$");
/**
* sole constructor
*
* @param variableServerConnection connection to the Variable Server
*/
public VariableTracker(VariableServerConnection variableServerConnection) {
this.variableServerConnection = variableServerConnection;
}
/**
* begin tracking <code>variable</code>
*
* @param variable the variable to track
*/
public void add(Variable variable) throws IOException {
if (variables.add(variable)) {
variableServerConnection.add(variable.name, variable.units);
}
}
/**
* stops tracking <code>variable</code>
*
* @param variable the variable to stop tracking
*/
public void remove(Variable variable) throws IOException {
variableServerConnection.remove(variable.getName());
variables.remove(variable);
}
/**
* causes the <code>variableListener</code> to be notified of updates to the variables
*
* @param variableListener the listener to be notified
*/
public void addVariableListener(VariableListener variableListener) {
variableListeners.add(variableListener);
}
/**
* causes the <code>variableListener</code> to no longer be notified of updates to the variables
*
* @param variableListener the listener to be removed
*/
public void removeVariableListener(VariableListener variableListener) {
variableListeners.remove(variableListener);
}
/** Forever listen for incoming messages from the Variable Server. */
@Override
public Void doInBackground() throws IOException {
while (true) {
if (!isCancelled()) {
String line = variableServerConnection.get();
if (line == null) {
throw new IOException("Reached end of stream.");
}
publish(line.split("\t", -1));
}
}
}
/**
* inform listeners that the variables have been updated
*/
@Override
protected void process(List<String[]> valueList) {
if (!isCancelled()) {
String[] values = valueList.get(valueList.size() - 1);
if (values.length == variables.size() + 1) {
int i = 1;
for (Variable variable : variables) {
Matcher matcher = pattern.matcher(values[i]);
matcher.find();
variable.setValue(matcher.group(1));
String units = matcher.group(2);
if (units != null) {
variable.setUnits(units);
}
++i;
}
for (VariableListener variableListener : variableListeners) {
variableListener.variablesUpdated();
}
}
}
}
/** executed on the Event Dispatch Thread after the doInBackground method is finished */
@Override
protected void done() {
if (!isCancelled()) {
try {
// Check for any exception that occurred during execution by calling get().
get();
}
catch (Exception exception) {
for (VariableListener variableListener : variableListeners) {
variableListener.variableUpdateFailed(exception);
}
}
}
}
}

View File

@ -0,0 +1,652 @@
/*
* $Id: DataProductsApplication.java 3761 2014-12-04 18:48:47Z hchen3 $
*
*/
//========================================
// Package
//========================================
package trick.dataproducts;
//========================================
// Imports
//========================================
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.ComponentOrientation;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JToggleButton;
import javax.swing.SwingWorker;
import org.jdesktop.application.Action;
import org.jdesktop.application.View;
import org.jdesktop.swingx.JXMultiSplitPane;
import org.jdesktop.swingx.MultiSplitLayout;
import trick.common.TrickApplication;
import trick.common.ui.UIUtils;
import trick.common.ui.components.NumberTextField;
import trick.dataproducts.trickqp.TrickQPApplication;
import trick.dataproducts.utils.Session;
import trick.dataproducts.utils.SessionRun;
import trick.dataproducts.utils.SessionXMLCreator;
/**
* Data Products Application that extends {@link TrickApplication}.
*
* @author Hong Chen
* @since Trick 10
*/
public abstract class DataProductsApplication extends TrickApplication {
//========================================
// Public data
//========================================
public JTextField versionField;
public JTextField titleField;
public NumberTextField startField;
public NumberTextField stopField;
public NumberTextField freqField;
public JTextArea statusArea;
public SessionRun runToConfigure;
public String sessionFile;
public File fileDevice;
//========================================
// Protected data
//========================================
protected JLabel versionLabel;
protected JLabel titleLabel;
protected JLabel startLabel;
protected JLabel stopLabel;
protected JLabel freqLabel;
// radio buttons for plot utility
protected ButtonGroup radioButtonGroup;
protected JRadioButtonMenuItem fermiRadioButton;
protected JRadioButtonMenuItem javaRadioButton;
protected JRadioButtonMenuItem gnuplotRadioButton;
protected JToggleButton gnuplotButton;
protected String plotDevice = Session.DEVICE_OPTIONS[Session.TERMINAL_DEVICE];
protected String gnuplotTerminal = Session.GNUPLOT_TERMINAL_OPTIONS[Session.X11_GNUPLOT_TERMINAL];
protected static String TEMP_DP_FILE = "/tmp/DP_" + System.getenv("USER") + ".xml";
protected static String TEMP_SESSION_FILE = "/tmp/Session_" + System.getenv("USER") + ".xml";
//========================================
// Private Data
//========================================
private String plotCommand;
// Options are: "Simple", "Comparison", "Delta", "Contrast"
private String preferredPresentation;
// Options are: "Plot", "Table".
private String displayMode;
//========================================
// Constructors
//========================================
//========================================
// Set/Get methods
//========================================
/**
* Sets the preferred presentation.
*/
public void setPreferredPresentation(String pt) {
preferredPresentation = pt;
}
/**
* Gets the preferred presentation.
*/
public String getPreferredPresentation() {
return preferredPresentation;
}
/**
* Sets preferred display mode.
*/
public void setDisplayMode(String md) {
displayMode = md;
}
/**
* Gets preferred display mode.
*/
public String getDisplayMode() {
return displayMode;
}
/**
* Gets the common bottom component if this is what you want.
*
* @return An instance of {@link JComponent}.
*/
protected JComponent getCommonBottom() {
JPanel panel = new JPanel();
panel.setPreferredSize(new Dimension(600, 180));
panel.setLayout(new BorderLayout());
JPanel fieldsPanel = new JPanel();
FlowLayout flowLayout = new FlowLayout();
fieldsPanel.setLayout(flowLayout);
flowLayout.setAlignment(FlowLayout.LEADING);
fieldsPanel.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT);
if (DataProductsApplication.getInstance() instanceof TrickQPApplication) {
titleLabel = new JLabel("Title:");
titleField = new JTextField(15);
fieldsPanel.add(titleLabel);
fieldsPanel.add(titleField);
fieldsPanel.add(Box.createHorizontalStrut(10));
}
versionLabel = new JLabel("Version:");
versionField = new JTextField("1.0", 2);
fieldsPanel.add(versionLabel);
fieldsPanel.add(versionField);
fieldsPanel.add(Box.createHorizontalStrut(10));
startLabel = new JLabel("Start:");
startField = new NumberTextField("-1.0e20", 5);
fieldsPanel.add(startLabel);
fieldsPanel.add(startField);
fieldsPanel.add(Box.createHorizontalStrut(10));
stopLabel = new JLabel("Stop:");
stopField = new NumberTextField("1.0e20", 5);
fieldsPanel.add(stopLabel);
fieldsPanel.add(stopField);
fieldsPanel.add(Box.createHorizontalStrut(10));
freqLabel = new JLabel("Freq:");
freqField = new NumberTextField("0.0", 5);
fieldsPanel.add(freqLabel);
fieldsPanel.add(freqField);
fieldsPanel.add(Box.createHorizontalStrut(10));
panel.add(fieldsPanel, BorderLayout.NORTH);
statusArea = new JTextArea();
statusArea.setBackground(new Color(65, 65, 65));
statusArea.setForeground(Color.white);
panel.add(new JScrollPane(statusArea), BorderLayout.CENTER);
return panel;
}
//========================================
// Methods
//========================================
@Action
public void configureRunTimename() {
String msgStr1 = "Please specify the time name for the selected run\n";
String msgStr2 = "\n\n";
if (runToConfigure != null) {
msgStr2 = runToConfigure.getDir() + msgStr2 ;
//String timeName = resourceMap.getString("default.timename");
String timeName = DEFAULT_TIME_NAME;
if (runToConfigure.getTimename() != null) {
timeName = runToConfigure.getTimename();
}
Object inputValue = JOptionPane.showInputDialog(getMainFrame(), msgStr1+msgStr2, timeName);
if (inputValue != null) {
runToConfigure.setTimename(inputValue.toString());
}
} else {
JOptionPane.showMessageDialog(getMainFrame(), "Please select a Run first!", "No Run Selected", JOptionPane.WARNING_MESSAGE);
return;
}
}
@Action
public void toggleGnuplot() {
if (gnuplotButton.isSelected()) {
gnuplotButton.setIcon(resourceMap.getIcon("gnuplot.on.icon"));
gnuplotRadioButton.setSelected(true);
getAction("selectGnuplotTerminal").setEnabled(true);
} else {
gnuplotButton.setIcon(resourceMap.getIcon("gnuplot.off.icon"));
if (gnuplotRadioButton.isSelected()) {
fermiRadioButton.setSelected(true);
}
getAction("selectGnuplotTerminal").setEnabled(false);
}
}
@Action
public void selectFermi() {
gnuplotButton.setSelected(false);
getAction("selectGnuplotTerminal").setEnabled(false);
toggleGnuplot();
}
@Action
public void selectGnuplot() {
gnuplotButton.setSelected(true);
getAction("selectGnuplotTerminal").setEnabled(true);
toggleGnuplot();
}
@Action
public void selectJavaPlot() {
gnuplotButton.setSelected(false);
getAction("selectGnuplotTerminal").setEnabled(false);
toggleGnuplot();
}
@Action
public void selectTerminalDevice() {
setDevice(Session.TERMINAL_DEVICE);
}
@Action
public void selectPrinterDevice() {
setDevice(Session.PRINTER_DEVICE);
}
@Action
public void selectGnuplotTerminal() {
// do nothing
}
@Action
public void selectX11() {
setGnuplotTerminal(Session.X11_GNUPLOT_TERMINAL);
}
@Action
public void selectPSColor() {
setGnuplotTerminal(Session.PS_COLOR_GNUPLOT_TERMINAL);
}
@Action
public void selectPSBW() {
setGnuplotTerminal(Session.PS_BW_GNUPLOT_TERMINAL);
}
@Action
public void selectPNG() {
setGnuplotTerminal(Session.PNG_GNUPLOT_TERMINAL);
}
@Action
public void selectEPS() {
setGnuplotTerminal(Session.EPS_GNUPLOT_TERMINAL);
}
@Action
public void selectAQUA() {
setGnuplotTerminal(Session.AQUA_GNUPLOT_TERMINAL);
}
/**
* Cleans up the socket communication before exiting the application.
*/
@Override
protected void shutdown() {
super.shutdown();
}
/**
* Makes initialization as needed. This is called before startup().
*
* @see #startup
*/
@Override
protected void initialize(String[] args) {
super.initialize(args);
}
/**
* Starts things such as establishing socket communication, and starting monitor tasks.
* This is called after startup.
*
* @see #initialize
* @see #startup
*/
@Override
protected void ready() {
createActionController();
}
/**
* Starts building GUI. This is called after initialize.
* Once startup() is done, ready() is called.
*
* @see #initialize
* @see #ready
*/
@Override
protected void startup() {
super.startup();
gnuplotButton = new JToggleButton();
gnuplotButton.setAction(getAction("toggleGnuplot"));
gnuplotButton.setText(null);
gnuplotButton.setFocusable(false);
fermiRadioButton = new JRadioButtonMenuItem();
fermiRadioButton.setAction(getAction("selectFermi"));
fermiRadioButton.setSelected(true);
javaRadioButton = new JRadioButtonMenuItem(getAction("selectJavaPlot"));
gnuplotRadioButton = new JRadioButtonMenuItem();
gnuplotRadioButton.setAction(getAction("selectGnuplot"));
radioButtonGroup = new ButtonGroup();
radioButtonGroup.add(fermiRadioButton);
radioButtonGroup.add(javaRadioButton);
radioButtonGroup.add(gnuplotRadioButton);
View view = getMainView();
view.setComponent(createMainPanel());
view.setMenuBar(createMenuBar());
view.setToolBar(createToolBar());
show(view);
}
/**
* Creates the main panel. This is required by TrickApplication.
*
* @return a {@link JComponent} as the main panel.
*/
@Override
protected JComponent createMainPanel() {
JXMultiSplitPane msp = new JXMultiSplitPane();
String layoutDef =
"(COLUMN " +
"(ROW weight=0.8 " +
"(COLUMN weight=0.44 (LEAF name=left.top weight=0.55) " +
" (LEAF name=left.middle weight=0.45) " +
") " +
"(COLUMN weight=0.56 (LEAF name=right.top weight=0.55) " +
" (LEAF name=right.middle weight=0.45) " +
") " +
")" +
"(LEAF name=bottom weight=0.2) " +
")";
MultiSplitLayout.Node modelRoot = MultiSplitLayout.parseModel( layoutDef );
msp.getMultiSplitLayout().setModel( modelRoot );
msp.add( createLeftTop(), "left.top" );
msp.add( createLeftMiddle(), "left.middle" );
msp.add( createRightTop(), "right.top" );
msp.add( createRightMiddle(), "right.middle");
msp.add( createBottom(), "bottom" );
msp.validate();
return msp;
}
/**
* Creates the component for left top.
*/
protected abstract JComponent createLeftTop();
/**
* Creates the component for left middle.
*/
protected abstract JComponent createLeftMiddle();
/**
* Creates the component for right top.
*/
protected abstract JComponent createRightTop();
/**
* Creates the component for right middle.
*/
protected abstract JComponent createRightMiddle();
/**
* Creates the component for the bottom.
*/
protected abstract JComponent createBottom();
/**
* Helper method for setting gnuplot terminal.
*
* @param index One of these: Session.X11_GNUPLOT_TERMINAL,
* Session.PS_COLOR_GNUPLOT_TERMINAL,
* Session.PW_BW_GNUPLOT_TERMINAL,
* Session.PNG_GNUPLOT_TERMINAL,
* Session.EPS_GNUPLOT_TERMINAL,
* Session.AQUA_GNUPLOT_TERMINAL.
*/
private void setGnuplotTerminal(int index) {
if (index >= 0 && index<Session.GNUPLOT_TERMINAL_OPTIONS.length) {
gnuplotTerminal = Session.GNUPLOT_TERMINAL_OPTIONS[index];
} else {
gnuplotTerminal = Session.GNUPLOT_TERMINAL_OPTIONS[Session.X11_GNUPLOT_TERMINAL];
}
}
/**
* Helper method for setting plot device.
*
* @param index One of these: Session.TERMINAL_DEVICE,
* Session.PRINTER_DEVICE,
* Session.FILE_DEVICE.
*/
private void setDevice(int index) {
if (index >= 0 && index<Session.DEVICE_OPTIONS.length) {
plotDevice = Session.DEVICE_OPTIONS[index];
} else {
plotDevice = Session.DEVICE_OPTIONS[Session.TERMINAL_DEVICE];
}
}
/**
* Resets all commond fields if available.
*/
public void resetCommonFields() {
if (titleField != null) {
titleField.setText("");
}
versionField.setText("1.0");
startField.setText("-1.0e20");
stopField.setText("1.0e20");
freqField.setText("0.0");
}
/**
* Sets the action controller for the application.
*/
protected abstract void createActionController();
/**
* Saves {@link Session} related data to a specified file.
*
* @param session An instance of {@link Session}.
* @param fileName The name of a file.
* @param runData A list for runs.
* @param productFilesData A list of dp files.
*/
public void saveSessionToFile(Session session, String fileName, Object[] runData, Object[] productFilesData) {
if (fileName == null) {
// User clicked a plot button, so create temporary session file
sessionFile = TEMP_SESSION_FILE;
} else {
sessionFile = fileName;
}
SessionXMLCreator xmlCreator = new SessionXMLCreator();
xmlCreator.setXMLFile(sessionFile);
xmlCreator.setDTDFile("Session.dtd");
xmlCreator.setPublicID("-//Tricklab//DTD Session V1.0//EN");
session.setVersion(versionField.getText());
// session file doesn't have title, add this back if it needs it.
//if (!titleField.getText().isEmpty()) {
//session.setTitle(titleField.getText());
//}
session.setDevice(plotDevice);
if (gnuplotButton.isSelected()) {
session.setGnuplotTerminal(gnuplotTerminal);
}
session.setTStart((Double)startField.getValue());
session.setTStop((Double)stopField.getValue());
session.setFrequency((Double)freqField.getValue());
xmlCreator.setRoot(session);
for (int i = 0; i < runData.length; i++) {
SessionRun sr = null;
if (runData[i] instanceof SessionRun) {
sr = (SessionRun)runData[i];
} else {
sr = new SessionRun(runData[i].toString());
}
session.addRun(sr);
}
for (int i = 0; i < productFilesData.length; i++) {
session.addProductFile(productFilesData[i].toString());
}
xmlCreator.runCreator();
}
/**
* Launches the external program for plotting.
*
* @param sessionFile The session used for plotting.
*/
public void launchPlotProgram(String sessionFile) {
if (fermiRadioButton.isSelected()) {
plotCommand = resourceMap.getString("fxplot.command");
} else if (javaRadioButton.isSelected()) {
plotCommand = resourceMap.getString("jxplot.command");
} else if (gnuplotRadioButton.isSelected()) {
plotCommand = resourceMap.getString("gxplot.command");
}
plotCommand = UIUtils.getTrickBin() + File.separator + plotCommand;
(new LaunchPlotProcessTask(plotCommand, sessionFile)).execute();
}
/**
* Launches a process with specified parameters.
*
* @param command The operating system program and arguments.
*/
public void launchPlotProcess(String... command) throws Exception{
if (command == null || command.length < 0) {
printStatusMessage("No plotting command specified!\n");
return;
}
if (plotDevice.equals(Session.DEVICE_OPTIONS[Session.FILE_DEVICE])) {
printStatusMessage("Generating postscript file(s) ...\n");
} else {
printStatusMessage("===>>>Launching " + command[0] + "<<<===\n");
}
ProcessBuilder pb = new ProcessBuilder(command);
captureProcessMessage(pb.start());
}
/**
* Redirects runtime process messages from screen to GUI status area.
*
* @param runtimeProcess The runtime process from which screen messages is generated.
*/
public void captureProcessMessage(Process runtimeProcess) {
try {
if (runtimeProcess == null) {
return;
}
BufferedReader stdInput = new BufferedReader(new InputStreamReader(runtimeProcess.getInputStream()));
BufferedReader stdError = new BufferedReader(new InputStreamReader(runtimeProcess.getErrorStream()));
String s = null;
// read the output from the command
while ((s = stdInput.readLine()) != null) {
printStatusMessage(s + "\n");
}
// read any errors from the attempted command
while ((s = stdError.readLine()) != null) {
printStatusMessage(s + "\n");
}
} catch (IOException ioe) {
printStatusMessage(ioe.getMessage() + "\n");
}
}
/**
* Prints status message to the status text area.
*/
public void printStatusMessage(String msg) {
statusArea.append(msg);
}
private class LaunchPlotProcessTask extends SwingWorker<Void, Void> {
private String[] processCommand;
public LaunchPlotProcessTask(String... command) {
this.processCommand = command;
}
@Override
public Void doInBackground() {
try {
launchPlotProcess(processCommand);
} catch (Exception e) {
printStatusMessage("Error launching plotting process!\n");
}
return null;
}
@Override
public void done() {
}
}
}

View File

@ -0,0 +1,799 @@
/*
* $Id: JXPlotApplication.java 3795 2015-02-11 19:35:28Z alin $
*/
package trick.dataproducts.plot;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.util.ArrayList;
import javax.swing.DefaultListModel;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.JToolBar;
import javax.swing.ListModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.xml.parsers.ParserConfigurationException;
import org.jdesktop.application.Action;
import org.jdesktop.application.Application;
import org.jdesktop.application.View;
import org.jdesktop.swingx.JXMultiSplitPane;
import org.jdesktop.swingx.JXTree;
import org.jdesktop.swingx.MultiSplitLayout;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.title.TextTitle;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;
import org.xml.sax.SAXException;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.DefaultFontMapper;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfWriter;
import trick.common.TrickApplication;
import trick.common.ui.UIUtils;
import trick.dataproducts.plot.utils.PlotUtils;
import trick.dataproducts.plot.utils.TrickChart;
import trick.dataproducts.plot.utils.TrickChartFrame;
import trick.dataproducts.plot.utils.TrickFrame;
import trick.dataproducts.plot.utils.TrickTableFrame;
import trick.dataproducts.plot.utils.TrickXYLineAndShapeRenderer;
import trick.dataproducts.plot.utils.TrickXYPlot;
import trick.dataproducts.plot.utils.TrickXYSeries;
import trick.dataproducts.trickqp.utils.Product;
import trick.dataproducts.trickqp.utils.ProductCurve;
import trick.dataproducts.trickqp.utils.ProductDataPanel;
import trick.dataproducts.trickqp.utils.ProductPage;
import trick.dataproducts.trickqp.utils.ProductPlot;
import trick.dataproducts.trickqp.utils.ProductTable;
import trick.dataproducts.trickqp.utils.ProductVar;
import trick.dataproducts.trickqp.utils.ProductVarcase;
import trick.dataproducts.trickqp.utils.ProductDomParser;
import trick.dataproducts.utils.Session;
import trick.dataproducts.utils.SessionRun;
import trick.dataproducts.utils.SessionDomParser;
/**
* Plotting using Java.
*
* @author Hong Chen
* @since Trick 13
*/
public class JXPlotApplication extends TrickApplication {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
private JXTree productTree;
private DefaultMutableTreeNode productTreeRoot;
@SuppressWarnings("rawtypes")
private JList tableList;
private static int chartInitialLocX = 50;
private static int chartInitialLocY = 50;
private Session sessionObject;
//========================================
// Constructors
//========================================
//========================================
// Actions
//========================================
@Action
public void saveAllToPDF() {
File file = UIUtils.chooseSaveFile(null, "plot_", "pdf", getMainFrame());
if (file == null) {
return;
}
try {
int dpFileCount = productTreeRoot.getChildCount();
if (dpFileCount > 0) {
Document document = new Document(PageSize.A4);
PdfWriter writer = null;
PdfContentByte pdfContent = null;
try {
writer = PdfWriter.getInstance(document, new FileOutputStream(file));
document.open();
// this object can be reused which is used to write each page to the same PDF file
pdfContent = writer.getDirectContent();
} catch (DocumentException e) {
e.printStackTrace();
}
for (int i = 0; i < dpFileCount; i++) {
DefaultMutableTreeNode eachDPFile = (DefaultMutableTreeNode)productTree.getModel().getChild(productTreeRoot, i);
int pageCount = eachDPFile.getChildCount();
for (int j = 0; j < pageCount; j++) {
DefaultMutableTreeNode eachPage = (DefaultMutableTreeNode)productTree.getModel().getChild(eachDPFile, j);
if (eachPage.getUserObject() instanceof TrickChartFrame) {
TrickChartFrame theFrame = (TrickChartFrame)eachPage.getUserObject();
theFrame.writePDFPage(pdfContent, new DefaultFontMapper());
}
}
}
// document needs to be closed after the PDF file is saved
if (document != null) {
document.close();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
//========================================
// Set/Get methods
//========================================
//========================================
// Methods
//========================================
/**
* Main method for this application.
*/
public static void main(String[] args) {
Application.launch(JXPlotApplication.class, args);
}
/**
* Makes initialization as needed. This is called before startup().
*
* @see #startup
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
protected void initialize(String[] args) {
super.initialize(args);
// TODO: make it as a tree
final ListModel listModel = new DefaultListModel();
tableList = new JList(listModel);
tableList.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
int index = tableList.locationToIndex(e.getPoint());
if (index != -1 && listModel.getElementAt(index) instanceof TrickFrame) {
TrickFrame theFrame = (TrickFrame)listModel.getElementAt(index);
if (!theFrame.isVisible()) {
theFrame.setVisible(true);
} else {
theFrame.requestFocus();
theFrame.toFront();
}
}
}
});
productTreeRoot = new DefaultMutableTreeNode("Root");
DefaultTreeModel treeModel = new DefaultTreeModel(productTreeRoot);
productTree = new JXTree(treeModel);
productTree.setRootVisible(false);
productTree.setShowsRootHandles(true);
productTree.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
TreePath clickedPath = null;
DefaultMutableTreeNode clickedNode = null;
// when nothing is viewable, do nothing and return immediately
if (productTree.getClosestPathForLocation(e.getX(), e.getY()) == null) {
return;
}
clickedPath = productTree.getClosestPathForLocation(e.getX(), e.getY());
if (clickedPath.getLastPathComponent() instanceof DefaultMutableTreeNode) {
clickedNode = (DefaultMutableTreeNode)clickedPath.getLastPathComponent();
}
if (clickedNode.getUserObject() instanceof TrickFrame) {
TrickFrame theFrame = (TrickFrame)clickedNode.getUserObject();
if (!theFrame.isVisible()) {
theFrame.setVisible(true);
} else {
theFrame.requestFocus();
theFrame.toFront();
}
}
}
});
if (args.length > 0) {
openSessionFile(args[0]);
}
}
/**
* Opens a session file for plotting.
*/
private void openSessionFile(String sessionFile) {
File file = new File(sessionFile);
if (file != null) {
try {
sessionObject = SessionDomParser.parse(file);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
for (String dpFile : sessionObject.getProductFiles()) {
// if parsing is failed, stop!
try {
Product productObject = ProductDomParser.parse(new File(dpFile)) ;
if (productObject != null) {
// if the mode is not defined or is set to PLOT_MODE, plot the data.
if (sessionObject.getMode() == null || sessionObject.getMode().equals(Session.MODE_OPTIONS[Session.PLOT_MODE])) {
DefaultMutableTreeNode dpFileNode = new DefaultMutableTreeNode(dpFile);
productTreeRoot.add(dpFileNode);
((DefaultTreeModel) productTree.getModel()).reload();
// if there is any page
if (productObject.getPageList() != null && productObject.getPageList().size() > 0) {
for (ProductPage eachPage : productObject.getPageList()) {
if (eachPage != null) {
createAndShowCharts(dpFileNode, eachPage);
}
}
}
} else if (sessionObject.getMode().equals(Session.MODE_OPTIONS[Session.TABLE_MODE])) {
if (productObject.getTableList() != null && productObject.getTableList().size() > 0) {
for (ProductTable eachTable : productObject.getTableList()) {
createAndShowTable(tableList, productObject.getTitle(), eachTable);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("\nERROR parsing " + dpFile + " !!!\n");
}
}
}
}
/**
* Helper method for creating table.
*/
@SuppressWarnings({ "rawtypes" })
private void createAndShowTable(JList list, String title, ProductTable theTable) {
showTable(theTable);
}
/**
* Helper method for creating charts for a page.
*/
private void createAndShowCharts(DefaultMutableTreeNode dpFileNode, ProductPage thePage) {
ArrayList<TrickChart> chartList = new ArrayList<TrickChart>();
if (sessionObject.getPresentation().equals(Session.PRESENTATION_OPTIONS[Session.SIMPLE_PRESENTATION])) {
createChartsForSingle(thePage, chartList);
} else if (sessionObject.getPresentation().equals(Session.PRESENTATION_OPTIONS[Session.COMPARISON_PRESENTATION])) {
createChartsForComparison(thePage, chartList);
} else if (sessionObject.getPresentation().equals(Session.PRESENTATION_OPTIONS[Session.DELTA_PRESENTATION])) {
createChartsForDelta(thePage, chartList, false);
} else if (sessionObject.getPresentation().equals(Session.PRESENTATION_OPTIONS[Session.CONTRAST_PRESENTATION])) {
createChartsForContrast(thePage, chartList);
}
showPagePlots(dpFileNode, thePage, chartList);
}
/**
* Helper method for creating all charts using contrast plotting for a particular {@link ProductPage}
* and adding the charts to a list. Contrast plotting shows both comparison and delta plots on the
* same page.
*/
private void createChartsForContrast(ProductPage thePage, ArrayList<TrickChart> chartList) {
createChartsForComparison(thePage, chartList);
createChartsForDelta(thePage, chartList, true);
}
/**
* Helper method for creating all charts using delta plotting for a particular {@link ProductPage}
* and adding the charts to a list.
*/
private void createChartsForDelta(ProductPage thePage, ArrayList<TrickChart> chartList, boolean isContrast) {
for (ProductPlot eachPlot : thePage.getPlotList()) {
XYSeriesCollection dataset = null;
int totalRuns = sessionObject.getRuns().size();
if (totalRuns == 1) {
dataset = new XYSeriesCollection();
for (ProductCurve eachCurve : eachPlot.getCurveList()) {
//dataset.addSeries(getXYSeriesForCurve(sessionObject.getRuns().get(0), thePage, eachPlot, eachCurve));
addSeriesToDataset(dataset, getXYSeriesForCurve(sessionObject.getRuns().get(0), thePage, eachPlot, eachCurve));
}
createAndAddChart("(" + sessionObject.getRuns().get(0).getDirName() +")", chartList, thePage, eachPlot, dataset, false);
} else {
if (isContrast) {
dataset = new XYSeriesCollection();
}
for (int i = 0; i < totalRuns - 1; i++) {
for (int j = i + 1; j < totalRuns; j++) {
if (!isContrast) {
dataset = new XYSeriesCollection();
}
for (ProductCurve eachCurve : eachPlot.getCurveList()) {
TrickXYSeries series1 = getXYSeriesForCurve(sessionObject.getRuns().get(i), thePage, eachPlot, eachCurve);
TrickXYSeries series2 = getXYSeriesForCurve(sessionObject.getRuns().get(j), thePage, eachPlot, eachCurve);
if (series1 == null || series2 == null) {
continue;
}
int totalCount = series1.getItemCount() < series2.getItemCount() ? series1.getItemCount() : series2.getItemCount();
TrickXYSeries deltaSeries = new TrickXYSeries("DELTA: "
+ series1.getDescription().substring(0, series1.getDescription().lastIndexOf("["))
+ " ["
+ sessionObject.getRuns().get(i).getDirName()
+ " - "
+ sessionObject.getRuns().get(j).getDirName() + "]", false, true);
for (int k = 0; k < totalCount; k++) {
deltaSeries.add(series1.getX(k).doubleValue(), series1.getY(k).doubleValue() - series2.getY(k).doubleValue());
}
//dataset.addSeries(deltaSeries);
addSeriesToDataset(dataset, deltaSeries);
deltaSeries.setXVar(series1.getXVar());
deltaSeries.setYVar(series1.getYVar());
}
if (!isContrast) {
createAndAddChart("(Difference)", chartList, thePage, eachPlot, dataset, isContrast);
}
}
}
if (isContrast) {
createAndAddChart("(Difference)", chartList, thePage, eachPlot, dataset, true);
}
}
}
}
/**
* Helper method for creating all charts using comparison plotting for a particular {@link ProductPage}
* and adding the charts to a list.
*/
private void createChartsForComparison(ProductPage thePage, ArrayList<TrickChart> chartList) {
for (ProductPlot eachPlot : thePage.getPlotList()) {
XYSeriesCollection dataset = getComparisonPlotDataset(thePage, eachPlot);
createAndAddChart("(Compare)" , chartList, thePage, eachPlot, dataset, false);
}
}
/**
* Helper method for creating all charts using single plotting for a particular {@link ProductPage}
* and adding the charts to a list.
*/
private void createChartsForSingle(ProductPage thePage, ArrayList<TrickChart> chartList) {
for (ProductPlot eachPlot : thePage.getPlotList()) {
for (SessionRun eachRun : sessionObject.getRuns()) {
XYSeriesCollection dataset = getSinglePlotDataset(eachRun, thePage, eachPlot);
createAndAddChart("("+eachRun.getDirName()+")", chartList, thePage, eachPlot, dataset, false);
}
}
}
/**
* Creates a chart for the specified {@link XYSeriesCollection} and {@link ProductPlot} and then
* adds to the list.
*/
private void createAndAddChart(String subTitle, ArrayList<TrickChart> chartList, ProductPage aPage, ProductPlot aPlot, XYSeriesCollection dataset, boolean isContrast) {
XYPlot plot = createXYPlot(aPage, aPlot, dataset);
TrickChart chart = new TrickChart(aPlot.getTitle(), TrickChart.TRICK_DEFAULT_TITLE_FONT, plot, true);
//TrickChartTheme chartTheme = new TrickChartTheme("TrickChart");
//chartTheme.apply(chart);
configureChart(subTitle, chart, aPage, aPlot, isContrast);
chartList.add(chart);
}
/**
* Helper method for creating a {@link XYPlot} for the specified {@link ProductPlot}
* and logged data.
*/
private XYPlot createXYPlot(ProductPage aPage, ProductPlot aPlot, XYSeriesCollection dataset) {
DecimalFormat newFormat = new DecimalScientificFormat();
NumberAxis xAxis = new NumberAxis(null);
xAxis.setNumberFormatOverride(newFormat);
NumberAxis yAxis = new NumberAxis(null);
yAxis.setNumberFormatOverride(newFormat);
TrickXYLineAndShapeRenderer renderer = new TrickXYLineAndShapeRenderer();
return new TrickXYPlot(aPage, aPlot, dataset, xAxis, yAxis, renderer);
}
/**
* Configures the specified chart.
*/
private void configureChart(String subTitleText, TrickChart chart, ProductPage aPage, ProductPlot aPlot, boolean isContrast) {
// TODO: will see if need to remove the legend for contrast plotting
//if (isContrast) {
// chart.removeLegend();
//} else {
if (aPlot.getForegroundColor() != null) {
chart.getLegend().setItemPaint(aPlot.getForegroundColor());
} else if (aPage.getForegroundColor() != null) {
chart.getLegend().setItemPaint(aPage.getForegroundColor());
}
if (aPlot.getBackgroundColor() != null) {
chart.getLegend().setBackgroundPaint(aPlot.getBackgroundColor());
} else if (aPage.getBackgroundColor() != null) {
chart.getLegend().setBackgroundPaint(aPage.getBackgroundColor());
}
//}
TextTitle subTitle = null;
if (subTitleText != null && !subTitleText.isEmpty()) {
subTitle = new TextTitle(subTitleText, TrickChart.TRICK_DEFAULT_SUBTITLE_FONT);
}
// Font
if (aPlot.getFont() != null && !(aPlot.getFont().isEmpty())) {
Font plotFont = ProductDataPanel.getFontFromText(aPlot.getFont());
chart.getTitle().setFont(plotFont);
//if (!isContrast) {
chart.getLegend().setItemFont(plotFont);
//}
if (subTitleText != null && !subTitleText.isEmpty()) {
subTitle.setFont(plotFont);
}
}
if (subTitle != null) {
chart.addSubtitle(subTitle);
}
}
/**
* Shows all plots on a page.
*/
private void showPagePlots(DefaultMutableTreeNode dpFileNode, ProductPage thePage, ArrayList<TrickChart> chartList) {
if (chartList.size() > 0) {
TrickChartFrame chartFrame = new TrickChartFrame(thePage.getTitle(), getMainFrame().getIconImage(), thePage, chartList);
dpFileNode.add(new DefaultMutableTreeNode(chartFrame));
((DefaultTreeModel)productTree.getModel()).reload();
locateFrame(chartFrame);
}
}
private void locateFrame(TrickFrame frame) {
frame.setLocation(chartInitialLocX, chartInitialLocY);
chartInitialLocX += 30;
chartInitialLocY += 30;
frame.pack();
frame.setVisible(true);
}
/**
* Display the table.
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
private void showTable(ProductTable theTable) {
if (theTable == null || theTable.getColumnList() == null || theTable.getColumnList().size() < 1) {
return;
}
TrickTableFrame tableFrame = new TrickTableFrame(theTable.getTitle(), getMainFrame().getIconImage(), sessionObject, theTable);
tableFrame.setLocation(this.getMainFrame().getLocation());
if (tableList.getModel() instanceof DefaultListModel) {
DefaultListModel listModel = (DefaultListModel)tableList.getModel();
listModel.addElement(tableFrame);
}
locateFrame(tableFrame);
}
/**
* Gets the dataset for single plotting. Note that for single plotting,
* data from different runs is showing on different plots.
* @param page TODO
*/
private XYSeriesCollection getSinglePlotDataset(SessionRun theRun, ProductPage page, ProductPlot plot) {
XYSeriesCollection dataset = new XYSeriesCollection();
for (ProductCurve eachCurve : plot.getCurveList()) {
if (eachCurve != null && eachCurve.isValid()) {
TrickXYSeries series = getXYSeriesForCurve(theRun, page, plot, eachCurve);
if (series != null) {
//dataset.addSeries(series);
addSeriesToDataset(dataset, series);
}
}
}
return dataset;
}
/**
* Helper method for getting {@link XYSeries} for the specified {@link ProductCurve}.
* @param page TODO
*/
private TrickXYSeries getXYSeriesForCurve(SessionRun theRun, ProductPage page, ProductPlot plot, ProductCurve eachCurve) {
TrickXYSeries series = null;
ProductVar theXVar = null;
ProductVar theYVar = null;
// a curve either has varcase or X & Y and doesn't have both at the same time
if (eachCurve.hasVarcase()) {
for (ProductVarcase eachVarcase : eachCurve.getVarcaseList()) {
if (eachVarcase.isValid()) {
theXVar = eachVarcase.getX();
theYVar = eachVarcase.getY();
series = PlotUtils.getXYVarSeries(theRun, page, plot, theXVar, theYVar);
// if XYSeries for this varcase can be found, skip the rest. otherwise, keep checking the next varcase
if (series != null) {
break;
}
}
}
} else {
theXVar = eachCurve.getX();
theYVar = eachCurve.getY();
series = PlotUtils.getXYVarSeries(theRun, page, plot, theXVar, theYVar);
}
return series;
}
/**
* Helper method for setting X and Y variable scales.
* If the variable itself doesn't specify the scale, the plot scale is used if available.
* If the variable does have the scale specified, the plot scale is ignored.
*/
/*private void setXYVarScale(ProductPlot plot, ProductVar theXVar, ProductVar theYVar) {
if (theXVar.getScale() == null) {
if (plot.getXScale() != null && !plot.getXScale().isEmpty()) {
try {
theXVar.setScale(Double.parseDouble(plot.getXScale()));
} catch (Exception e) {
// if there is an exception, just simply don't set the scale.
}
}
}
if (theYVar.getScale() == null) {
if (plot.getYScale() != null && !plot.getYScale().isEmpty()) {
try {
theYVar.setScale(Double.parseDouble(plot.getYScale()));
} catch (Exception e) {
// if there is an exception, just simply don't set the scale.
}
}
}
}*/
/**
* Gets the dataset for comparison plotting. Note that for comparison plotting,
* data from different runs is showing on the same plot.
* @param page TODO
*/
private XYSeriesCollection getComparisonPlotDataset(ProductPage page, ProductPlot plot) {
XYSeriesCollection dataset = new XYSeriesCollection();
for (ProductCurve eachCurve : plot.getCurveList()) {
if (eachCurve != null) {
for (SessionRun eachRun : sessionObject.getRuns()) {
TrickXYSeries series = getXYSeriesForCurve(eachRun, page, plot, eachCurve);
if (series != null) {
addSeriesToDataset(dataset, series);
}
}
}
}
return dataset;
}
/**
* Helper method for adding the data series index as the prefix for the key of a series
* so that the key is guaranteed to be unique.
*/
private void addSeriesToDataset(XYSeriesCollection dataset, TrickXYSeries series) {
String theKey = series.getKey().toString();
theKey = "Series " + dataset.getSeriesCount() + ": " + theKey.toString();
series.setKey(theKey);
dataset.addSeries(series);
}
/**
* Starts building GUI. This is called after initialize.
* Once startup() is done, ready() is called.
*
* @see #initialize
* @see #ready
*/
@Override
protected void startup() {
super.startup();
View view = getMainView();
view.setComponent(createMainPanel());
view.setMenuBar(createMenuBar());
//view.setToolBar(createToolBar());
show(view);
//getMainFrame().setLocation(0, 0);
}
@Override
protected void ready() {
super.ready();
}
@Override
protected void shutdown() {
try {
super.shutdown();
} catch (Exception e) {
// add this catch here in order not to show the warning
// exception when try to exit the application while the
// plotting frame is maximized. this is due to the problem
// with storing session of the framework. here basically,
// the plotting frame session is not saved which we don't
// need it anyway.
// do nothing
}
}
/**
* Creates the main panel. This is required by TrickApplication.
*
* @return a {@link JComponent} as the main panel.
*/
@Override
protected JComponent createMainPanel() {
JXMultiSplitPane msp = new JXMultiSplitPane();
String layoutDef =
"(COLUMN (LEAF name=top weight=0.7)" +
//" (LEAF name=middle weight=0.2)" +
" (LEAF name=bottom weight=0.3)" +
")";
MultiSplitLayout.Node modelRoot = MultiSplitLayout.parseModel( layoutDef );
msp.getMultiSplitLayout().setModel( modelRoot );
JPanel productsPanel = UIUtils.createSearchableTitledPanel("Products & Pages", productTree, null);
productsPanel.setMinimumSize(new Dimension(250, 50));
productsPanel.setPreferredSize(new Dimension(500, 150));
JPanel tablesPanel = UIUtils.createSearchableTitledPanel("Tables", tableList, null);
tablesPanel.setMinimumSize(new Dimension(250, 50));
//pagesPanel.setPreferredSize(new Dimension(400, 50));
msp.add(productsPanel, "top" );
//msp.add(pagesPanel, "middle" );
msp.add(tablesPanel, "bottom" );
return msp;
}
/**
* Create the JMenuBar for this application.
*/
@Override
protected JMenuBar createMenuBar() {
JMenuBar menuBar = super.createMenuBar();
JMenu menu = menuBar.getMenu(0);
menu.add(new JSeparator(), 0);
//menu.add(new JMenuItem(getAction("saveALLToPDF")), 0);
menu.add(createMenuItem("saveAllToPDF"), 0);
return menuBar;
}
/**
* Creates the tool bar for the application.
*
* @return a {@link JToolBar} for the application.
*/
@Override
protected JToolBar createToolBar() {
return new JToolBar();
}
/*
TODO: may want to add feature for righ_clicking a series to have
a pop up menu for making it visible or invisible.
@Override
public void actionPerformed(ActionEvent e) {
int series = -1;
if (e.getActionCommand().equals("S1")) {
series = 0;
}
else if (e.getActionCommand().equals("S2")) {
series = 1;
}
else if (e.getActionCommand().equals("S3")) {
series = 2;
}
if (series >= 0) {
boolean visible = this.renderer.getItemVisible(series, 0);
this.renderer.setSeriesVisible(series, new Boolean(!visible));
}
}*/
//========================================
// Inner classes
//========================================
public class DecimalScientificFormat extends DecimalFormat {
private static final long serialVersionUID = -7709354031636993724L;
private DecimalFormat normalFormat = new DecimalFormat("0.#####");
private DecimalFormat scientificFormat = new DecimalFormat("0.#####E0");
@Override
public StringBuffer format(double number, StringBuffer result, FieldPosition fieldPosition) {
String decimalFormat = normalFormat.format(number);
String numberString = Double.toString(number);
boolean needScientificNotion = false;
int dotLoc = numberString.indexOf(".");
if (numberString.indexOf("E") != -1) {
needScientificNotion = true;
} else if (dotLoc == -1) {
if (numberString.length() > 5) {
needScientificNotion = true;
}
} else {
if (dotLoc >= 5) {
needScientificNotion = true;
} else if (numberString.length() - dotLoc >= 6) {
needScientificNotion = true;
}
}
if (number != 0.0 && needScientificNotion) {
return scientificFormat.format(number, result, fieldPosition);
} else {
return result.append(decimalFormat);
}
}
}
}

View File

@ -0,0 +1,11 @@
#
# $Id: JXPlotApplication.properties 3531 2014-05-16 16:32:51Z hchen3 $
#
Application.id = JXPlotApplication
Application.title = Trick Plot
mainFrame.title = Trick Plot
saveAllToPDF.Action.text = &Make All to PDF
saveAllToPDF.Action.shortDescription = Make a PDF of all plots of all pages

View File

@ -0,0 +1,373 @@
/*
* $Id: PlotUtils.java 3795 2015-02-11 19:35:28Z alin $
*/
package trick.dataproducts.plot.utils;
import java.awt.Color;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.StyledDocument;
import org.jfree.data.xy.XYSeries;
import trick.common.ui.TrickFileFilter;
import trick.common.ui.UIUtils;
import trick.common.utils.BinaryDataReader;
import trick.common.utils.CSVDataReader;
import trick.common.utils.DataReader;
import trick.dataproducts.trickqp.utils.ProductColumn;
import trick.dataproducts.trickqp.utils.ProductPage;
import trick.dataproducts.trickqp.utils.ProductPlot;
import trick.dataproducts.trickqp.utils.ProductTable;
import trick.dataproducts.trickqp.utils.ProductVar;
import trick.dataproducts.utils.SessionRun;
/**
* This data reader is for reading recorded data from different type of files.
*
* @author Hong Chen
* @since Trick 13
*/
public class PlotUtils {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
//========================================
// Methods
//========================================
/**
* Writes the logged data based on the {@link ProductTable} spec to the {@link StyledDocument}
* for a specified {@link SessionRun}. The data is then displayed in the form of a table.
* This is much faster than using Java table component for a large set of data.
*
* @param run The RUN_ directory that contains the logged data.
* @param theTable The table spec.
* @param doc The document that holds the logged data in order
* for the data to be shown in the form of a table.
*/
public static void insertTableData(SessionRun run, ProductTable theTable, StyledDocument doc) {
ArrayList<DataReader> varDataReaderList = null;
File runDir = new File(run.getDir());
if (runDir != null && runDir.exists()) {
File[] files = UIUtils.getListFiles(runDir, TrickFileFilter.TRICK_DATA_RECORD);
StringBuffer eachRow = new StringBuffer();
// do nothing if no data recording files found
if (files == null) {
return;
}
// style for header
StyleContext context = new StyleContext();
Style headingStyle = context.getStyle(StyleContext.DEFAULT_STYLE);
StyleConstants.setAlignment(headingStyle, StyleConstants.ALIGN_RIGHT);
StyleConstants.setBold(headingStyle, true);
StyleConstants.setFontSize(headingStyle, 14);
StyleConstants.setSpaceAbove(headingStyle, 4);
StyleConstants.setSpaceBelow(headingStyle, 4);
try {
doc.insertString(doc.getLength(), "Title: " + theTable.getTitle() + "\n", headingStyle);
doc.insertString(doc.getLength(), "Run: " + run.getDir() + "\n\n", headingStyle);
} catch (BadLocationException ble) {
ble.printStackTrace();
}
eachRow.setLength(0);
varDataReaderList = new ArrayList<DataReader>();
// build up the data reader list for reading the data and write the variable names on table
// variable names row
eachRow.append("Line#\t");
for (ProductColumn theColumn : theTable.getColumnList()) {
DataReader eachReader = getVarDataReader(runDir, theColumn.getVar());
eachRow.append(theColumn.getVar().getShortName() + " {" + theColumn.getVar().getUnits() + "}" + "\t");
if (eachReader == null || eachReader.locateVarIndex(theColumn.getVar().getName()) == -1) {
continue;
}
try {
eachReader.beginRead(theColumn.getVar());
} catch (IOException e) {
e.printStackTrace();
}
varDataReaderList.add(eachReader);
}
eachRow.append("\n");
if (varDataReaderList.size() < 1) {
return;
}
try {
StyleConstants.setBackground(headingStyle, Color.lightGray);
doc.insertString(doc.getLength(), eachRow.toString(), headingStyle);
eachRow.setLength(0);
} catch (BadLocationException ble) {
ble.printStackTrace();
}
double eachVarValue = Double.NaN;
// style for data
context = new StyleContext();
Style dataStyle = context.getStyle(StyleContext.DEFAULT_STYLE);
StyleConstants.setAlignment(dataStyle, StyleConstants.ALIGN_RIGHT);
StyleConstants.setBold(dataStyle, false);
StyleConstants.setFontSize(dataStyle, 12);
StyleConstants.setForeground(dataStyle, Color.BLUE);
int lineIndex = 0;
while (true) {
eachRow.append(lineIndex + "\t");
// get one value for each variable at a time
for (DataReader eachReader : varDataReaderList) {
try {
eachVarValue = eachReader.getVarValue();
if (Double.isNaN(eachVarValue)) {
break;
}
eachRow.append(eachVarValue + "\t");
} catch (FileNotFoundException e) {
System.err.println(e);
} catch (IOException e) {
System.err.println(e);
}
}
if (Double.isNaN(eachVarValue)) {
break;
}
eachRow.append("\n");
try {
if ((lineIndex & 1) == 0) {
StyleConstants.setBackground(dataStyle, Color.white);
} else {
StyleConstants.setBackground(dataStyle, Color.lightGray);
}
doc.insertString(doc.getLength(), eachRow.toString(), dataStyle);
eachRow.setLength(0);
lineIndex++;
} catch (BadLocationException ble) {
ble.printStackTrace();
}
}
// end data reader
for (DataReader eachReader : varDataReaderList) {
eachReader.endRead();
}
}
}
/**
* Builds a {@link XYSeries} for x and y of the specified plot spec from the recorded data that is in a particular run directory.
*
* @param run A {@link SessionRun} instance.
* @param plot A {@link ProductPlot} instance.
* @param xVar The X variable.
* @param yVar The Y variable.
* @return An instance of {@link XYSeries}.
*/
public static TrickXYSeries getXYVarSeries(
SessionRun run,
ProductPage page,
ProductPlot plot,
ProductVar xVar,
ProductVar yVar
) {
TrickXYSeries series = null;
DataReader dataReaderX = null;
DataReader dataReaderY = null;
File runDir = new File(run.getDir());
if (runDir != null && runDir.exists()) {
File[] files = UIUtils.getListFiles(runDir, TrickFileFilter.TRICK_DATA_RECORD);
// do nothing if no data recording files found
if (files == null) {
return series;
}
dataReaderX = getVarDataReader(runDir, xVar);
if (dataReaderX == null || dataReaderX.locateVarIndex(xVar.getName()) == -1) {
return series;
}
dataReaderX.setTimename(run.getTimename());
configureDataReader(page, plot, dataReaderX);
dataReaderY = getVarDataReader(runDir, yVar);
if (dataReaderY == null || dataReaderY.locateVarIndex(yVar.getName()) == -1) {
return series;
}
dataReaderY.setTimename(run.getTimename());
configureDataReader(page, plot, dataReaderY);
try {
String description = getSeriesDescription(runDir.getName(), xVar, yVar);
series = new TrickXYSeries(description, false, true);
series.setDescription(description);
dataReaderX.beginRead(xVar);
dataReaderY.beginRead(yVar);
double xValue = dataReaderX.getVarValue();
double yValue = dataReaderY.getVarValue();
while (!dataReaderX.isEnd() && Double.isNaN(xValue)) {
xValue = dataReaderX.getVarValue();
}
while (!dataReaderY.isEnd() && Double.isNaN(yValue)) {
yValue = dataReaderY.getVarValue();
}
// If either data reader doesn't have time data recorded, then time stamp is
// not a concern. Simply just both x & y as they are.
// If xVar reader's time stamp is bigger, reads more yVar till yVar reader's
// time stamp almost equals to the xVar reader's time stamp and vice versa.
// The xVar and yVar values are added to the series only if their time stamp
// matches within 1e-9. TODO: Is 1e-9 good enough?
while (!Double.isNaN(xValue) && !Double.isNaN(yValue)) {
if (DataReader.nearlyEqual(dataReaderX.getTimeValue(), dataReaderY.getTimeValue()) ||
Double.isNaN(dataReaderX.getTimeValue()) ||
Double.isNaN(dataReaderY.getTimeValue())) {
series.add(xValue, yValue);
xValue = dataReaderX.getVarValue();
yValue = dataReaderY.getVarValue();
} else if (dataReaderX.getTimeValue() > dataReaderY.getTimeValue()) {
yValue = dataReaderY.getVarValue();
} else {
xValue = dataReaderX.getVarValue();
}
}
} catch (FileNotFoundException e) {
System.err.println(e);
} catch (IOException e) {
System.err.println(e);
}
dataReaderX.endRead();
dataReaderY.endRead();
if (series != null) {
series.setXVar(xVar);
series.setYVar(yVar);
}
}
return series;
}
/**
* Configures the reader by applying {@link ProductPage} and {@link ProductPlot} specs.
*/
private static void configureDataReader(ProductPage page, ProductPlot plot, DataReader theReader) {
if (page.getTStart() != null && plot.getTStart() != null) {
if (page.getTStart().doubleValue() > plot.getTStart().doubleValue()) {
theReader.setTStart(page.getTStart());
} else {
theReader.setTStart(plot.getTStart());
}
} else {
if (page.getTStart() != null && plot.getTStart() == null) {
theReader.setTStart(page.getTStart());
} else if (page.getTStart() == null && plot.getTStart() != null) {
theReader.setTStart(plot.getTStart());
} else {
theReader.setTStart(page.getTStart());
}
}
if (page.getTStop() != null && plot.getTStop() != null) {
if (page.getTStop().doubleValue() < plot.getTStop().doubleValue()) {
theReader.setTStop(page.getTStop());
} else {
theReader.setTStop(plot.getTStop());
}
} else {
if (page.getTStop() != null && plot.getTStop() == null) {
theReader.setTStop(page.getTStop());
} else if (page.getTStop() == null && plot.getTStop() != null) {
theReader.setTStop(plot.getTStop());
} else {
theReader.setTStop(page.getTStop());
}
}
}
/**
* Helper method for getting the corresponding reader for the specified variable.
*
* @param runDir The RUN_ dir that contains the recorded data.
* @param var The {@link ProductVar} object which needs getting data for.
*
* @return An instance of {@link DataReader}.
*/
private static DataReader getVarDataReader(File runDir, ProductVar var) {
DataReader theReader = null;
File[] files = UIUtils.getListFiles(runDir, TrickFileFilter.TRICK_DATA_RECORD);
for (int i = 0; i < files.length; i++) {
if (files[i].getPath().endsWith(".csv")) {
theReader = new CSVDataReader(files[i].getPath());
} else if (files[i].getPath().endsWith(".trk")) {
theReader = new BinaryDataReader(files[i].getPath());
} else if (files[i].getPath().endsWith(".h5")) {
// TODO: set up data reader
}
if (theReader == null) {
continue;
}
if (theReader.locateVarIndex(var.getName()) != -1) {
break;
}
}
return theReader;
}
/**
* Makes up the description for a series for the specified X & Y variables.
*/
private static String getSeriesDescription(String runDir, ProductVar xVar, ProductVar yVar) {
// use variable name & units for label for plotting by default
String xVarLabel = xVar.getName() + " (" + xVar.getUnits() + ")";
String yVarLabel = yVar.getName() + " (" + yVar.getUnits() + ")";
// if label for the variable is specified, the specified label is used for plotting instead of its name&units
if (xVar.getLabel() != null && !(xVar.getLabel().isEmpty())) {
xVarLabel = xVar.getLabel();
}
if (yVar.getLabel() != null && !(yVar.getLabel().isEmpty())) {
yVarLabel = yVar.getLabel();
}
return yVarLabel + " VS. " + xVarLabel + " [" + runDir + "]";
}
}

View File

@ -0,0 +1,119 @@
/*
* $Id: TrickChart.java 3795 2015-02-11 19:35:28Z alin $
*/
package trick.dataproducts.plot.utils;
import java.awt.Font;
import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.block.BlockBorder;
import org.jfree.chart.plot.Plot;
public class TrickChart extends JFreeChart {
//========================================
// Public data
//========================================
/** The default font for the primary title. */
public static final Font TRICK_DEFAULT_TITLE_FONT = new Font("SansSerif", Font.BOLD, 12);
/** The default font for sub titles. */
public static final Font TRICK_DEFAULT_SUBTITLE_FONT = new Font("SansSerif", Font.PLAIN, 12);
/** The default font for legend. */
public static final Font TRICK_DEFAULT_LEGEND_FONT = new Font("SansSerif", Font.BOLD, 10);
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
private static final long serialVersionUID = -7190474578193337645L;
//========================================
// Constructors
//========================================
/**
* Creates a new chart based on the supplied plot. The chart will have
* a legend added automatically, but no title (although you can easily add
* one later).
* <br><br>
* Note that the {@link ChartFactory} class contains a range
* of static methods that will return ready-made charts, and often this
* is a more convenient way to create charts than using this constructor.
*
* @param plot the plot (<code>null</code> not permitted).
*/
public TrickChart(Plot plot) {
super(plot);
changeLegend();
setAntiAlias(false);
}
/**
* Creates a new chart with the given title and plot. A default font
* ({@link #DEFAULT_TITLE_FONT}) is used for the title, and the chart will
* have a legend added automatically.
* <br><br>
* Note that the {@link ChartFactory} class contains a range
* of static methods that will return ready-made charts, and often this
* is a more convenient way to create charts than using this constructor.
*
* @param title the chart title (<code>null</code> permitted).
* @param plot the plot (<code>null</code> not permitted).
*/
public TrickChart(String title, Plot plot) {
super(title, plot);
changeLegend();
setAntiAlias(false);
}
/**
* Creates a new chart with the given title and plot. The
* <code>createLegend</code> argument specifies whether or not a legend
* should be added to the chart.
* <br><br>
* Note that the {@link ChartFactory} class contains a range
* of static methods that will return ready-made charts, and often this
* is a more convenient way to create charts than using this constructor.
*
* @param title the chart title (<code>null</code> permitted).
* @param titleFont the font for displaying the chart title
* (<code>null</code> permitted).
* @param plot controller of the visual representation of the data
* (<code>null</code> not permitted).
* @param createLegend a flag indicating whether or not a legend should
* be created for the chart.
*/
public TrickChart(String title, Font titleFont, Plot plot, boolean createLegend) {
super(title, titleFont, plot, createLegend);
if (createLegend) {
changeLegend();
}
setAntiAlias(false);
}
//========================================
// Methods
//========================================
private void changeLegend() {
getLegend().setItemFont(TRICK_DEFAULT_LEGEND_FONT);
getLegend().setFrame(BlockBorder.NONE);
getLegend().setBackgroundPaint(null);
}
/**
* Uses the title of this chart to represent the chart.
*/
@Override
public String toString() {
return getTitle().getText();
}
}

View File

@ -0,0 +1,316 @@
/*
* $Id: TrickChartControlPanel.java 3795 2015-02-11 19:35:28Z alin $
*/
package trick.dataproducts.plot.utils;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.border.EtchedBorder;
import org.jfree.chart.ChartMouseEvent;
import org.jfree.chart.ChartMouseListener;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.annotations.XYPointerAnnotation;
import org.jfree.chart.entity.XYItemEntity;
import org.jfree.chart.event.ChartChangeEvent;
import org.jfree.chart.event.ChartChangeListener;
import org.jfree.chart.event.ChartProgressEvent;
import org.jfree.chart.event.ChartProgressListener;
import org.jfree.chart.panel.CrosshairOverlay;
import org.jfree.chart.plot.Crosshair;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.data.xy.XYDataset;
import org.jfree.ui.Layer;
import org.jfree.ui.RectangleAnchor;
import org.jfree.ui.TextAnchor;
public class TrickChartControlPanel extends JPanel implements ChartChangeListener, ChartMouseListener, ChartProgressListener {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
private JFreeChart trickChart;
private TrickChartPanel chartPanel;
private JPanel controlPanel;
private static final long serialVersionUID = -6328244469933876791L;
private JCheckBox showLegendCheck;
private JCheckBox showGridCheck;
private JCheckBox showCrosshairCheck;
private JButton printButton;
private JButton moreButton;
private JCheckBoxMenuItem showControlCheck;
private int lastSelectedSeries = -1;
private Crosshair crosshairX;
private Crosshair crosshairY;
//========================================
// Constructors
//========================================
/**
* Constructs a panel containing a chart and its control.
* The <code>useBuffer</code> flag controls whether or not an
* offscreen <code>BufferedImage</code> is maintained for the chart.
* If the buffer is used, more memory is consumed, but panel repaints
* will be a lot quicker in cases where the chart itself hasn't
* changed (for example, when another frame is moved to reveal the panel).
*
* WARNING: If you set the <code>useBuffer</code>
* flag to false, note that the mouse zooming rectangle will (in that case)
* be drawn using XOR, and there is a SEVERE performance problem with that
* on JRE6 on Windows.
*
* @param chart the chart.
* @param useBuffer a flag controlling whether or not an off-screen buffer
* is used (read the warning above before setting this
* to <code>false</code>).
*/
public TrickChartControlPanel(JFreeChart chart, boolean useBuffer) {
setLayout(new BorderLayout());
setDoubleBuffered(true);
updateUI();
trickChart = chart;
trickChart.addChangeListener(this);
trickChart.addProgressListener(this);
trickChart.getXYPlot().setRangeCrosshairLockedOnData(false);
trickChart.getXYPlot().setDomainCrosshairLockedOnData(false);
chartPanel = new TrickChartPanel(chart, useBuffer);
chartPanel.setDefaultDirectoryForSaveAs(new File("."));
chartPanel.setMouseWheelEnabled(true);
chartPanel.setAutoscrolls(true);
chartPanel.addChartMouseListener(this);
Border border = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
chartPanel.setBorder(border);
CrosshairOverlay overlay = new CrosshairOverlay();
crosshairX = new Crosshair(0.0);
crosshairX.setVisible(false);
crosshairX.setPaint(Color.red);
crosshairY = new Crosshair(0.0);
crosshairY.setVisible(false);
crosshairY.setPaint(Color.blue);
overlay.addDomainCrosshair(crosshairX);
overlay.addRangeCrosshair(crosshairY);
chartPanel.addOverlay(overlay);
crosshairX.setLabelVisible(true);
crosshairX.setLabelAnchor(RectangleAnchor.BOTTOM_RIGHT);
crosshairX.setLabelBackgroundPaint(new Color(255, 255, 0, 100));
crosshairY.setLabelVisible(true);
crosshairY.setLabelBackgroundPaint(new Color(255, 255, 0, 100));
controlPanel = new JPanel();
setupControls();
controlPanel.add(showLegendCheck);
controlPanel.add(showGridCheck);
controlPanel.add(showCrosshairCheck);
controlPanel.add(printButton);
controlPanel.add(moreButton);
this.add(chartPanel, BorderLayout.CENTER);
this.add(controlPanel, BorderLayout.SOUTH);
showControlCheck = new JCheckBoxMenuItem("Show Control", true);
showControlCheck.addActionListener(new AbstractAction("Show Control") {
private static final long serialVersionUID = -2185831057523724894L;
@Override
public void actionPerformed(ActionEvent e) {
if (showControlCheck.isSelected()) {
controlPanel.setVisible(true);
} else {
controlPanel.setVisible(false);
}
}
});
chartPanel.getPopupMenu().add(showControlCheck);
}
/**
* Sets up all control gui components.
*/
private void setupControls() {
// by default, legend is shown
showLegendCheck = new JCheckBox("Show Legend", true);
showLegendCheck.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (!showLegendCheck.isSelected()) {
trickChart.getLegend().setVisible(false);
} else {
trickChart.getLegend().setVisible(true);
}
}
});
// depending on the DP_ file setting
showGridCheck = new JCheckBox("Show Grid", false);
if (trickChart.getXYPlot().isDomainGridlinesVisible()) {
showGridCheck.setSelected(true);
}
showGridCheck.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (!showGridCheck.isSelected()) {
trickChart.getXYPlot().setRangeGridlinesVisible(false);
trickChart.getXYPlot().setDomainGridlinesVisible(false);
} else {
trickChart.getXYPlot().setRangeGridlinesVisible(true);
trickChart.getXYPlot().setDomainGridlinesVisible(true);
}
}
});
// by default, crosshair is not shown
showCrosshairCheck = new JCheckBox("Show Crosshair", false);
showCrosshairCheck.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (!showCrosshairCheck.isSelected()) {
crosshairX.setVisible(false);
crosshairY.setVisible(false);
} else {
crosshairX.setVisible(true);
crosshairY.setVisible(true);
}
}
});
printButton = new JButton(new AbstractAction("Print...") {
private static final long serialVersionUID = 4694651015847994699L;
@Override
public void actionPerformed(ActionEvent e) {
chartPanel.createChartPrintJob();
}
});
moreButton = new JButton(new AbstractAction("More...") {
private static final long serialVersionUID = 4106804422858015720L;
@Override
public void actionPerformed(ActionEvent e) {
chartPanel.getPopupMenu().show((JButton)e.getSource(), 0, 0);
}
});
}
/**
* Gets the instance of {@link JFreeChart} of this panel.
*
* @return the instance of {@link JFreeChart} which this panel holds.
*/
public JFreeChart getTheChart() {
return trickChart;
}
@Override
public void chartChanged(ChartChangeEvent event) {
}
@Override
public void chartMouseClicked(ChartMouseEvent event) {
/*
* TODO: complete it!
MouseEvent me = event.getTrigger();
if ((me.getModifiers() & MouseEvent.CTRL_MASK) > 0) {
String response = JOptionPane.showInputDialog(this,
"Formula:",
"Curve Formula",
JOptionPane.QUESTION_MESSAGE);
if (response != null && !response.trim().isEmpty()) {
// applyFormulaToPlot();
}
} else if ((me.getModifiers() & MouseEvent.SHIFT_MASK) > 0) {
// manipulateCurve();
}
*/
}
@Override
public void chartProgress(ChartProgressEvent event) {
crosshairX.setValue(trickChart.getXYPlot().getDomainCrosshairValue());
crosshairY.setValue(trickChart.getXYPlot().getRangeCrosshairValue());
}
@Override
public void chartMouseMoved(ChartMouseEvent event) {
XYPlot plot = event.getChart().getXYPlot();
if (event.getEntity() instanceof XYItemEntity) {
XYItemEntity e = (XYItemEntity) (event.getEntity());
XYDataset dataset = e.getDataset();
for (int i = 0; i < plot.getDatasetCount(); i++) {
XYDataset test = plot.getDataset(i);
if (test == dataset) {
XYItemRenderer r = plot.getRenderer(i);
if (r instanceof TrickXYLineAndShapeRenderer) {
TrickXYLineAndShapeRenderer sel = (TrickXYLineAndShapeRenderer) r;
if (lastSelectedSeries != -1) {
r.removeAnnotations();
}
if (sel.isSelectionActive()) {
sel.setSelectedSeries(-1);
sel.setSelectedItem(-1);
} else {
sel.setSelectedSeries(e.getSeriesIndex());
lastSelectedSeries = e.getSeriesIndex();
XYPointerAnnotation annotation = new XYPointerAnnotation(
"series " + e.getSeriesIndex(), test.getXValue(e.getSeriesIndex(), e.getItem()), test.getYValue(e.getSeriesIndex(), e.getItem()), -Math.PI / 4.0);
annotation.setTextAnchor(TextAnchor.BOTTOM_LEFT);
annotation.setPaint(sel.getSeriesPaint(e.getSeriesIndex()));
annotation.setArrowPaint(sel.getSeriesPaint(e.getSeriesIndex()));
plot.getRenderer().addAnnotation(annotation, Layer.BACKGROUND);
}
}
}
}
} else {
if (lastSelectedSeries != -1) {
plot.getRenderer().removeAnnotations();
}
}
}
//========================================
// Inner classes
//========================================
}

View File

@ -0,0 +1,321 @@
/*
* $Id: TrickChartFrame.java 3531 2014-05-16 16:32:51Z hchen3 $
*/
package trick.dataproducts.plot.utils;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.awt.geom.Rectangle2D;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import org.jfree.chart.ChartPanel;
import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.PageSize;
import com.lowagie.text.pdf.BaseFont;
import com.lowagie.text.pdf.DefaultFontMapper;
import com.lowagie.text.pdf.FontMapper;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfTemplate;
import com.lowagie.text.pdf.PdfWriter;
import trick.common.TrickApplication;
import trick.common.ui.UIUtils;
import trick.dataproducts.trickqp.utils.ProductPage;
public class TrickChartFrame extends TrickFrame {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
private static final long serialVersionUID = 1388143913508263815L;
private ArrayList<TrickChartControlPanel> allPanels;
private String pageTitle = "Page";
//========================================
// Constructors
//========================================
/**
* Creates a new, initially invisible <code>Frame</code> with the
* specified title and frame icon if necessary.
* <p>
* This constructor sets the component's locale property to the value
* returned by <code>JComponent.getDefaultLocale</code>.
*
* @param title the title for the frame
* @param iconImage the icon image for the frame and has to set it to null for Mac
* @param thePage the {@link ProductPage} instance that contains page spec
* @param chartList the list of charts that are in the specified the page
*/
public TrickChartFrame(String title, Image iconImage, ProductPage thePage, ArrayList<TrickChart> chartList) throws HeadlessException {
super(title, iconImage);
setMenuBar();
if (fileMenu != null) {
fileMenu.add(new SaveAction("Make PDF", new ImageIcon(TrickApplication.class.getResource("resources/filesave.gif")), "Save Page to PDF", KeyEvent.VK_S));
fileMenu.add(new JSeparator());
JMenuItem closeMenuItem = new JMenuItem(new CloseAction("Close", "Close Plot", KeyEvent.VK_L));
fileMenu.add(closeMenuItem);
}
if (thePage != null && thePage.getTitle() != null) {
pageTitle = thePage.getTitle();
}
setupChart(thePage, chartList);
}
//========================================
// Methods
//========================================
/**
* Helper method for setting up the plot.
*/
private void setupChart(ProductPage thePage, ArrayList<TrickChart> chartList) {
if (chartList == null || chartList.size() < 0) {
return;
}
int chartSize = chartList.size();
allPanels = new ArrayList<TrickChartControlPanel>(chartSize);
JPanel framePanel = getPlotChartFramePanel(thePage, chartSize);
for (TrickChart eachChart : chartList) {
TrickChartControlPanel eachPanel = new TrickChartControlPanel(eachChart, true);
allPanels.add(eachPanel);
framePanel.add(eachPanel);
}
setContentPane(framePanel);
}
/**
* Configures a panel so that it is able to show specified number of charts.
*/
private JPanel getPlotChartFramePanel(ProductPage thePage, int subChartNumber) {
JPanel framePanel = new JPanel();
framePanel.setPreferredSize(new Dimension(ChartPanel.DEFAULT_WIDTH, ChartPanel.DEFAULT_HEIGHT+280));
int numberVCells = 1;
int numberHCells = 1;
if (thePage.getHcells() != null) {
numberHCells = thePage.getHcells().intValue();
}
if (thePage.getVcells() != null) {
numberVCells = thePage.getVcells().intValue();
}
if (subChartNumber > (numberHCells * numberVCells)) {
if (subChartNumber < 9) {
if (subChartNumber == 3) {
numberHCells = 1;
numberVCells = 3;
} else if (subChartNumber == 1) {
numberVCells = 1;
numberHCells = 1;
} else {
numberVCells = 2;
numberHCells = (subChartNumber / 2) + (subChartNumber % 2);
}
} else {
while((numberHCells * numberVCells) < subChartNumber ) {
if (numberHCells <= numberVCells) {
numberHCells++;
} else {
numberVCells++;
}
}
}
}
framePanel.setLayout(new GridLayout(numberVCells, numberHCells));
return framePanel;
}
public String getChartTitle() {
return pageTitle;
}
public int getChartSize() {
if (allPanels != null) {
return allPanels.size();
}
return 0;
}
/**
* Helper method for saving all charts to a PDF file.
* @throws IOException
*/
public void saveChartsAsPDF() throws IOException {
File file = UIUtils.chooseSaveFile(null, "plot_", "pdf", this);
if (file == null) {
return;
}
Document document = new Document(PageSize.A4);
PdfWriter writer = null;
PdfContentByte pdfContent = null;
try {
writer = PdfWriter.getInstance(document, new FileOutputStream(file));
document.open();
pdfContent = writer.getDirectContent();
} catch (DocumentException e) {
e.printStackTrace();
}
writePDFPage(pdfContent, new DefaultFontMapper());
if (document != null) {
document.close();
}
}
/**
* Writes all plots shown to one page of PDF.
*
* @param pdfContent an object containing the user positioned text and graphic contents of a page.
* @param mapper mapping between AWT fonts and PDF fonts.
* @throws IOException
*/
public void writePDFPage(PdfContentByte pdfContent, FontMapper mapper) throws IOException {
if (pdfContent == null) {
return;
}
Document document = pdfContent.getPdfDocument();
int chartLocOffset = 30;
try {
int pageWidth = (int)document.getPageSize().getWidth();
int pageHeight = (int)document.getPageSize().getHeight();
document.newPage();
BaseFont pageTitleFont = BaseFont.createFont(BaseFont.HELVETICA_BOLD, "Cp1252", false);
// show page title text
pdfContent.beginText();
pdfContent.setFontAndSize(pageTitleFont, 12);
pdfContent.showTextAligned(PdfContentByte.ALIGN_CENTER, getChartTitle(), pageWidth / 2 , pageHeight - chartLocOffset / 2, 0);
pdfContent.endText();
// draw all plots
PdfTemplate pdfTemplate = pdfContent.createTemplate(pageWidth, pageHeight);
Graphics2D g2 = pdfTemplate.createGraphics(pageWidth, pageHeight, mapper);
int rows = 1;
int columns = 1;
if (getContentPane().getLayout() instanceof GridLayout) {
rows = ((GridLayout)getContentPane().getLayout()).getRows();
columns = ((GridLayout)getContentPane().getLayout()).getColumns();
}
int eachChartWidth = pageWidth;
int eachChartHeight = pageHeight - chartLocOffset;
if (columns != 0) {
eachChartWidth = pageWidth / columns;
}
if (rows != 0) {
eachChartHeight = (pageHeight - chartLocOffset) / rows;
}
int xLoc = 0;
int yLoc = chartLocOffset;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < columns; j++) {
int index = i * columns + j;
if (index >= getChartSize()) {
break;
}
TrickChartControlPanel eachPanel = (TrickChartControlPanel)getContentPane().getComponent(index);
if (eachPanel.getTheChart() != null) {
Rectangle2D r2D = new Rectangle2D.Double(xLoc, yLoc, eachChartWidth, eachChartHeight);
eachPanel.getTheChart().draw(g2, r2D);
}
xLoc = xLoc + eachChartWidth;
}
xLoc = 0;
yLoc = yLoc + eachChartHeight;
}
g2.dispose();
pdfContent.addTemplate(pdfTemplate, 0, 0);
}
catch (DocumentException de) {
de.printStackTrace();
}
}
/**
* Sets this frame invisible.
*/
private void closeChart() {
setVisible(false);
}
//========================================
// Inner Classes
//========================================
public class SaveAction extends AbstractAction {
private static final long serialVersionUID = 5844945315420458601L;
public SaveAction(String text, ImageIcon icon,
String desc, Integer mnemonic) {
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
public void actionPerformed(ActionEvent e) {
try {
saveChartsAsPDF();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
public class CloseAction extends AbstractAction {
private static final long serialVersionUID = 3077821392818469620L;
public CloseAction(String text, String desc, Integer mnemonic) {
super(text);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
public void actionPerformed(ActionEvent e) {
closeChart();
}
}
}

View File

@ -0,0 +1,50 @@
package trick.dataproducts.plot.utils;
import javax.swing.JOptionPane;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import trick.dataproducts.plot.utils.editor.TrickChartEditor;
import trick.dataproducts.plot.utils.editor.TrickChartEditorManager;
public class TrickChartPanel extends ChartPanel {
private static final long serialVersionUID = -507551123952070511L;
/**
* Constructs a panel containing a chart. The <code>useBuffer</code> flag
* controls whether or not an offscreen <code>BufferedImage</code> is
* maintained for the chart. If the buffer is used, more memory is
* consumed, but panel repaints will be a lot quicker in cases where the
* chart itself hasn't changed (for example, when another frame is moved
* to reveal the panel). WARNING: If you set the <code>useBuffer</code>
* flag to false, note that the mouse zooming rectangle will (in that case)
* be drawn using XOR, and there is a SEVERE performance problem with that
* on JRE6 on Windows.
*
* @param chart the chart.
* @param useBuffer a flag controlling whether or not an off-screen buffer
* is used (read the warning above before setting this
* to <code>false</code>).
*/
public TrickChartPanel(JFreeChart chart, boolean useBuffer) {
super(chart, useBuffer);
}
/**
* Displays a dialog that allows the user to edit the properties for the
* current chart.
*/
@Override
public void doEditChartProperties() {
TrickChartEditor editor = TrickChartEditorManager.getChartEditor(getChart());
int result = JOptionPane.showConfirmDialog(this, editor,
localizationResources.getString("Chart_Properties"),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
editor.updateChart(getChart());
}
}
}

View File

@ -0,0 +1,25 @@
/*
* $Id: TrickChartTheme.java 3107 2013-07-03 18:53:42Z hchen3 $
*/
package trick.dataproducts.plot.utils;
import java.awt.Font;
import org.jfree.chart.StandardChartTheme;
public class TrickChartTheme extends StandardChartTheme {
private static final long serialVersionUID = 4199990670106681300L;
/**
* Creates a new default instance.
*
* @param name the name of the theme (<code>null</code> not permitted).
*/
public TrickChartTheme(String name) {
super(name);
this.setExtraLargeFont(new Font("Tahoma", Font.BOLD, 14));
this.setLargeFont(new Font("Tahoma", Font.BOLD, 12));
}
}

View File

@ -0,0 +1,96 @@
/*
* $Id: TrickFrame.java 3795 2015-02-11 19:35:28Z alin $
*/
package trick.dataproducts.plot.utils;
import java.awt.Component;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.event.KeyEvent;
import javax.swing.Box;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.WindowConstants;
import trick.common.ui.UIUtils;
public class TrickFrame extends JFrame {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
protected JMenu fileMenu = null;
//========================================
// Private Data
//========================================
private static final long serialVersionUID = -2771397837741213286L;
//========================================
// Constructors
//========================================
/**
* Creates a new, initially invisible <code>Frame</code> with the
* specified title and frame icon if necessary.
* <p>
* This constructor sets the component's locale property to the value
* returned by <code>JComponent.getDefaultLocale</code>.
*
* @param title the title for the frame
* @param iconImage the icon image for the frame and has to set it to null for Mac
*
* @exception HeadlessException if GraphicsEnvironment.isHeadless()
* returns true.
* @see java.awt.GraphicsEnvironment#isHeadless
* @see Component#setSize
* @see Component#setVisible
* @see JComponent#getDefaultLocale
*/
public TrickFrame(String title, Image iconImage) throws HeadlessException {
super(title);
setIconImage(iconImage);
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
// Set chartFrame icon to null for Mac to avoid invalid context 0x0 error message
String theOS = System.getProperty("os.name").toLowerCase();
if (theOS.indexOf("mac") != -1) {
setIconImage(null);
}
}
//========================================
// Methods
//========================================
/**
* Helper method for setting up the menu bar if needed.
*/
protected void setMenuBar() {
JMenuBar menuBar = new JMenuBar();
fileMenu = new JMenu("File");
fileMenu.setMnemonic(KeyEvent.VK_F);
menuBar.add(fileMenu);
menuBar.add(Box.createHorizontalGlue());
menuBar.add(UIUtils.getSmallTrickIconLabel());
setJMenuBar(menuBar);
}
@Override
public String toString() {
return getTitle();
}
}

View File

@ -0,0 +1,192 @@
/*
* $Id: TrickTableFrame.java 3496 2014-04-17 19:48:51Z hchen3 $
*/
package trick.dataproducts.plot.utils;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.HeadlessException;
import java.awt.Image;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.io.File;
import javax.swing.AbstractAction;
import javax.swing.ImageIcon;
import javax.swing.JMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JSeparator;
import javax.swing.JTabbedPane;
import javax.swing.JTextPane;
import javax.swing.JViewport;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyleContext;
import javax.swing.text.TabSet;
import javax.swing.text.TabStop;
import javax.swing.text.html.HTMLDocument;
import trick.common.TrickApplication;
import trick.common.ui.UIUtils;
import trick.dataproducts.trickqp.utils.ProductTable;
import trick.dataproducts.utils.Session;
import trick.dataproducts.utils.SessionRun;
public class TrickTableFrame extends TrickFrame {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private data
//========================================
private static final long serialVersionUID = -3151139797020281386L;
/** The pane that holds tables. One tab for one RUN. */
private JTabbedPane framePane;
//========================================
// Constructors
//========================================
/**
* Creates a new, initially invisible <code>Frame</code> with the
* specified title and frame icon image if necessary.
* <p>
* This constructor sets the component's locale property to the value
* returned by <code>JComponent.getDefaultLocale</code>.
*
* @param title the title for the frame
* @param sessionObject the {@link Session} object that contains where the table data is from
* @param theTable the {@link ProductTable} instance that contains the table specs
*
*/
public TrickTableFrame(String title, Image iconImage, Session sessionObject, ProductTable theTable) throws HeadlessException {
super(title, iconImage);
setMenuBar();
if (fileMenu != null) {
fileMenu.add(new SaveAction("Save", new ImageIcon(TrickApplication.class.getResource("resources/filesave.gif")), "Save Table", KeyEvent.VK_S));
fileMenu.add(new JSeparator());
JMenuItem closeMenuItem = new JMenuItem(new CloseAction("Close", "Close Table", KeyEvent.VK_L));
fileMenu.add(closeMenuItem);
}
setupTable(sessionObject, theTable);
}
//========================================
// Methods
//========================================
/**
* Helper method for setting up the table.
*/
private void setupTable(Session sessionObject, ProductTable theTable) {
framePane = new JTabbedPane();
framePane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
for (SessionRun eachRun : sessionObject.getRuns()) {
JTextPane eachTablePane = new JTextPane();
eachTablePane.setEditable(false);
eachTablePane.setPreferredSize(new Dimension(400, 600));
// using HTMLDocument so that the table pane does not performing line wrapping
eachTablePane.setContentType("text/html");
HTMLDocument doc = (HTMLDocument)eachTablePane.getDocument();
// sets tabs setting for the table pane so that all values separated by tabs
// can be aligned as table columns
TabStop[] tabs = new TabStop[theTable.getColumnList().size()];
int tabPixels = 200;
for (int i = 0; i < theTable.getColumnList().size(); i++) {
tabs[i] = new TabStop(tabPixels, TabStop.ALIGN_RIGHT, TabStop.LEAD_EQUALS);
tabPixels += 200;
}
TabSet tabset = new TabSet(tabs);
StyleContext context = StyleContext.getDefaultStyleContext();
AttributeSet attrSet = context.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.TabSet, tabset);
eachTablePane.setParagraphAttributes(attrSet, false);
PlotUtils.insertTableData(eachRun, theTable, doc);
// scroll to top of the pane
eachTablePane.setCaretPosition(0);
framePane.add(eachRun.getDirName(), new JScrollPane(eachTablePane));
}
add(framePane, BorderLayout.CENTER);
}
/**
* Helper method for saving the table data to a text file.
*/
private void saveTable() {
File file = UIUtils.chooseSaveFile(null, "table_", null, this);
if (file != null) {
JViewport viewPort = ((JScrollPane)framePane.getSelectedComponent()).getViewport();
JTextPane selectedPane = (JTextPane)viewPort.getView();
try {
UIUtils.saveTextFile(selectedPane.getDocument().getText(0, selectedPane.getDocument().getLength()), file);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
}
/**
* Sets this frame invisible.
*/
private void closeTable() {
setVisible(false);
}
//========================================
// Inner Classes
//========================================
public class SaveAction extends AbstractAction {
private static final long serialVersionUID = -2005694863569791565L;
public SaveAction(String text, ImageIcon icon,
String desc, Integer mnemonic) {
super(text, icon);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
public void actionPerformed(ActionEvent e) {
saveTable();
}
}
public class CloseAction extends AbstractAction {
private static final long serialVersionUID = 8766852963567400594L;
public CloseAction(String text, String desc, Integer mnemonic) {
super(text);
putValue(SHORT_DESCRIPTION, desc);
putValue(MNEMONIC_KEY, mnemonic);
}
public void actionPerformed(ActionEvent e) {
closeTable();
}
}
}

View File

@ -0,0 +1,57 @@
/*
* $Id: TrickXYLineAndShapeRenderer.java 3795 2015-02-11 19:35:28Z alin $
*/
package trick.dataproducts.plot.utils;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
public class TrickXYLineAndShapeRenderer extends XYLineAndShapeRenderer {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private data
//========================================
private static final long serialVersionUID = -7308381022424004094L;
private int selectedSeries = -1;
private int selectedItem = -1;
//========================================
// Constructors
//========================================
public TrickXYLineAndShapeRenderer() {
super(true, false);
setBaseShapesFilled(false);
}
//========================================
// Set/Get methods
//========================================
public void setSelectedSeries(int series) {
this.selectedSeries = series;
}
public void setSelectedItem(int item) {
this.selectedItem = item;
}
//========================================
// Methods
//========================================
public boolean isSelectionActive() {
return (selectedSeries > -1 && selectedItem > -1);
}
}

View File

@ -0,0 +1,343 @@
/*
* $Id: TrickXYPlot.java 3795 2015-02-11 19:35:28Z alin $
*/
package trick.dataproducts.plot.utils;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Shape;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.labels.StandardXYToolTipGenerator;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.XYPlot;
import org.jfree.data.xy.XYSeriesCollection;
import trick.dataproducts.trickqp.utils.ProductDataPanel;
import trick.dataproducts.trickqp.utils.ProductPage;
import trick.dataproducts.trickqp.utils.ProductPlot;
import trick.dataproducts.trickqp.utils.ProductVar;
/**
* Extends {@link XYPlot} so that Trick plotting specification can
* be applied to the plot.
*
* @author Hong Chen
*
*/
public class TrickXYPlot extends XYPlot {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private Data
//========================================
private static final long serialVersionUID = -3995993644038371850L;
//========================================
// Constructors
//========================================
/**
* Creates a new plot with the specified dataset, axes and renderer
* that is for a particular {@link ProductPage} and {@link ProductPlot}.
*
* @param aPage the {@link ProductPage} which the plot is with.
* @param aPlot the {@link ProductPlot} spec plotting.
* @param dataset the dataset (<code>null</code> permitted).
* @param guiXAxis the domain axis (<code>null</code> permitted).
* @param guiYAxis the range axis (<code>null</code> permitted).
* @param renderer the renderer (<code>null</code> permitted).
*/
public TrickXYPlot(ProductPage aPage,
ProductPlot aPlot,
XYSeriesCollection dataset,
NumberAxis guiXAxis,
NumberAxis guiYAxis,
TrickXYLineAndShapeRenderer renderer) {
super(dataset, guiXAxis, guiYAxis, renderer);
setAxisRange(dataset, guiXAxis, guiYAxis);
// the order of the following calls matters as the lower level of
// specs would override the higher level of specs
applyPageSpec(aPage, guiXAxis, guiYAxis);
applyPlotSpec(aPage, aPlot, dataset, guiXAxis, guiYAxis);
// TODO: applyXVarSpec
applyYVarSpec(dataset, renderer);
setOrientation(PlotOrientation.VERTICAL);
renderer.setBaseToolTipGenerator(new StandardXYToolTipGenerator());
}
//========================================
// Methods
//========================================
/**
* Helper method for setting the range for both X and Y axis.
* The min and max values are based on all series data.
*/
private void setAxisRange(XYSeriesCollection dataset, NumberAxis guiXAxis,
NumberAxis guiYAxis) {
if (dataset == null || dataset.getSeriesCount() < 1) {
return;
}
double minX = dataset.getSeries(0).getMinX();
double maxX = dataset.getSeries(0).getMaxX();
double minY = dataset.getSeries(0).getMinY();
double maxY = dataset.getSeries(0).getMaxY();
for (int i = 1; i < dataset.getSeriesCount(); i++) {
minX = Math.min(minX, dataset.getSeries(i).getMinX());
maxX = Math.max(maxX, dataset.getSeries(i).getMaxX());
minY = Math.min(minY, dataset.getSeries(i).getMinY());
maxY = Math.max(maxY, dataset.getSeries(i).getMaxY());
}
guiXAxis.setRange(minX, maxX);
guiYAxis.setRange(minY, maxY);
}
/**
* Helper method for applying page spec to gui.
*/
private void applyPageSpec(ProductPage aPage, NumberAxis guiXAxis, NumberAxis guiYAxis) {
if (aPage.getForegroundColor() != null) {
guiXAxis.setTickLabelPaint(aPage.getForegroundColor());
guiXAxis.setLabelPaint(aPage.getForegroundColor());
guiYAxis.setTickLabelPaint(aPage.getForegroundColor());
guiYAxis.setLabelPaint(aPage.getForegroundColor());
}
if (aPage.getBackgroundColor() != null) {
setBackgroundPaint(aPage.getBackgroundColor());
}
}
/**
* Helper method for applying plot spec to gui.
*/
private void applyPlotSpec(ProductPage aPage,
ProductPlot aPlot,
XYSeriesCollection dataset,
NumberAxis guiXAxis,
NumberAxis guiYAxis) {
applyPlotXAxisSpec(aPlot, dataset, guiXAxis);
applyPlotYAxisSpec(aPlot, dataset, guiYAxis);
// Plot Start and Stop
// Plot Foreground
if (aPlot.getForegroundColor() != null) {
guiXAxis.setTickLabelPaint(aPlot.getForegroundColor());
guiXAxis.setLabelPaint(aPlot.getForegroundColor());
guiYAxis.setTickLabelPaint(aPlot.getForegroundColor());
guiYAxis.setLabelPaint(aPlot.getForegroundColor());
}
// Plot Background
if (aPlot.getBackgroundColor() != null) {
setBackgroundPaint(aPlot.getBackgroundColor());
}
// Plot Grid and Grid Color
if (aPlot.getGrid().equalsIgnoreCase("Yes")) {
setDomainGridlinesVisible(true);
setRangeGridlinesVisible(true);
if (aPlot.getGridColor() != null) {
setDomainGridlinePaint(aPlot.getGridColor());
setRangeGridlinePaint(aPlot.getGridColor());
}
// use this stroke for both domain and range grid to make it more clear
BasicStroke stroke = new BasicStroke(1.0f, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND);
setDomainGridlineStroke(stroke);
setRangeGridlineStroke(stroke);
} else {
setDomainGridlinesVisible(true);
setRangeGridlinesVisible(true);
}
// Plot Font
if (aPlot.getFont() != null && !(aPlot.getFont().isEmpty())) {
Font plotFont = ProductDataPanel.getFontFromText(aPlot.getFont());
if (plotFont != null) {
guiXAxis.setTickLabelFont(plotFont);
guiXAxis.setLabelFont(plotFont);
guiYAxis.setTickLabelFont(plotFont);
guiYAxis.setLabelFont(plotFont);
}
}
}
/**
* Helper method for applying Y axis spec to gui.
*/
private void applyPlotYAxisSpec(ProductPlot aPlot,
XYSeriesCollection dataset,
NumberAxis guiYAxis) {
// apply Plot Y Axis Label
// if no label provided, the Y variable name is used if they are all the same within the collection
if (aPlot.getYAxis() != null) {
guiYAxis.setLabel(aPlot.getYAxis().getLabel());
} else {
ProductVar theYVar = getYVarFromSeriesCollection(dataset);
if (theYVar != null) {
guiYAxis.setLabel(theYVar.getName());
guiYAxis.setFixedAutoRange(dataset.getSeries(0).getMaxY() - dataset.getSeries(0).getMinY());
}
}
// Y Axis Format
if (aPlot.getYAxis() != null && aPlot.getYAxis().getFormat() != null && !aPlot.getYAxis().getFormat().isEmpty()) {
try {
DecimalFormat newFormat = new DecimalFormat(aPlot.getYAxis().getFormat());
newFormat.setRoundingMode(RoundingMode.HALF_UP);
guiYAxis.setNumberFormatOverride(newFormat);
} catch (IllegalArgumentException iae) {
// do nothing if the provided format is invalid
}
}
if (aPlot.getYMin() != null && aPlot.getYMax() != null) {
guiYAxis.setRange(aPlot.getYMin().doubleValue(), aPlot.getYMax().doubleValue());
} else if (aPlot.getYMin() != null) {
guiYAxis.setRange(aPlot.getYMin().doubleValue(), guiYAxis.getUpperBound());
} else if (aPlot.getYMax() != null) {
guiYAxis.setRange(guiYAxis.getLowerBound(), aPlot.getYMax().doubleValue());
}
}
/**
* Helper method for applying X axis spec to gui.
*/
private void applyPlotXAxisSpec(ProductPlot aPlot,
XYSeriesCollection dataset,
NumberAxis guiXAxis) {
// apply Plot X Axis Label
// if no label provided, the X variable name is used if they are all the same within the collection
if (aPlot.getXAxis() != null) {
guiXAxis.setLabel(aPlot.getXAxis().getLabel());
} else {
ProductVar theXVar = getXVarFromSeriesCollection(dataset);
if (theXVar != null) {
guiXAxis.setLabel(theXVar.getName());
guiXAxis.setFixedAutoRange(dataset.getSeries(0).getMaxX() - dataset.getSeries(0).getMinX());
}
}
if (aPlot.getXMin() != null && aPlot.getXMax() != null) {
guiXAxis.setRange(aPlot.getXMin().doubleValue(), aPlot.getXMax().doubleValue());
} else if (aPlot.getXMin() != null) {
guiXAxis.setRange(aPlot.getXMin().doubleValue(), guiXAxis.getUpperBound());
} else if (aPlot.getXMax() != null) {
guiXAxis.setRange(guiXAxis.getLowerBound(), aPlot.getXMax().doubleValue());
}
}
/**
* Helper method for applying Y variable spec to gui.
*/
private void applyYVarSpec(XYSeriesCollection dataset,
TrickXYLineAndShapeRenderer renderer) {
// Y Var Line Color, Line Style, Symbol Style, Symbol Size
for (int i = 0; i < dataset.getSeriesCount(); i++) {
TrickXYSeries xySeries = null;
if (dataset.getSeries(i) instanceof TrickXYSeries) {
xySeries = (TrickXYSeries)dataset.getSeries(i);
// color
Color lineColor = xySeries.getYVar().getLineColor();
if (lineColor != null) {
renderer.setSeriesPaint(i, lineColor);
}
// style
ProductVar.LineStyle lineStyle = xySeries.getYVar().getLineStyle();
if (lineStyle != null) {
renderer.setSeriesStroke(i, lineStyle.getStroke());
}
// symbol
ProductVar.SymbolStyle symbolStyle = xySeries.getYVar().getSymbolStyle();
Shape symbolShape = xySeries.getYVar().getSymbolShape(symbolStyle);
if (symbolShape != null) {
renderer.setSeriesShapesVisible(i, true);
renderer.setSeriesShape(i, symbolShape);
renderer.setBaseShapesFilled(symbolStyle.isFilled());
} else {
renderer.setSeriesShapesVisible(i, false);
renderer.setBaseShapesFilled(false);
}
}
}
}
/**
* Helper method for getting the same X variable name from the specified {@link XYSeriesCollection}.
*/
private ProductVar getXVarFromSeriesCollection(XYSeriesCollection dataset) {
ProductVar theXVar = null;
if (dataset.getSeriesCount() > 0) {
if (dataset.getSeries(0) instanceof TrickXYSeries) {
theXVar = ((TrickXYSeries)dataset.getSeries(0)).getXVar();
for (int i = 1; i < dataset.getSeriesCount(); i++) {
TrickXYSeries theXYSeries = null;
if (dataset.getSeries(i) instanceof TrickXYSeries) {
theXYSeries = (TrickXYSeries)dataset.getSeries(i);
if (!(theXVar.getName().equals(theXYSeries.getXVar().getName()))) {
theXVar = null;
break;
}
}
}
}
}
return theXVar;
}
/**
* Helper method for getting the same Y variable name from the specified {@link XYSeriesCollection}.
*/
private ProductVar getYVarFromSeriesCollection(XYSeriesCollection dataset) {
ProductVar theYVar = null;
if (dataset.getSeriesCount() > 0) {
if (dataset.getSeries(0) instanceof TrickXYSeries) {
theYVar = ((TrickXYSeries)dataset.getSeries(0)).getYVar();
for (int i = 1; i < dataset.getSeriesCount(); i++) {
TrickXYSeries theXYSeries = null;
if (dataset.getSeries(i) instanceof TrickXYSeries) {
theXYSeries = (TrickXYSeries)dataset.getSeries(i);
if (!(theYVar.getName().equals(theXYSeries.getYVar().getName()))) {
theYVar = null;
break;
}
}
}
}
}
return theYVar;
}
}

View File

@ -0,0 +1,119 @@
/*
* $Id: TrickXYSeries.java 3795 2015-02-11 19:35:28Z alin $
*/
package trick.dataproducts.plot.utils;
import org.jfree.data.xy.XYSeries;
import trick.dataproducts.trickqp.utils.ProductVar;
public class TrickXYSeries extends XYSeries {
//========================================
// Public data
//========================================
//========================================
// Protected data
//========================================
//========================================
// Private data
//========================================
private static final long serialVersionUID = -4137551900938397559L;
private ProductVar xVar;
private ProductVar yVar;
//========================================
// Constructors
//========================================
/**
* Creates a new empty series. By default, items added to the series will
* be sorted into ascending order by x-value, and duplicate x-values will
* be allowed (these defaults can be modified with another constructor.
*
* @param key the series key (<code>null</code> not permitted).
*/
public TrickXYSeries(Comparable key) {
super(key, true, true);
}
/**
* Constructs a new empty series, with the auto-sort flag set as requested,
* and duplicate values allowed.
*
* @param key the series key (<code>null</code> not permitted).
* @param autoSort a flag that controls whether or not the items in the
* series are sorted.
*/
public TrickXYSeries(Comparable key, boolean autoSort) {
super(key, autoSort, true);
}
/**
* Constructs a new xy-series that contains no data. You can specify
* whether or not duplicate x-values are allowed for the series.
*
* @param key the series key (<code>null</code> not permitted).
* @param autoSort a flag that controls whether or not the items in the
* series are sorted.
* @param allowDuplicateXValues a flag that controls whether duplicate
* x-values are allowed.
*/
public TrickXYSeries(Comparable key, boolean autoSort, boolean allowDuplicateXValues) {
super(key, autoSort, allowDuplicateXValues);
}
//========================================
// Set/Get methods
//========================================
/**
* Sets X variable to the specified {@link ProductVar}.
*
* @param x An instance of {@link ProductVar}.
*/
public void setXVar(ProductVar x) {
xVar = x;
}
/**
* Sets Y variable to the specified {@link ProductVar}.
*
* @param y An instance of {@link ProductVar}.
*/
public void setYVar(ProductVar y) {
yVar = y;
}
/**
* Gets X variable.
*
* @return An instance of {@link ProductVar}.
*/
public ProductVar getXVar() {
return xVar;
}
/**
* Gets Y variable.
*
* @return An instance of {@link ProductVar}.
*/
public ProductVar getYVar() {
return yVar;
}
//========================================
// Methods
//========================================
}

View File

@ -0,0 +1,136 @@
/*
* $Id
*/
package trick.dataproducts.plot.utils.editor;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.jfree.chart.axis.Axis;
import org.jfree.chart.axis.LogAxis;
import org.jfree.chart.axis.NumberTickUnit;
/**
* A panel for editing properties of a {@link LogAxis}.
*/
public class DefaultLogAxisEditor extends TrickValueAxisEditor {
private static final long serialVersionUID = -5229846864465910050L;
private double manualTickUnitValue;
private JTextField manualTickUnit;
/**
* Standard constructor: builds a property panel for the specified axis.
*
* @param axis the axis, which should be changed.
*/
public DefaultLogAxisEditor(LogAxis axis) {
super(axis);
this.manualTickUnitValue = axis.getTickUnit().getSize();
manualTickUnit.setText(Double.toString(this.manualTickUnitValue));
}
/**
* Creates a panel for editing the tick unit.
*
* @return A panel.
*/
@Override
protected JPanel createTickUnitPanel() {
JPanel tickUnitPanel = super.createTickUnitPanel();
tickUnitPanel.add(new JLabel(localizationResources.getString(
"Manual_TickUnit_value")));
this.manualTickUnit = new JTextField(Double.toString(
this.manualTickUnitValue));
this.manualTickUnit.setEnabled(!isAutoTickUnitSelection());
this.manualTickUnit.setActionCommand("TickUnitValue");
this.manualTickUnit.addActionListener(this);
this.manualTickUnit.addFocusListener(this);
tickUnitPanel.add(this.manualTickUnit);
tickUnitPanel.add(new JPanel());
return tickUnitPanel;
}
/**
* Handles actions from within the property panel.
*
* @param event an event.
*/
@Override
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (command.equals("TickUnitValue")) {
validateTickUnit();
}
else {
// pass to the super-class for handling
super.actionPerformed(event);
}
}
@Override
public void focusLost(FocusEvent event) {
super.focusLost(event);
if (event.getSource() == this.manualTickUnit) {
validateTickUnit();
}
}
/**
* Toggles the auto-tick-unit setting.
*/
@Override
public void toggleAutoTick() {
super.toggleAutoTick();
if (isAutoTickUnitSelection()) {
this.manualTickUnit.setText(Double.toString(this.manualTickUnitValue));
this.manualTickUnit.setEnabled(false);
}
else {
this.manualTickUnit.setEnabled(true);
}
}
/**
* Validates the tick unit entered.
*/
public void validateTickUnit() {
double newTickUnit;
try {
newTickUnit = Double.parseDouble(this.manualTickUnit.getText());
}
catch (NumberFormatException e) {
newTickUnit = this.manualTickUnitValue;
}
if (newTickUnit > 0.0) {
this.manualTickUnitValue = newTickUnit;
}
this.manualTickUnit.setText(Double.toString(this.manualTickUnitValue));
}
/**
* Sets the properties of the specified axis to match the properties
* defined on this panel.
*
* @param axis the axis.
*/
@Override
public void setAxisProperties(Axis axis) {
super.setAxisProperties(axis);
LogAxis logAxis = (LogAxis) axis;
if (!isAutoTickUnitSelection()) {
logAxis.setTickUnit(new NumberTickUnit(manualTickUnitValue));
}
}
}

View File

@ -0,0 +1,488 @@
/*
* $Id
*/
package trick.dataproducts.plot.utils.editor;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Paint;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ResourceBundle;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import org.jfree.chart.axis.Axis;
import org.jfree.chart.axis.LogAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.util.ResourceBundleWrapper;
import org.jfree.layout.LCBLayout;
import org.jfree.ui.FontChooserPanel;
import org.jfree.ui.FontDisplayField;
import org.jfree.ui.PaintSample;
import org.jfree.ui.RectangleInsets;
/**
* A panel for editing the properties of an axis.
*/
public class TrickAxisEditor extends JPanel implements ActionListener {
/**
*
*/
private static final long serialVersionUID = 5523403058732526022L;
/** The axis label. */
private JTextField label;
/** The label font. */
private Font labelFont;
/** The label paint. */
private PaintSample labelPaintSample;
/** A field showing a description of the label font. */
private JTextField labelFontField;
/** The font for displaying tick labels on the axis. */
private Font tickLabelFont;
/**
* A field containing a description of the font for displaying tick labels
* on the axis.
*/
private JTextField tickLabelFontField;
/** The paint (color) for the tick labels. */
private PaintSample tickLabelPaintSample;
/**
* An empty sub-panel for extending the user interface to handle more
* complex axes.
*/
private JPanel slot1;
/**
* An empty sub-panel for extending the user interface to handle more
* complex axes.
*/
private JPanel slot2;
/** A flag that indicates whether or not the tick labels are visible. */
private JCheckBox showTickLabelsCheckBox;
/** A flag that indicates whether or not the tick marks are visible. */
private JCheckBox showTickMarksCheckBox;
// /** Insets text field. */
// private InsetsTextField tickLabelInsetsTextField;
//
// /** Label insets text field. */
// private InsetsTextField labelInsetsTextField;
/** The tick label insets. */
private RectangleInsets tickLabelInsets;
/** The label insets. */
private RectangleInsets labelInsets;
/** A tabbed pane for... */
private JTabbedPane otherTabs;
/** The resourceBundle for the localization. */
protected static ResourceBundle localizationResources
= ResourceBundleWrapper.getBundle(
"org.jfree.chart.editor.LocalizationBundle");
/**
* A static method that returns a panel that is appropriate for the axis
* type.
*
* @param axis the axis whose properties are to be displayed/edited in
* the panel.
*
* @return A panel or <code>null</code< if axis is <code>null</code>.
*/
public static TrickAxisEditor getInstance(Axis axis) {
if (axis != null) {
// figure out what type of axis we have and instantiate the
// appropriate panel
if (axis instanceof NumberAxis) {
return new TrickNumberAxisEditor((NumberAxis) axis);
}
if (axis instanceof LogAxis) {
return new DefaultLogAxisEditor((LogAxis) axis);
}
else {
return new TrickAxisEditor(axis);
}
}
else {
return null;
}
}
/**
* Standard constructor: builds a panel for displaying/editing the
* properties of the specified axis.
*
* @param axis the axis whose properties are to be displayed/edited in
* the panel.
*/
public TrickAxisEditor(Axis axis) {
this.labelFont = axis.getLabelFont();
this.labelPaintSample = new PaintSample(axis.getLabelPaint());
this.tickLabelFont = axis.getTickLabelFont();
this.tickLabelPaintSample = new PaintSample(axis.getTickLabelPaint());
// Insets values
this.tickLabelInsets = axis.getTickLabelInsets();
this.labelInsets = axis.getLabelInsets();
setLayout(new BorderLayout());
JPanel general = new JPanel(new BorderLayout());
general.setBorder(
BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(),
localizationResources.getString("General")
)
);
JPanel interior = new JPanel(new LCBLayout(5));
interior.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
interior.add(new JLabel(localizationResources.getString("Label")));
this.label = new JTextField(axis.getLabel());
interior.add(this.label);
interior.add(new JPanel());
interior.add(new JLabel(localizationResources.getString("Font")));
this.labelFontField = new FontDisplayField(this.labelFont);
interior.add(this.labelFontField);
JButton b = new JButton(localizationResources.getString("Select..."));
b.setActionCommand("SelectLabelFont");
b.addActionListener(this);
interior.add(b);
interior.add(new JLabel(localizationResources.getString("Paint")));
interior.add(this.labelPaintSample);
b = new JButton(localizationResources.getString("Select..."));
b.setActionCommand("SelectLabelPaint");
b.addActionListener(this);
interior.add(b);
// interior.add(
// new JLabel(localizationResources.getString("Label_Insets"))
// );
// b = new JButton(localizationResources.getString("Edit..."));
// b.setActionCommand("LabelInsets");
// b.addActionListener(this);
// this.labelInsetsTextField = new InsetsTextField(this.labelInsets);
// interior.add(this.labelInsetsTextField);
// interior.add(b);
//
// interior.add(
// new JLabel(localizationResources.getString("Tick_Label_Insets"))
// );
// b = new JButton(localizationResources.getString("Edit..."));
// b.setActionCommand("TickLabelInsets");
// b.addActionListener(this);
// this.tickLabelInsetsTextField
// = new InsetsTextField(this.tickLabelInsets);
// interior.add(this.tickLabelInsetsTextField);
// interior.add(b);
general.add(interior);
add(general, BorderLayout.NORTH);
this.slot1 = new JPanel(new BorderLayout());
JPanel other = new JPanel(new BorderLayout());
other.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(),
localizationResources.getString("Other")));
this.otherTabs = new JTabbedPane();
this.otherTabs.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
JPanel ticks = new JPanel(new LCBLayout(3));
ticks.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
this.showTickLabelsCheckBox = new JCheckBox(
localizationResources.getString("Show_tick_labels"),
axis.isTickLabelsVisible()
);
ticks.add(this.showTickLabelsCheckBox);
ticks.add(new JPanel());
ticks.add(new JPanel());
ticks.add(
new JLabel(localizationResources.getString("Tick_label_font"))
);
this.tickLabelFontField = new FontDisplayField(this.tickLabelFont);
ticks.add(this.tickLabelFontField);
b = new JButton(localizationResources.getString("Select..."));
b.setActionCommand("SelectTickLabelFont");
b.addActionListener(this);
ticks.add(b);
this.showTickMarksCheckBox = new JCheckBox(
localizationResources.getString("Show_tick_marks"),
axis.isTickMarksVisible()
);
ticks.add(this.showTickMarksCheckBox);
ticks.add(new JPanel());
ticks.add(new JPanel());
this.otherTabs.add(localizationResources.getString("Ticks"), ticks);
other.add(this.otherTabs);
this.slot1.add(other);
this.slot2 = new JPanel(new BorderLayout());
this.slot2.add(this.slot1, BorderLayout.NORTH);
add(this.slot2);
}
/**
* Returns the current axis label.
*
* @return The current axis label.
*/
public String getLabel() {
return this.label.getText();
}
/**
* Returns the current label font.
*
* @return The current label font.
*/
public Font getLabelFont() {
return this.labelFont;
}
/**
* Returns the current label paint.
*
* @return The current label paint.
*/
public Paint getLabelPaint() {
return this.labelPaintSample.getPaint();
}
/**
* Returns a flag that indicates whether or not the tick labels are visible.
*
* @return <code>true</code> if ick mark labels are visible.
*/
public boolean isTickLabelsVisible() {
return this.showTickLabelsCheckBox.isSelected();
}
/**
* Returns the font used to draw the tick labels (if they are showing).
*
* @return The font used to draw the tick labels.
*/
public Font getTickLabelFont() {
return this.tickLabelFont;
}
/**
* Returns the current tick label paint.
*
* @return The current tick label paint.
*/
public Paint getTickLabelPaint() {
return this.tickLabelPaintSample.getPaint();
}
/**
* Returns the current value of the flag that determines whether or not
* tick marks are visible.
*
* @return <code>true</code> if tick marks are visible.
*/
public boolean isTickMarksVisible() {
return this.showTickMarksCheckBox.isSelected();
}
/**
* Returns the current tick label insets value
*
* @return The current tick label insets value.
*/
public RectangleInsets getTickLabelInsets() {
return (this.tickLabelInsets == null)
? new RectangleInsets(0, 0, 0, 0)
: this.tickLabelInsets;
}
/**
* Returns the current label insets value
*
* @return The current label insets value.
*/
public RectangleInsets getLabelInsets() {
return (this.labelInsets == null)
? new RectangleInsets(0, 0, 0, 0) : this.labelInsets;
}
/**
* Returns a reference to the tabbed pane.
*
* @return A reference to the tabbed pane.
*/
public JTabbedPane getOtherTabs() {
return this.otherTabs;
}
/**
* Handles user interaction with the property panel.
*
* @param event information about the event that triggered the call to
* this method.
*/
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (command.equals("SelectLabelFont")) {
attemptLabelFontSelection();
}
else if (command.equals("SelectLabelPaint")) {
attemptModifyLabelPaint();
}
else if (command.equals("SelectTickLabelFont")) {
attemptTickLabelFontSelection();
}
// else if (command.equals("LabelInsets")) {
// editLabelInsets();
// }
// else if (command.equals("TickLabelInsets")) {
// editTickLabelInsets();
// }
}
/**
* Presents a font selection dialog to the user.
*/
private void attemptLabelFontSelection() {
FontChooserPanel panel = new FontChooserPanel(this.labelFont);
int result = JOptionPane.showConfirmDialog(this, panel,
localizationResources.getString("Font_Selection"),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
this.labelFont = panel.getSelectedFont();
this.labelFontField.setText(
this.labelFont.getFontName() + " " + this.labelFont.getSize()
);
}
}
/**
* Allows the user the opportunity to change the outline paint.
*/
private void attemptModifyLabelPaint() {
Color initialColor = (labelPaintSample.getPaint() instanceof Color ? (Color)labelPaintSample.getPaint() : Color.blue);
Color c = JColorChooser.showDialog(this, localizationResources.getString("Label_Color"), initialColor);
if (c != null) {
this.labelPaintSample.setPaint(c);
}
}
/**
* Presents a tick label font selection dialog to the user.
*/
public void attemptTickLabelFontSelection() {
FontChooserPanel panel = new FontChooserPanel(this.tickLabelFont);
int result = JOptionPane.showConfirmDialog(this, panel,
localizationResources.getString("Font_Selection"),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
this.tickLabelFont = panel.getSelectedFont();
this.tickLabelFontField.setText(
this.tickLabelFont.getFontName() + " "
+ this.tickLabelFont.getSize()
);
}
}
// /**
// * Presents insets chooser panel allowing user to modify tick label's
// * individual insets values. Updates the current insets text field if
// * edit is accepted.
// */
// private void editTickLabelInsets() {
// InsetsChooserPanel panel = new InsetsChooserPanel(
// this.tickLabelInsets);
// int result = JOptionPane.showConfirmDialog(
// this, panel, localizationResources.getString("Edit_Insets"),
// JOptionPane.PLAIN_MESSAGE
// );
//
// if (result == JOptionPane.OK_OPTION) {
// this.tickLabelInsets = panel.getInsets();
// this.tickLabelInsetsTextField.setInsets(this.tickLabelInsets);
// }
// }
//
// /**
// * Presents insets chooser panel allowing user to modify label's
// * individual insets values. Updates the current insets text field if edit
// * is accepted.
// */
// private void editLabelInsets() {
// InsetsChooserPanel panel = new InsetsChooserPanel(this.labelInsets);
// int result = JOptionPane.showConfirmDialog(
// this, panel, localizationResources.getString("Edit_Insets"),
// JOptionPane.PLAIN_MESSAGE
// );
//
// if (result == JOptionPane.OK_OPTION) {
// this.labelInsets = panel.getInsets();
// this.labelInsetsTextField.setInsets(this.labelInsets);
// }
// }
/**
* Sets the properties of the specified axis to match the properties
* defined on this panel.
*
* @param axis the axis.
*/
public void setAxisProperties(Axis axis) {
axis.setLabel(getLabel());
axis.setLabelFont(getLabelFont());
axis.setLabelPaint(getLabelPaint());
axis.setTickMarksVisible(isTickMarksVisible());
// axis.setTickMarkStroke(getTickMarkStroke());
axis.setTickLabelsVisible(isTickLabelsVisible());
axis.setTickLabelFont(getTickLabelFont());
axis.setTickLabelPaint(getTickLabelPaint());
axis.setTickLabelInsets(getTickLabelInsets());
axis.setLabelInsets(getLabelInsets());
}
}

View File

@ -0,0 +1,301 @@
/*
* $Id: TrickChartEditor.java 3349 2013-12-17 15:05:20Z hchen3 $
*/
package trick.dataproducts.plot.utils.editor;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Paint;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.ArrayList;
import java.util.ResourceBundle;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.editor.ChartEditor;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PolarPlot;
import org.jfree.chart.title.Title;
import org.jfree.chart.util.ResourceBundleWrapper;
import org.jfree.layout.LCBLayout;
import org.jfree.ui.PaintSample;
import org.jfree.ui.StrokeChooserPanel;
import org.jfree.ui.StrokeSample;
import trick.dataproducts.trickqp.utils.ProductVar;
/**
* A panel for editing chart properties (includes subpanels for the title,
* legend and plot).
*/
public class TrickChartEditor extends JPanel implements ActionListener, ChartEditor {
private static final long serialVersionUID = -513746078897898843L;
/** A panel for displaying/editing the properties of the title. */
private TrickTitleEditor titleEditor;
/** A panel for displaying/editing the properties of the plot. */
private TrickPlotEditor plotEditor;
/**
* A checkbox indicating whether or not the chart is drawn with
* anti-aliasing.
*/
private JCheckBox antialias;
/** The chart background color. */
private PaintSample background;
/** The chart plot series color. */
private ArrayList<PaintSample> seriesPaintList;
/** The chart plot series color. */
private ArrayList<StrokeSample> seriesStrokeList;
/** The resourceBundle for the localization. */
protected static ResourceBundle localizationResources
= ResourceBundleWrapper.getBundle(
"org.jfree.chart.editor.LocalizationBundle");
private static StrokeSample[] AVAILABLE_STROKE_SAMPLES = new StrokeSample[ProductVar.LineStyle.values().length];
static {
for (int i = 0; i < ProductVar.LineStyle.values().length; i++) {
AVAILABLE_STROKE_SAMPLES[i] = new StrokeSample(ProductVar.LineStyle.values()[i].getStroke());
}
}
/**
* Standard constructor - the property panel is made up of a number of
* sub-panels that are displayed in the tabbed pane.
*
* @param chart the chart, which properties should be changed.
*/
public TrickChartEditor(JFreeChart chart) {
setLayout(new BorderLayout());
JPanel other = new JPanel(new BorderLayout());
other.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
JPanel general = new JPanel(new BorderLayout());
general.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(),
localizationResources.getString("General")));
JPanel interior = new JPanel(new LCBLayout(4));
interior.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
this.antialias = new JCheckBox(localizationResources.getString(
"Draw_anti-aliased"));
this.antialias.setSelected(chart.getAntiAlias());
interior.add(this.antialias);
interior.add(new JLabel(""));
interior.add(new JLabel(""));
interior.add(new JLabel(localizationResources.getString(
"Background_paint")));
this.background = new PaintSample(chart.getBackgroundPaint());
interior.add(this.background);
JButton button = new JButton(localizationResources.getString(
"Select..."));
button.setActionCommand("BackgroundPaint");
button.addActionListener(this);
interior.add(button);
interior.add(new JLabel(localizationResources.getString(
"Series_Paint")));
new JTextField(localizationResources.getString(
"No_editor_implemented"));
int seriesCount = chart.getXYPlot().getSeriesCount();
JPanel seriesPaintPanel = new JPanel(new GridLayout(0, 3, 1, 1));
seriesPaintList = new ArrayList<PaintSample>(seriesCount);
for (int i = 0; i < seriesCount; i++) {
PaintSample aPaintSample = new PaintSample(chart.getXYPlot().getRenderer().getSeriesPaint(i));
seriesPaintList.add(i, aPaintSample);
seriesPaintPanel.add(seriesPaintList.get(i));
aPaintSample.addMouseListener(new LocalMouseListener());
}
interior.add(seriesPaintPanel);
interior.add(new JLabel(""));
interior.add(new JLabel(localizationResources.getString(
"Series_Stroke")));
JPanel seriesStrokePanel = new JPanel(new GridLayout(0, 3, 1, 1));
seriesStrokeList = new ArrayList<StrokeSample>(seriesCount);
for (int i = 0; i < seriesCount; i++) {
StrokeSample aStrokeSample = new StrokeSample(chart.getXYPlot().getRenderer().getSeriesStroke(i));
seriesStrokeList.add(i, aStrokeSample);
seriesStrokePanel.add(seriesStrokeList.get(i));
aStrokeSample.addMouseListener(new LocalMouseListener());
}
interior.add(seriesStrokePanel);
interior.add(new JLabel(""));
general.add(interior, BorderLayout.NORTH);
other.add(general, BorderLayout.NORTH);
JPanel parts = new JPanel(new BorderLayout());
Title title = chart.getTitle();
Plot plot = chart.getPlot();
JTabbedPane tabs = new JTabbedPane();
this.titleEditor = new TrickTitleEditor(title);
this.titleEditor.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
tabs.addTab(localizationResources.getString("Title"), this.titleEditor);
if (plot instanceof PolarPlot) {
this.plotEditor = new TrickPolarPlotEditor((PolarPlot) plot);
}
else {
this.plotEditor = new TrickPlotEditor(plot);
}
this.plotEditor.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
tabs.addTab(localizationResources.getString("Plot"), this.plotEditor);
tabs.add(localizationResources.getString("Other"), other);
parts.add(tabs, BorderLayout.NORTH);
add(parts);
}
/**
* Returns a reference to the title editor.
*
* @return A panel for editing the title.
*/
public TrickTitleEditor getTitleEditor() {
return this.titleEditor;
}
/**
* Returns a reference to the plot property sub-panel.
*
* @return A panel for editing the plot properties.
*/
public TrickPlotEditor getPlotEditor() {
return this.plotEditor;
}
/**
* Returns the current setting of the anti-alias flag.
*
* @return <code>true</code> if anti-aliasing is enabled.
*/
public boolean getAntiAlias() {
return this.antialias.isSelected();
}
/**
* Returns the current background paint.
*
* @return The current background paint.
*/
public Paint getBackgroundPaint() {
return this.background.getPaint();
}
/**
* Handles user interactions with the panel.
*
* @param event a BackgroundPaint action.
*/
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (command.equals("BackgroundPaint")) {
attemptModifyBackgroundPaint();
}
}
/**
* Allows the user the opportunity to select a new background paint. Uses
* JColorChooser, so we are only allowing a subset of all Paint objects to
* be selected (fix later).
*/
private void attemptModifyBackgroundPaint() {
Color initialColor = (background.getPaint() instanceof Color ? (Color)background.getPaint() : Color.blue);
Color c = JColorChooser.showDialog(this, localizationResources.getString("Background_Color"), initialColor);
if (c != null) {
this.background.setPaint(c);
}
}
/**
* Updates the properties of a chart to match the properties defined on the
* panel.
*
* @param chart the chart.
*/
public void updateChart(JFreeChart chart) {
this.titleEditor.setTitleProperties(chart);
this.plotEditor.updatePlotProperties(chart.getPlot());
chart.setAntiAlias(getAntiAlias());
chart.setBackgroundPaint(getBackgroundPaint());
for (int i = 0; i < chart.getXYPlot().getSeriesCount(); i++) {
chart.getXYPlot().getRenderer().setSeriesPaint(i, seriesPaintList.get(i).getPaint());
chart.getXYPlot().getRenderer().setSeriesStroke(i, seriesStrokeList.get(i).getStroke());
}
}
/**
* Allow the user to change the outline stroke.
*/
private void attemptStrokeSelection(StrokeSample sample) {
StrokeChooserPanel panel = new StrokeChooserPanel(
sample, AVAILABLE_STROKE_SAMPLES);
int result = JOptionPane.showConfirmDialog(this, panel,
localizationResources.getString("Stroke_Selection"),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
sample.setStroke(panel.getSelectedStroke());
}
}
public class LocalMouseListener extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
if (!seriesPaintList.isEmpty()) {
for (PaintSample theSample : seriesPaintList) {
if (e.getSource().equals(theSample)) {
Color initialColor = (theSample.getPaint() instanceof Color ? (Color)theSample.getPaint() : Color.blue);
Color c = JColorChooser.showDialog(theSample, "Change Paint Color", initialColor);
if (c != null) {
theSample.setPaint(c);
}
}
}
}
if (!seriesStrokeList.isEmpty()) {
for (StrokeSample theSample : seriesStrokeList) {
if (e.getSource().equals(theSample)) {
attemptStrokeSelection(theSample);
}
}
}
}
}
}

View File

@ -0,0 +1,33 @@
/*
* $Id
*/
package trick.dataproducts.plot.utils.editor;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.editor.ChartEditor;
import org.jfree.chart.editor.ChartEditorFactory;
/**
* A default implementation of the {@link ChartEditorFactory} interface.
*/
public class TrickChartEditorFactory implements ChartEditorFactory {
/**
* Creates a new instance.
*/
public TrickChartEditorFactory() {
}
/**
* Returns a new instance of a {@link ChartEditor}.
*
* @param chart the chart.
*
* @return A chart editor for the given chart.
*/
public TrickChartEditor createEditor(JFreeChart chart) {
return new TrickChartEditor(chart);
}
}

View File

@ -0,0 +1,58 @@
/*
* $Id
*/
package trick.dataproducts.plot.utils.editor;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.editor.ChartEditor;
import org.jfree.chart.util.ParamChecks;
/**
* The central point for obtaining {@link ChartEditor} instances for editing
* charts. Right now, the API is minimal - the plan is to extend this class
* to provide customization options for chart editors (for example, make some
* editor items read-only).
*/
public class TrickChartEditorManager {
/** This factory creates new {@link ChartEditor} instances as required. */
static TrickChartEditorFactory factory = new TrickChartEditorFactory();
/**
* Private constructor prevents instantiation.
*/
private TrickChartEditorManager() {
// nothing to do
}
/**
* Returns the current factory.
*
* @return The current factory (never <code>null</code>).
*/
public static TrickChartEditorFactory getChartEditorFactory() {
return factory;
}
/**
* Sets the chart editor factory.
*
* @param f the new factory (<code>null</code> not permitted).
*/
public static void setChartEditorFactory(TrickChartEditorFactory f) {
ParamChecks.nullNotPermitted(f, "f");
factory = f;
}
/**
* Returns a component that can be used to edit the given chart.
*
* @param chart the chart.
*
* @return The chart editor.
*/
public static TrickChartEditor getChartEditor(JFreeChart chart) {
return factory.createEditor(chart);
}
}

View File

@ -0,0 +1,144 @@
/*
* $Id
*/
package trick.dataproducts.plot.utils.editor;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.jfree.chart.axis.Axis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.layout.LCBLayout;
/**
* A panel for editing the properties of a value axis.
*/
public class TrickNumberAxisEditor extends TrickValueAxisEditor
implements FocusListener {
private static final long serialVersionUID = 651540823473853902L;
private double manualTickUnitValue;
private JTextField manualTickUnit;
/**
* Standard constructor: builds a property panel for the specified axis.
*
* @param axis the axis, which should be changed.
*/
public TrickNumberAxisEditor(NumberAxis axis) {
super(axis);
this.manualTickUnitValue = axis.getTickUnit().getSize();
validateTickUnit();
}
@Override
protected JPanel createTickUnitPanel()
{
JPanel tickUnitPanel = new JPanel(new LCBLayout(3));
tickUnitPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
tickUnitPanel.add(new JPanel());
JCheckBox autoTickUnitSelectionCheckBox = new JCheckBox(
localizationResources.getString("Auto-TickUnit_Selection"),
isAutoTickUnitSelection());
autoTickUnitSelectionCheckBox.setActionCommand("AutoTickOnOff");
autoTickUnitSelectionCheckBox.addActionListener(this);
setAutoTickUnitSelectionCheckBox(autoTickUnitSelectionCheckBox);
tickUnitPanel.add(getAutoTickUnitSelectionCheckBox());
tickUnitPanel.add(new JPanel());
tickUnitPanel.add(new JLabel(localizationResources.getString(
"Manual_TickUnit_value")));
this.manualTickUnit = new JTextField(Double.toString(
this.manualTickUnitValue));
this.manualTickUnit.setEnabled(!isAutoTickUnitSelection());
this.manualTickUnit.setActionCommand("TickUnitValue");
this.manualTickUnit.addActionListener(this);
this.manualTickUnit.addFocusListener(this);
tickUnitPanel.add(this.manualTickUnit);
tickUnitPanel.add(new JPanel());
return tickUnitPanel;
}
/**
* Handles actions from within the property panel.
* @param event an event.
*/
@Override
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (command.equals("TickUnitValue")) {
validateTickUnit();
}
else {
// pass to the super-class for handling
super.actionPerformed(event);
}
}
@Override
public void focusLost(FocusEvent event) {
super.focusLost(event);
if (event.getSource() == this.manualTickUnit) {
validateTickUnit();
}
}
@Override
public void toggleAutoTick() {
super.toggleAutoTick();
if (isAutoTickUnitSelection()) {
this.manualTickUnit.setText(Double.toString(this.manualTickUnitValue));
this.manualTickUnit.setEnabled(false);
}
else {
this.manualTickUnit.setEnabled(true);
}
}
public void validateTickUnit() {
double newTickUnit;
try {
newTickUnit = Double.parseDouble(this.manualTickUnit.getText());
}
catch (NumberFormatException e) {
newTickUnit = this.manualTickUnitValue;
}
if (newTickUnit > 0.0) {
this.manualTickUnitValue = newTickUnit;
}
this.manualTickUnit.setText(Double.toString(this.manualTickUnitValue));
}
/**
* Sets the properties of the specified axis to match the properties
* defined on this panel.
*
* @param axis the axis.
*/
@Override
public void setAxisProperties(Axis axis) {
super.setAxisProperties(axis);
NumberAxis numberAxis = (NumberAxis) axis;
if (!isAutoTickUnitSelection()) {
numberAxis.setTickUnit(new NumberTickUnit(manualTickUnitValue));
}
}
}

View File

@ -0,0 +1,629 @@
/*
* $Id
*/
package trick.dataproducts.plot.utils.editor;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Paint;
import java.awt.Stroke;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ResourceBundle;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import org.jfree.chart.axis.Axis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.plot.PolarPlot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.category.CategoryItemRenderer;
import org.jfree.chart.renderer.category.LineAndShapeRenderer;
import org.jfree.chart.renderer.xy.StandardXYItemRenderer;
import org.jfree.chart.renderer.xy.XYItemRenderer;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.util.ResourceBundleWrapper;
import org.jfree.layout.LCBLayout;
import org.jfree.ui.PaintSample;
import org.jfree.ui.RectangleInsets;
import org.jfree.ui.StrokeChooserPanel;
import org.jfree.ui.StrokeSample;
import org.jfree.util.BooleanUtilities;
/**
* A panel for editing the properties of a {@link Plot}.
*/
public class TrickPlotEditor extends JPanel implements ActionListener {
private static final long serialVersionUID = -6751169039890765522L;
/** Orientation constants. */
private final static String[] orientationNames = {"Vertical", "Horizontal"};
private final static int ORIENTATION_VERTICAL = 0;
private final static int ORIENTATION_HORIZONTAL = 1;
/** The paint (color) used to fill the background of the plot. */
private PaintSample backgroundPaintSample;
/** The stroke used to draw the outline of the plot. */
private StrokeSample outlineStrokeSample;
/** The paint (color) used to draw the outline of the plot. */
private PaintSample outlinePaintSample;
/**
* A panel used to display/edit the properties of the domain axis (if any).
*/
private TrickAxisEditor domainAxisPropertyPanel;
/**
* A panel used to display/edit the properties of the range axis (if any).
*/
private TrickAxisEditor rangeAxisPropertyPanel;
/** An array of stroke samples to choose from. */
private StrokeSample[] availableStrokeSamples;
/** The insets for the plot. */
private RectangleInsets plotInsets;
/**
* The orientation for the plot (for <tt>CategoryPlot</tt>s and
* <tt>XYPlot</tt>s).
*/
private PlotOrientation plotOrientation;
/**
* The orientation combo box (for <tt>CategoryPlot</tt>s and
* <tt>XYPlot</tt>s).
*/
private JComboBox orientationCombo;
/** Whether or not to draw lines between each data point (for
* <tt>LineAndShapeRenderer</tt>s and <tt>StandardXYItemRenderer</tt>s).
*/
private Boolean drawLines;
/**
* The checkbox for whether or not to draw lines between each data point.
*/
private JCheckBox drawLinesCheckBox;
/** Whether or not to draw shapes at each data point (for
* <tt>LineAndShapeRenderer</tt>s and <tt>StandardXYItemRenderer</tt>s).
*/
private Boolean drawShapes;
/**
* The checkbox for whether or not to draw shapes at each data point.
*/
private JCheckBox drawShapesCheckBox;
/** The resourceBundle for the localization. */
protected static ResourceBundle localizationResources
= ResourceBundleWrapper.getBundle(
"org.jfree.chart.editor.LocalizationBundle");
/**
* Standard constructor - constructs a panel for editing the properties of
* the specified plot.
* <P>
* In designing the panel, we need to be aware that subclasses of Plot will
* need to implement subclasses of PlotPropertyEditPanel - so we need to
* leave one or two 'slots' where the subclasses can extend the user
* interface.
*
* @param plot the plot, which should be changed.
*/
public TrickPlotEditor(Plot plot) {
JPanel panel = createPlotPanel(plot);
add(panel);
}
@SuppressWarnings({ "rawtypes", "unchecked" })
protected JPanel createPlotPanel(Plot plot) {
this.plotInsets = plot.getInsets();
this.backgroundPaintSample = new PaintSample(plot.getBackgroundPaint());
this.outlineStrokeSample = new StrokeSample(plot.getOutlineStroke());
this.outlinePaintSample = new PaintSample(plot.getOutlinePaint());
if (plot instanceof CategoryPlot) {
this.plotOrientation = ((CategoryPlot) plot).getOrientation();
}
else if (plot instanceof XYPlot) {
this.plotOrientation = ((XYPlot) plot).getOrientation();
}
if (plot instanceof CategoryPlot) {
CategoryItemRenderer renderer = ((CategoryPlot) plot).getRenderer();
if (renderer instanceof LineAndShapeRenderer) {
LineAndShapeRenderer r = (LineAndShapeRenderer) renderer;
this.drawLines = BooleanUtilities.valueOf(
r.getBaseLinesVisible());
this.drawShapes = BooleanUtilities.valueOf(
r.getBaseShapesVisible());
}
}
else if (plot instanceof XYPlot) {
XYItemRenderer renderer = ((XYPlot) plot).getRenderer();
if (renderer instanceof StandardXYItemRenderer) {
StandardXYItemRenderer r = (StandardXYItemRenderer) renderer;
this.drawLines = BooleanUtilities.valueOf(r.getPlotLines());
this.drawShapes = BooleanUtilities.valueOf(r.getBaseShapesVisible());
} else if (renderer instanceof XYLineAndShapeRenderer) {
XYLineAndShapeRenderer r = (XYLineAndShapeRenderer) renderer;
this.drawLines = BooleanUtilities.valueOf(r.getBaseLinesVisible());
this.drawShapes = BooleanUtilities.valueOf(r.getBaseShapesVisible());
}
}
setLayout(new BorderLayout());
this.availableStrokeSamples = new StrokeSample[4];
this.availableStrokeSamples[0] = new StrokeSample(null);
this.availableStrokeSamples[1] = new StrokeSample(
new BasicStroke(1.0f));
this.availableStrokeSamples[2] = new StrokeSample(
new BasicStroke(2.0f));
this.availableStrokeSamples[3] = new StrokeSample(
new BasicStroke(3.0f));
// create a panel for the settings...
JPanel panel = new JPanel(new BorderLayout());
panel.setBorder(BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(), plot.getPlotType()
+ localizationResources.getString(":")));
JPanel general = new JPanel(new BorderLayout());
general.setBorder(BorderFactory.createTitledBorder(
localizationResources.getString("General")));
JPanel interior = new JPanel(new LCBLayout(7));
interior.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
// interior.add(new JLabel(localizationResources.getString("Insets")));
// JButton button = new JButton(
// localizationResources.getString("Edit...")
// );
// button.setActionCommand("Insets");
// button.addActionListener(this);
//
// this.insetsTextField = new InsetsTextField(this.plotInsets);
// this.insetsTextField.setEnabled(false);
// interior.add(this.insetsTextField);
// interior.add(button);
interior.add(new JLabel(localizationResources.getString(
"Outline_stroke")));
JButton button = new JButton(localizationResources.getString(
"Select..."));
button.setActionCommand("OutlineStroke");
button.addActionListener(this);
interior.add(this.outlineStrokeSample);
interior.add(button);
interior.add(new JLabel(localizationResources.getString(
"Outline_Paint")));
button = new JButton(localizationResources.getString("Select..."));
button.setActionCommand("OutlinePaint");
button.addActionListener(this);
interior.add(this.outlinePaintSample);
interior.add(button);
interior.add(new JLabel(localizationResources.getString(
"Background_paint")));
button = new JButton(localizationResources.getString("Select..."));
button.setActionCommand("BackgroundPaint");
button.addActionListener(this);
interior.add(this.backgroundPaintSample);
interior.add(button);
if (this.plotOrientation != null) {
boolean isVertical = this.plotOrientation.equals(
PlotOrientation.VERTICAL);
int index = isVertical ? ORIENTATION_VERTICAL
: ORIENTATION_HORIZONTAL;
interior.add(new JLabel(localizationResources.getString(
"Orientation")));
this.orientationCombo = new JComboBox(orientationNames);
this.orientationCombo.setSelectedIndex(index);
this.orientationCombo.setActionCommand("Orientation");
this.orientationCombo.addActionListener(this);
interior.add(new JPanel());
interior.add(this.orientationCombo);
}
if (this.drawLines != null) {
interior.add(new JLabel(localizationResources.getString(
"Draw_lines")));
this.drawLinesCheckBox = new JCheckBox();
this.drawLinesCheckBox.setSelected(this.drawLines.booleanValue());
this.drawLinesCheckBox.setActionCommand("DrawLines");
this.drawLinesCheckBox.addActionListener(this);
interior.add(new JPanel());
interior.add(this.drawLinesCheckBox);
}
if (this.drawShapes != null) {
interior.add(new JLabel(localizationResources.getString(
"Draw_shapes")));
this.drawShapesCheckBox = new JCheckBox();
this.drawShapesCheckBox.setSelected(this.drawShapes.booleanValue());
this.drawShapesCheckBox.setActionCommand("DrawShapes");
this.drawShapesCheckBox.addActionListener(this);
interior.add(new JPanel());
interior.add(this.drawShapesCheckBox);
}
general.add(interior, BorderLayout.NORTH);
JPanel appearance = new JPanel(new BorderLayout());
appearance.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
appearance.add(general, BorderLayout.NORTH);
JTabbedPane tabs = createPlotTabs(plot);
tabs.add(localizationResources.getString("Appearance"), appearance);
panel.add(tabs);
return panel;
}
protected JTabbedPane createPlotTabs(Plot plot)
{
JTabbedPane tabs = new JTabbedPane();
tabs.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
Axis domainAxis = null;
if (plot instanceof CategoryPlot) {
domainAxis = ((CategoryPlot) plot).getDomainAxis();
}
else if (plot instanceof XYPlot) {
domainAxis = ((XYPlot) plot).getDomainAxis();
}
this.domainAxisPropertyPanel = TrickAxisEditor.getInstance(
domainAxis);
if (this.domainAxisPropertyPanel != null) {
this.domainAxisPropertyPanel.setBorder(
BorderFactory.createEmptyBorder(2, 2, 2, 2));
tabs.add(localizationResources.getString("Domain_Axis"),
this.domainAxisPropertyPanel);
}
Axis rangeAxis = null;
if (plot instanceof CategoryPlot) {
rangeAxis = ((CategoryPlot) plot).getRangeAxis();
}
else if (plot instanceof XYPlot) {
rangeAxis = ((XYPlot) plot).getRangeAxis();
}
else if (plot instanceof PolarPlot) {
rangeAxis = ((PolarPlot) plot).getAxis();
}
this.rangeAxisPropertyPanel = TrickAxisEditor.getInstance(rangeAxis);
if (this.rangeAxisPropertyPanel != null) {
this.rangeAxisPropertyPanel.setBorder(
BorderFactory.createEmptyBorder(2, 2, 2, 2));
tabs.add(localizationResources.getString("Range_Axis"),
this.rangeAxisPropertyPanel);
}
//dmo: added this panel for colorbar control. (start dmo additions)
/*ColorBar colorBar = null;
if (plot instanceof ContourPlot) {
colorBar = ((ContourPlot) plot).getColorBar();
}
this.colorBarAxisPropertyPanel = TrickColorBarEditor.getInstance(
colorBar);
if (this.colorBarAxisPropertyPanel != null) {
this.colorBarAxisPropertyPanel.setBorder(
BorderFactory.createEmptyBorder(2, 2, 2, 2));
tabs.add(localizationResources.getString("Color_Bar"),
this.colorBarAxisPropertyPanel);
}
//dmo: (end dmo additions)
*/
return tabs;
}
/**
* Returns the current plot insets.
*
* @return The current plot insets.
*/
public RectangleInsets getPlotInsets() {
if (this.plotInsets == null) {
this.plotInsets = new RectangleInsets(0.0, 0.0, 0.0, 0.0);
}
return this.plotInsets;
}
/**
* Returns the current background paint.
*
* @return The current background paint.
*/
public Paint getBackgroundPaint() {
return this.backgroundPaintSample.getPaint();
}
/**
* Returns the current outline stroke.
*
* @return The current outline stroke (possibly <code>null</code>).
*/
public Stroke getOutlineStroke() {
return this.outlineStrokeSample.getStroke();
}
/**
* Returns the current outline paint.
*
* @return The current outline paint.
*/
public Paint getOutlinePaint() {
return this.outlinePaintSample.getPaint();
}
/**
* Returns a reference to the panel for editing the properties of the
* domain axis.
*
* @return A reference to a panel.
*/
public TrickAxisEditor getDomainAxisPropertyEditPanel() {
return this.domainAxisPropertyPanel;
}
/**
* Returns a reference to the panel for editing the properties of the
* range axis.
*
* @return A reference to a panel.
*/
public TrickAxisEditor getRangeAxisPropertyEditPanel() {
return this.rangeAxisPropertyPanel;
}
/**
* Handles user actions generated within the panel.
* @param event the event
*/
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (command.equals("BackgroundPaint")) {
attemptBackgroundPaintSelection();
}
else if (command.equals("OutlineStroke")) {
attemptOutlineStrokeSelection();
}
else if (command.equals("OutlinePaint")) {
attemptOutlinePaintSelection();
}
// else if (command.equals("Insets")) {
// editInsets();
// }
else if (command.equals("Orientation")) {
attemptOrientationSelection();
}
else if (command.equals("DrawLines")) {
attemptDrawLinesSelection();
}
else if (command.equals("DrawShapes")) {
attemptDrawShapesSelection();
}
}
/**
* Allow the user to change the background paint.
*/
private void attemptBackgroundPaintSelection() {
Color initialColor = (backgroundPaintSample.getPaint() instanceof Color ? (Color)backgroundPaintSample.getPaint() : Color.blue);
Color c = JColorChooser.showDialog(this, localizationResources.getString("Background_Color"), initialColor);
if (c != null) {
this.backgroundPaintSample.setPaint(c);
}
}
/**
* Allow the user to change the outline stroke.
*/
private void attemptOutlineStrokeSelection() {
StrokeChooserPanel panel = new StrokeChooserPanel(
this.outlineStrokeSample, this.availableStrokeSamples);
int result = JOptionPane.showConfirmDialog(this, panel,
localizationResources.getString("Stroke_Selection"),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
this.outlineStrokeSample.setStroke(panel.getSelectedStroke());
}
}
/**
* Allow the user to change the outline paint. We use JColorChooser, so
* the user can only choose colors (a subset of all possible paints).
*/
private void attemptOutlinePaintSelection() {
Color initialColor = (outlinePaintSample.getPaint() instanceof Color ? (Color)outlinePaintSample.getPaint() : Color.blue);
Color c= JColorChooser.showDialog(this, localizationResources.getString("Outline_Color"), initialColor);
if (c != null) {
this.outlinePaintSample.setPaint(c);
}
}
// /**
// * Allow the user to edit the individual insets' values.
// */
// private void editInsets() {
// InsetsChooserPanel panel = new InsetsChooserPanel(this.plotInsets);
// int result = JOptionPane.showConfirmDialog(
// this, panel, localizationResources.getString("Edit_Insets"),
// JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE
// );
//
// if (result == JOptionPane.OK_OPTION) {
// this.plotInsets = panel.getInsets();
// this.insetsTextField.setInsets(this.plotInsets);
// }
//
// }
//
/**
* Allow the user to modify the plot orientation if this is an editor for a
* <tt>CategoryPlot</tt> or a <tt>XYPlot</tt>.
*/
private void attemptOrientationSelection() {
int index = this.orientationCombo.getSelectedIndex();
if (index == ORIENTATION_VERTICAL) {
this.plotOrientation = PlotOrientation.VERTICAL;
}
else {
this.plotOrientation = PlotOrientation.HORIZONTAL;
}
}
/**
* Allow the user to modify whether or not lines are drawn between data
* points by <tt>LineAndShapeRenderer</tt>s and
* <tt>StandardXYItemRenderer</tt>s.
*/
private void attemptDrawLinesSelection() {
this.drawLines = BooleanUtilities.valueOf(
this.drawLinesCheckBox.isSelected());
}
/**
* Allow the user to modify whether or not shapes are drawn at data points
* by <tt>LineAndShapeRenderer</tt>s and <tt>StandardXYItemRenderer</tt>s.
*/
private void attemptDrawShapesSelection() {
this.drawShapes = BooleanUtilities.valueOf(
this.drawShapesCheckBox.isSelected());
}
/**
* Updates the plot properties to match the properties defined on the panel.
*
* @param plot The plot.
*/
public void updatePlotProperties(Plot plot) {
// set the plot properties...
plot.setOutlinePaint(getOutlinePaint());
plot.setOutlineStroke(getOutlineStroke());
plot.setBackgroundPaint(getBackgroundPaint());
plot.setInsets(getPlotInsets());
// then the axis properties...
if (this.domainAxisPropertyPanel != null) {
Axis domainAxis = null;
if (plot instanceof CategoryPlot) {
CategoryPlot p = (CategoryPlot) plot;
domainAxis = p.getDomainAxis();
}
else if (plot instanceof XYPlot) {
XYPlot p = (XYPlot) plot;
domainAxis = p.getDomainAxis();
}
if (domainAxis != null) {
this.domainAxisPropertyPanel.setAxisProperties(domainAxis);
}
}
if (this.rangeAxisPropertyPanel != null) {
Axis rangeAxis = null;
if (plot instanceof CategoryPlot) {
CategoryPlot p = (CategoryPlot) plot;
rangeAxis = p.getRangeAxis();
}
else if (plot instanceof XYPlot) {
XYPlot p = (XYPlot) plot;
rangeAxis = p.getRangeAxis();
}
else if (plot instanceof PolarPlot) {
PolarPlot p = (PolarPlot) plot;
rangeAxis = p.getAxis();
}
if (rangeAxis != null) {
this.rangeAxisPropertyPanel.setAxisProperties(rangeAxis);
}
}
if (this.plotOrientation != null) {
if (plot instanceof CategoryPlot) {
CategoryPlot p = (CategoryPlot) plot;
p.setOrientation(this.plotOrientation);
}
else if (plot instanceof XYPlot) {
XYPlot p = (XYPlot) plot;
p.setOrientation(this.plotOrientation);
}
}
if (this.drawLines != null) {
if (plot instanceof CategoryPlot) {
CategoryPlot p = (CategoryPlot) plot;
CategoryItemRenderer r = p.getRenderer();
if (r instanceof LineAndShapeRenderer) {
((LineAndShapeRenderer) r).setBaseLinesVisible(this.drawLines.booleanValue());
}
}
else if (plot instanceof XYPlot) {
XYPlot p = (XYPlot) plot;
XYItemRenderer r = p.getRenderer();
if (r instanceof StandardXYItemRenderer) {
((StandardXYItemRenderer) r).setPlotLines(this.drawLines.booleanValue());
} else if (r instanceof XYLineAndShapeRenderer) {
((XYLineAndShapeRenderer) r).setBaseLinesVisible(this.drawLines.booleanValue());
}
}
}
if (this.drawShapes != null) {
if (plot instanceof CategoryPlot) {
CategoryPlot p = (CategoryPlot) plot;
CategoryItemRenderer r = p.getRenderer();
if (r instanceof LineAndShapeRenderer) {
((LineAndShapeRenderer) r).setBaseShapesVisible(this.drawShapes.booleanValue());
}
}
else if (plot instanceof XYPlot) {
XYPlot p = (XYPlot) plot;
XYItemRenderer r = p.getRenderer();
if (r instanceof StandardXYItemRenderer) {
((StandardXYItemRenderer) r).setBaseShapesVisible(this.drawShapes.booleanValue());
} else if (r instanceof XYLineAndShapeRenderer) {
((XYLineAndShapeRenderer) r).setBaseShapesVisible(this.drawShapes.booleanValue());
}
}
}
/*
//dmo: added this panel for colorbar control. (start dmo additions)
if (this.colorBarAxisPropertyPanel != null) {
ColorBar colorBar = null;
if (plot instanceof ContourPlot) {
ContourPlot p = (ContourPlot) plot;
colorBar = p.getColorBar();
}
if (colorBar != null) {
this.colorBarAxisPropertyPanel.setAxisProperties(colorBar);
}
}
//dmo: (end dmo additions)
*/
}
}

View File

@ -0,0 +1,179 @@
/*
* $Id
*/
package trick.dataproducts.plot.utils.editor;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import javax.swing.BorderFactory;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import org.jfree.chart.axis.NumberTickUnit;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PolarPlot;
import org.jfree.layout.LCBLayout;
/**
* A panel for editing the properties of a {@link PolarPlot}.
*/
public class TrickPolarPlotEditor extends TrickPlotEditor
implements FocusListener {
private static final long serialVersionUID = 436737477629003049L;
/** A text field to enter a manual TickUnit. */
private JTextField manualTickUnit;
/** A text field to enter the angleOffset. */
private JTextField angleOffset;
/** The size for the manual TickUnit. */
private double manualTickUnitValue;
/** The value for the plot's angle offset. */
private double angleOffsetValue;
/**
* Standard constructor - constructs a panel for editing the properties of
* the specified plot.
*
* @param plot the plot, which should be changed.
*/
public TrickPolarPlotEditor(PolarPlot plot) {
super(plot);
this.angleOffsetValue = plot.getAngleOffset();
this.angleOffset.setText(Double.toString(this.angleOffsetValue));
this.manualTickUnitValue = plot.getAngleTickUnit().getSize();
this.manualTickUnit.setText(Double.toString(this.manualTickUnitValue));
}
/**
* Creates a tabbed pane for editing the plot attributes.
*
* @param plot the plot.
*
* @return A tabbed pane.
*/
@Override
protected JTabbedPane createPlotTabs(Plot plot) {
JTabbedPane tabs = super.createPlotTabs(plot);
// TODO find a better localization key
tabs.insertTab(localizationResources.getString("General1"), null, createPlotPanel(), null, 0);
tabs.setSelectedIndex(0);
return tabs;
}
private JPanel createPlotPanel() {
JPanel plotPanel = new JPanel(new LCBLayout(3));
plotPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
plotPanel.add(new JLabel(localizationResources.getString(
"AngleOffset")));
this.angleOffset = new JTextField(Double.toString(
this.angleOffsetValue));
this.angleOffset.setActionCommand("AngleOffsetValue");
this.angleOffset.addActionListener(this);
this.angleOffset.addFocusListener(this);
plotPanel.add(this.angleOffset);
plotPanel.add(new JPanel());
plotPanel.add(new JLabel(localizationResources.getString(
"Manual_TickUnit_value")));
this.manualTickUnit = new JTextField(Double.toString(
this.manualTickUnitValue));
this.manualTickUnit.setActionCommand("TickUnitValue");
this.manualTickUnit.addActionListener(this);
this.manualTickUnit.addFocusListener(this);
plotPanel.add(this.manualTickUnit);
plotPanel.add(new JPanel());
return plotPanel;
}
/**
* Does nothing.
*
* @param event the event.
*/
public void focusGained(FocusEvent event) {
// don't need to do anything
}
/**
* Revalidates minimum/maximum range.
*
* @param event the event.
*/
public void focusLost(FocusEvent event) {
if (event.getSource() == this.angleOffset) {
validateAngleOffset();
}
else if (event.getSource() == this.manualTickUnit) {
validateTickUnit();
}
}
/**
* Handles actions from within the property panel.
* @param event an event.
*/
@Override
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (command.equals("AngleOffsetValue")) {
validateAngleOffset();
}
else if (command.equals("TickUnitValue")) {
validateTickUnit();
}
}
/**
* Validates the angle offset entered by the user.
*/
public void validateAngleOffset() {
double newOffset;
try {
newOffset = Double.parseDouble(this.angleOffset.getText());
}
catch (NumberFormatException e) {
newOffset = this.angleOffsetValue;
}
this.angleOffsetValue = newOffset;
this.angleOffset.setText(Double.toString(this.angleOffsetValue));
}
/**
* Validates the tick unit entered by the user.
*/
public void validateTickUnit() {
double newTickUnit;
try {
newTickUnit = Double.parseDouble(this.manualTickUnit.getText());
}
catch (NumberFormatException e) {
newTickUnit = this.manualTickUnitValue;
}
if (newTickUnit > 0.0 && newTickUnit < 360.0) {
this.manualTickUnitValue = newTickUnit;
}
this.manualTickUnit.setText(Double.toString(this.manualTickUnitValue));
}
@Override
public void updatePlotProperties(Plot plot) {
super.updatePlotProperties(plot);
PolarPlot pp = (PolarPlot) plot;
pp.setAngleTickUnit(new NumberTickUnit(this.manualTickUnitValue));
pp.setAngleOffset(this.angleOffsetValue);
}
}

View File

@ -0,0 +1,267 @@
/*
* $Id
*/
package trick.dataproducts.plot.utils.editor;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Paint;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ResourceBundle;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.title.TextTitle;
import org.jfree.chart.title.Title;
import org.jfree.chart.util.ResourceBundleWrapper;
import org.jfree.layout.LCBLayout;
import org.jfree.ui.FontChooserPanel;
import org.jfree.ui.FontDisplayField;
import org.jfree.ui.PaintSample;
/**
* A panel for editing the properties of a chart title.
*/
public class TrickTitleEditor extends JPanel implements ActionListener {
private static final long serialVersionUID = 7434968517978830476L;
/** Whether or not to display the title on the chart. */
private boolean showTitle;
/** The checkbox to indicate whether or not to display the title. */
private JCheckBox showTitleCheckBox;
/** A field for displaying/editing the title text. */
private JTextField titleField;
/** The font used to draw the title. */
private Font titleFont;
/** A field for displaying a description of the title font. */
private JTextField fontfield;
/** The button to use to select a new title font. */
private JButton selectFontButton;
/** The paint (color) used to draw the title. */
private PaintSample titlePaint;
/** The button to use to select a new paint (color) to draw the title. */
private JButton selectPaintButton;
/** The resourceBundle for the localization. */
protected static ResourceBundle localizationResources
= ResourceBundleWrapper.getBundle(
"org.jfree.chart.editor.LocalizationBundle");
/**
* Standard constructor: builds a panel for displaying/editing the
* properties of the specified title.
*
* @param title the title, which should be changed.
*/
public TrickTitleEditor(Title title) {
TextTitle t = (title != null ? (TextTitle) title
: new TextTitle(localizationResources.getString("Title")));
this.showTitle = (title != null);
this.titleFont = t.getFont();
this.titleField = new JTextField(t.getText());
this.titlePaint = new PaintSample(t.getPaint());
setLayout(new BorderLayout());
JPanel general = new JPanel(new BorderLayout());
general.setBorder(
BorderFactory.createTitledBorder(
BorderFactory.createEtchedBorder(),
localizationResources.getString("General")
)
);
JPanel interior = new JPanel(new LCBLayout(4));
interior.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
interior.add(new JLabel(localizationResources.getString("Show_Title")));
this.showTitleCheckBox = new JCheckBox();
this.showTitleCheckBox.setSelected(this.showTitle);
this.showTitleCheckBox.setActionCommand("ShowTitle");
this.showTitleCheckBox.addActionListener(this);
interior.add(new JPanel());
interior.add(this.showTitleCheckBox);
JLabel titleLabel = new JLabel(localizationResources.getString("Text"));
interior.add(titleLabel);
interior.add(this.titleField);
interior.add(new JPanel());
JLabel fontLabel = new JLabel(localizationResources.getString("Font"));
this.fontfield = new FontDisplayField(this.titleFont);
this.selectFontButton = new JButton(
localizationResources.getString("Select...")
);
this.selectFontButton.setActionCommand("SelectFont");
this.selectFontButton.addActionListener(this);
interior.add(fontLabel);
interior.add(this.fontfield);
interior.add(this.selectFontButton);
JLabel colorLabel = new JLabel(
localizationResources.getString("Color")
);
this.selectPaintButton = new JButton(
localizationResources.getString("Select...")
);
this.selectPaintButton.setActionCommand("SelectPaint");
this.selectPaintButton.addActionListener(this);
interior.add(colorLabel);
interior.add(this.titlePaint);
interior.add(this.selectPaintButton);
this.enableOrDisableControls();
general.add(interior);
add(general, BorderLayout.NORTH);
}
/**
* Returns the title text entered in the panel.
*
* @return The title text entered in the panel.
*/
public String getTitleText() {
return this.titleField.getText();
}
/**
* Returns the font selected in the panel.
*
* @return The font selected in the panel.
*/
public Font getTitleFont() {
return this.titleFont;
}
/**
* Returns the paint selected in the panel.
*
* @return The paint selected in the panel.
*/
public Paint getTitlePaint() {
return this.titlePaint.getPaint();
}
/**
* Handles button clicks by passing control to an appropriate handler
* method.
*
* @param event the event
*/
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (command.equals("SelectFont")) {
attemptFontSelection();
}
else if (command.equals("SelectPaint")) {
attemptPaintSelection();
}
else if (command.equals("ShowTitle")) {
attemptModifyShowTitle();
}
}
/**
* Presents a font selection dialog to the user.
*/
public void attemptFontSelection() {
FontChooserPanel panel = new FontChooserPanel(this.titleFont);
int result =
JOptionPane.showConfirmDialog(
this, panel, localizationResources.getString("Font_Selection"),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE
);
if (result == JOptionPane.OK_OPTION) {
this.titleFont = panel.getSelectedFont();
this.fontfield.setText(
this.titleFont.getFontName() + " " + this.titleFont.getSize()
);
}
}
/**
* Allow the user the opportunity to select a Paint object. For now, we
* just use the standard color chooser - all colors are Paint objects, but
* not all Paint objects are colors (later we can implement a more general
* Paint chooser).
*/
public void attemptPaintSelection() {
Paint p = this.titlePaint.getPaint();
Color defaultColor = (p instanceof Color ? (Color) p : Color.blue);
Color c = JColorChooser.showDialog(
this, localizationResources.getString("Title_Color"), defaultColor
);
if (c != null) {
this.titlePaint.setPaint(c);
}
}
/**
* Allow the user the opportunity to change whether the title is
* displayed on the chart or not.
*/
private void attemptModifyShowTitle() {
this.showTitle = this.showTitleCheckBox.isSelected();
this.enableOrDisableControls();
}
/**
* If we are supposed to show the title, the controls are enabled.
* If we are not supposed to show the title, the controls are disabled.
*/
private void enableOrDisableControls() {
boolean enabled = (this.showTitle == true);
this.titleField.setEnabled(enabled);
this.selectFontButton.setEnabled(enabled);
this.selectPaintButton.setEnabled(enabled);
}
/**
* Sets the properties of the specified title to match the properties
* defined on this panel.
*
* @param chart the chart whose title is to be modified.
*/
public void setTitleProperties(JFreeChart chart) {
if (this.showTitle) {
TextTitle title = chart.getTitle();
if (title == null) {
title = new TextTitle();
chart.setTitle(title);
}
title.setText(getTitleText());
title.setFont(getTitleFont());
title.setPaint(getTitlePaint());
}
else {
chart.setTitle((TextTitle) null);
}
}
}

View File

@ -0,0 +1,384 @@
/*
* $Id
*/
package trick.dataproducts.plot.utils.editor;
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.util.ResourceBundle;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JColorChooser;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.JTextField;
import org.jfree.chart.axis.Axis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.util.ResourceBundleWrapper;
import org.jfree.layout.LCBLayout;
import org.jfree.ui.PaintSample;
import org.jfree.ui.StrokeChooserPanel;
import org.jfree.ui.StrokeSample;
/**
* A panel for editing properties of a {@link ValueAxis}.
*/
public class TrickValueAxisEditor extends TrickAxisEditor
implements FocusListener {
private static final long serialVersionUID = -8568989539318482713L;
/** A flag that indicates whether or not the axis range is determined
* automatically.
*/
private boolean autoRange;
/** Flag if auto-tickunit-selection is enabled. */
private boolean autoTickUnitSelection;
/** The lowest value in the axis range. */
private double minimumValue;
/** The highest value in the axis range. */
private double maximumValue;
/** A checkbox that indicates whether or not the axis range is determined
* automatically.
*/
private JCheckBox autoRangeCheckBox;
/** A check-box enabling/disabling auto-tickunit-selection. */
private JCheckBox autoTickUnitSelectionCheckBox;
/** A text field for entering the minimum value in the axis range. */
private JTextField minimumRangeValue;
/** A text field for entering the maximum value in the axis range. */
private JTextField maximumRangeValue;
/** The paint selected for drawing the gridlines. */
private PaintSample gridPaintSample;
/** The stroke selected for drawing the gridlines. */
private StrokeSample gridStrokeSample;
/** An array of stroke samples to choose from (since I haven't written a
* decent StrokeChooser component yet).
*/
private StrokeSample[] availableStrokeSamples;
/** The resourceBundle for the localization. */
protected static ResourceBundle localizationResources
= ResourceBundleWrapper.getBundle(
"org.jfree.chart.editor.LocalizationBundle");
/**
* Standard constructor: builds a property panel for the specified axis.
*
* @param axis the axis, which should be changed.
*/
public TrickValueAxisEditor(ValueAxis axis) {
super(axis);
this.autoRange = axis.isAutoRange();
this.minimumValue = axis.getLowerBound();
this.maximumValue = axis.getUpperBound();
this.autoTickUnitSelection = axis.isAutoTickUnitSelection();
this.gridPaintSample = new PaintSample(Color.blue);
this.gridStrokeSample = new StrokeSample(new BasicStroke(1.0f));
this.availableStrokeSamples = new StrokeSample[3];
this.availableStrokeSamples[0] = new StrokeSample(
new BasicStroke(1.0f));
this.availableStrokeSamples[1] = new StrokeSample(
new BasicStroke(2.0f));
this.availableStrokeSamples[2] = new StrokeSample(
new BasicStroke(3.0f));
JTabbedPane other = getOtherTabs();
JPanel range = new JPanel(new LCBLayout(3));
range.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
range.add(new JPanel());
this.autoRangeCheckBox = new JCheckBox(localizationResources.getString(
"Auto-adjust_range"), this.autoRange);
this.autoRangeCheckBox.setActionCommand("AutoRangeOnOff");
this.autoRangeCheckBox.addActionListener(this);
range.add(this.autoRangeCheckBox);
range.add(new JPanel());
range.add(new JLabel(localizationResources.getString(
"Minimum_range_value")));
this.minimumRangeValue = new JTextField(Double.toString(
this.minimumValue));
this.minimumRangeValue.setEnabled(!this.autoRange);
this.minimumRangeValue.setActionCommand("MinimumRange");
this.minimumRangeValue.addActionListener(this);
this.minimumRangeValue.addFocusListener(this);
range.add(this.minimumRangeValue);
range.add(new JPanel());
range.add(new JLabel(localizationResources.getString(
"Maximum_range_value")));
this.maximumRangeValue = new JTextField(Double.toString(
this.maximumValue));
this.maximumRangeValue.setEnabled(!this.autoRange);
this.maximumRangeValue.setActionCommand("MaximumRange");
this.maximumRangeValue.addActionListener(this);
this.maximumRangeValue.addFocusListener(this);
range.add(this.maximumRangeValue);
range.add(new JPanel());
other.add(localizationResources.getString("Range"), range);
other.add(localizationResources.getString("TickUnit"),
createTickUnitPanel());
}
protected JPanel createTickUnitPanel() {
JPanel tickUnitPanel = new JPanel(new LCBLayout(3));
tickUnitPanel.setBorder(BorderFactory.createEmptyBorder(4, 4, 4, 4));
tickUnitPanel.add(new JPanel());
this.autoTickUnitSelectionCheckBox = new JCheckBox(
localizationResources.getString("Auto-TickUnit_Selection"),
this.autoTickUnitSelection);
this.autoTickUnitSelectionCheckBox.setActionCommand("AutoTickOnOff");
this.autoTickUnitSelectionCheckBox.addActionListener(this);
tickUnitPanel.add(this.autoTickUnitSelectionCheckBox);
tickUnitPanel.add(new JPanel());
return tickUnitPanel;
}
/**
* Getter for the {@link #autoTickUnitSelection} flag.
*
* @return The value of the flag for enabling auto-tickunit-selection.
*/
protected boolean isAutoTickUnitSelection() {
return autoTickUnitSelection;
}
/**
* Setter for the {@link #autoTickUnitSelection} flag.
* @param autoTickUnitSelection The new value for auto-tickunit-selection.
*/
protected void setAutoTickUnitSelection(boolean autoTickUnitSelection) {
this.autoTickUnitSelection = autoTickUnitSelection;
}
/**
* Get the checkbox that enables/disables auto-tickunit-selection.
*
* @return The checkbox.
*/
protected JCheckBox getAutoTickUnitSelectionCheckBox() {
return autoTickUnitSelectionCheckBox;
}
/**
* Set the checkbox that enables/disables auto-tickunit-selection.
*
* @param autoTickUnitSelectionCheckBox The checkbox.
*/
protected void setAutoTickUnitSelectionCheckBox(
JCheckBox autoTickUnitSelectionCheckBox) {
this.autoTickUnitSelectionCheckBox = autoTickUnitSelectionCheckBox;
}
/**
* Returns the current setting of the auto-range property.
*
* @return <code>true</code> if auto range is enabled.
*/
public boolean isAutoRange() {
return this.autoRange;
}
/**
* Returns the current setting of the minimum value in the axis range.
*
* @return The current setting of the minimum value in the axis range.
*/
public double getMinimumValue() {
return this.minimumValue;
}
/**
* Returns the current setting of the maximum value in the axis range.
*
* @return The current setting of the maximum value in the axis range.
*/
public double getMaximumValue() {
return this.maximumValue;
}
/**
* Handles actions from within the property panel.
* @param event an event.
*/
@Override
public void actionPerformed(ActionEvent event) {
String command = event.getActionCommand();
if (command.equals("GridStroke")) {
attemptGridStrokeSelection();
}
else if (command.equals("GridPaint")) {
attemptGridPaintSelection();
}
else if (command.equals("AutoRangeOnOff")) {
toggleAutoRange();
}
else if (command.equals("MinimumRange")) {
validateMinimum();
}
else if (command.equals("MaximumRange")) {
validateMaximum();
}
else if (command.equals("AutoTickOnOff")) {
toggleAutoTick();
}
else {
// pass to the super-class for handling
super.actionPerformed(event);
}
}
/**
* Handle a grid stroke selection.
*/
protected void attemptGridStrokeSelection() {
StrokeChooserPanel panel = new StrokeChooserPanel(this.gridStrokeSample,
this.availableStrokeSamples);
int result = JOptionPane.showConfirmDialog(this, panel,
localizationResources.getString("Stroke_Selection"),
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
if (result == JOptionPane.OK_OPTION) {
this.gridStrokeSample.setStroke(panel.getSelectedStroke());
}
}
/**
* Handle a grid paint selection.
*/
protected void attemptGridPaintSelection() {
Color initialColor = (gridPaintSample.getPaint() instanceof Color ? (Color)gridPaintSample.getPaint() : Color.blue);
Color c = JColorChooser.showDialog(this, localizationResources.getString("Grid_Color"), initialColor);
if (c != null) {
this.gridPaintSample.setPaint(c);
}
}
/**
* Does nothing.
*
* @param event the event.
*/
public void focusGained(FocusEvent event) {
// don't need to do anything
}
/**
* Revalidates minimum/maximum range.
*
* @param event the event.
*/
public void focusLost(FocusEvent event) {
if (event.getSource() == this.minimumRangeValue) {
validateMinimum();
}
else if (event.getSource() == this.maximumRangeValue) {
validateMaximum();
}
}
/**
* Toggle the auto range setting.
*/
public void toggleAutoRange() {
this.autoRange = this.autoRangeCheckBox.isSelected();
if (this.autoRange) {
this.minimumRangeValue.setText(Double.toString(this.minimumValue));
this.minimumRangeValue.setEnabled(false);
this.maximumRangeValue.setText(Double.toString(this.maximumValue));
this.maximumRangeValue.setEnabled(false);
}
else {
this.minimumRangeValue.setEnabled(true);
this.maximumRangeValue.setEnabled(true);
}
}
public void toggleAutoTick() {
this.autoTickUnitSelection = this.autoTickUnitSelectionCheckBox.isSelected();
}
/**
* Revalidate the range minimum.
*/
public void validateMinimum() {
double newMin;
try {
newMin = Double.parseDouble(this.minimumRangeValue.getText());
if (newMin >= this.maximumValue) {
newMin = this.minimumValue;
}
}
catch (NumberFormatException e) {
newMin = this.minimumValue;
}
this.minimumValue = newMin;
this.minimumRangeValue.setText(Double.toString(this.minimumValue));
}
/**
* Revalidate the range maximum.
*/
public void validateMaximum() {
double newMax;
try {
newMax = Double.parseDouble(this.maximumRangeValue.getText());
if (newMax <= this.minimumValue) {
newMax = this.maximumValue;
}
}
catch (NumberFormatException e) {
newMax = this.maximumValue;
}
this.maximumValue = newMax;
this.maximumRangeValue.setText(Double.toString(this.maximumValue));
}
/**
* Sets the properties of the specified axis to match the properties
* defined on this panel.
*
* @param axis the axis.
*/
@Override
public void setAxisProperties(Axis axis) {
super.setAxisProperties(axis);
ValueAxis valueAxis = (ValueAxis) axis;
valueAxis.setAutoRange(this.autoRange);
if (!this.autoRange) {
valueAxis.setRange(this.minimumValue, this.maximumValue);
}
valueAxis.setAutoTickUnitSelection(this.autoTickUnitSelection);
}
}

View File

@ -0,0 +1,70 @@
# $Id: DataProductsApplication.properties 3259 2013-10-17 21:37:36Z hchen3 $
# Resources file for DataProductsApplication class
Application.id = DataProductsApplication
Application.title = Data Products
mainFrame.title = Data Products
singlePlot.Action.text = &Single Plot...
singlePlot.Action.shortDescription = Show Single Plot
singlePlot.Action.icon = plot_single.gif
comparisonPlot.Action.text = &Comparison Plot...
comparisonPlot.Action.shortDescription = Show Comparison Plot
comparisonPlot.Action.icon = plot_coplot.gif
errorPlot.Action.text = &Error Plot...
errorPlot.Action.shortDescription = Show Error Plot
errorPlot.Action.icon = plot_error.gif
contrastPlot.Action.text = Co&ntrast Plot...
contrastPlot.Action.shortDescription = Contrast Plot: Show Both Comparison and Error Plots
contrastPlot.Action.icon = plot_contrast.gif
tabularData.Action.text = &Table...
tabularData.Action.shortDescription = Show Tabular Data
tabularData.Action.icon = table_callback1.gif
tabularErrorData.Action.text = Table Err&or...
tabularErrorData.Action.shortDescription = Show Tabular Error Data
tabularErrorData.Action.icon = table_error_callback.gif
removeSelectedNode.Action.text = Remove
removeSelectedNode.Action.shortDescription = Remove the Selected Node
configureRunTimename.Action.text = Configure Time Name...
configureRunTimename.Action.shortDescription = Configure the Time Name from Default sys.exec.out.time to a Different one
toggleGnuplot.Action.text = Gnuplot
toggleGnuplot.Action.shortDescription = Check it if using Gnuplot
toggleGnuplot.Action.icon = gnuplot_off.gif
selectFermi.Action.text = Fermi
selectGnuplot.Action.text = Gnuplot
selectJavaPlot.Action.text = Java
selectTerminalDevice.Action.text = Terminal
selectPrinterDevice.Action.text = Printer
selectFileDevice.Action.text = File ...
selectGnuplotTerminal.Action.text = Gnuplot Terminal
selectX11.Action.text = X11
selectPSColor.Action.text = PS-Color
selectPSBW.Action.text = PS-BW
selectPNG.Action.text = PNG
selectEPS.Action.text = EPS
selectAQUA.Action.text = AQUA
gnuplot.on.icon = gnuplot_on.gif
gnuplot.off.icon = gnuplot_off.gif
fxplot.command = fxplot
gxplot.command = gxplot
jxplot.command = jxplot
#default.timename = sys.exec.out.time

Binary file not shown.

After

Width:  |  Height:  |  Size: 668 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 751 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 469 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 B

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,121 @@
# $Id: TrickDPApplication.properties 2827 2013-02-27 19:44:59Z hchen3 $
# Resources file for TrickDPApplication class
Application.id = trick_dp
Application.title = Trick Data Products
Application.description = Trick Data Products Application
mainFrame.title = Trick DP
# Menu Bar
sessionMenu.text = &Session
simsRunsMenu.text = Sims/&Runs
dataProductMenu.text = &Data Product
settingsMenu.text = Se&ttings
actionsMenu.text = &Actions
helpMenu.text = &Help
# Menu items
## Session menu
newSession.Action.text = &New...
newSession.Action.shortDescription = Start a New Session
openSession.Action.text = &Open...
openSession.Action.shortDescription = Open an Existing Session
##convertSession.Action.text = &Convert...
##convertSession.Action.shortDescription = Convert Session File to XML Format
saveSession.Action.text = &Save...
saveSession.Action.shortDescription = Save Current Session
refreshSession.Action.text = R&efresh...
refreshSession.Action.shortDescription = Refresh Current Session
#propertiesSession.Action.text = &Properties...
#propertiesSession.Action.shortDescription = Show Properties of Current Session
## Sims/Runs menu
importSimDir.Action.text = Import &Sim Dir...
importSimDir.Action.shortDescription = Import Sim Directory to Current Session
addRunDir.Action.text = Add &Run Dir...
addRunDir.Action.shortDescription = Add a Run Directory to Current Session
## Data Product menu
addDP.Action.text = &Add DP...
addDP.Action.shortDescription = Add a Data Product file to Current Session
editSelectedDP.Action.text = &Edit DP...
editSelectedDP.Action.shortDescription = Open Quickplot to edit the Selected Data Product from DP Selections
editRightClickedDP.Action.text = &Edit DP...
editRightClickedDP.Action.shortDescription = Open Quickplot to edit the Selected Data Product file
filterDP.Action.text = &Filter...
filterDP.Action.shortDescription = Filter the Displayed Data Product files
## Settings
plotDestination.Action.text = &Destination
plotDestination.Action.shortDescritpion = The Destination for Plotting
## Actions menu
gnuSinglePlot.Action.text = GNUplot Postscript Single Plot...
gnuSinglePlot.Action.shortDescription = Show GNU Postscript Single Plot
gnuSinglePlot.Action.icon = ps_single.gif
gnuComparisonPlot.Action.text = GNUplot Postscript Comparison Plot...
gnuComparisonPlot.Action.shortDescription = Show GNU Postscript Comparison Plot
gnuComparisonPlot.Action.icon = ps_coplot.gif
gnuErrorPlot.Action.text = GNUplot Postscript Error Plot...
gnuErrorPlot.Action.shortDescription = Show GNU Postscript Error Plot
gnuErrorPlot.Action.icon = ps_error.gif
quickPlot.Action.text = &Quickplot...
quickPlot.Action.shortDescription = Quick Plot
quickPlot.Action.icon = quickplot.gif
createPDF.Action.text = Create &PDF Booklet...
createPDF.Action.shortDescription = Create PDF Booklet...
createPDF.Action.icon = adobe_pdf.gif
## Popup Menu for tree
addRuns.Action.text = Add run(s)
addRuns.Action.shortDescription = Selects run(s)
readDPList.Action.text = Read DP List
readDPList.Action.shortDescription = Add DP List in Selected SIM Directory
openSelected.Action.text = Opentree
openSelected.Action.shortDescription = Open Selected Tree Nodes
closeSelected.Action.text = Closetree
closeSelected.Action.shortDescription = Close Selected Tree Nodes
removeSelectedNodes.Action.text = Remove
removeSelectedNodes.Action.shortDescription = Remove Selected Node(s)
addDPs.Action.text = Add DPs
addDPs.Action.shortDescription = Add Selected to DP List
## Popup Menu for list
removeSelectedItems.Action.text = Remove
removeSelectedItems.Action.shortDescription = Remove Selected List Item(s)
removeAllItems.Action.text = Remove All
removeAllItems.Action.shortDescription = Remove All List Items
runSim.Action.text = Run Sim
runSim.Action.shortDescription = Run Selected Sim
refreshSelected.Action.text = Refresh
refreshSelected.Action.shortDescription = Refresh the Selected Nodes of the Tree

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1,70 @@
<?xml version='1.0' encoding='ISO-8859-1' ?>
<!DOCTYPE helpset
PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp HelpSet Version 2.0//EN"
"http://java.sun.com/products/javahelp/helpset_2_0.dtd">
<helpset version="2.0">
<!-- title -->
<title>Trick DP - Help</title>
<!-- maps -->
<maps>
<homeID>top</homeID>
<mapref location="Map.jhm"/>
</maps>
<!-- views -->
<view>
<name>TOC</name>
<label>Table Of Contents</label>
<type>javax.help.TOCView</type>
<data>HelpTOC.xml</data>
</view>
<!--view>
<name>Index</name>
<label>Index</label>
<type>javax.help.IndexView</type>
<data>HelpIndex.xml</data>
</view-->
<view>
<name>Search</name>
<label>Search</label>
<type>javax.help.SearchView</type>
<data engine="com.sun.java.help.search.DefaultSearchEngine">
JavaHelpSearch
</data>
</view>
<view>
<name>Favorites</name>
<label>Favorites</label>
<type>javax.help.FavoritesView</type>
</view>
<presentation default="true" displayviewimages="false">
<name>main window</name>
<size width="700" height="400" />
<location x="200" y="200" />
<title>Trick DP - Online Help</title>
<image>trickicon</image>
<toolbar>
<helpaction>javax.help.BackAction</helpaction>
<helpaction>javax.help.ForwardAction</helpaction>
<helpaction>javax.help.SeparatorAction</helpaction>
<helpaction>javax.help.HomeAction</helpaction>
<helpaction>javax.help.ReloadAction</helpaction>
<helpaction>javax.help.SeparatorAction</helpaction>
<helpaction>javax.help.PrintAction</helpaction>
<helpaction>javax.help.PrintSetupAction</helpaction>
</toolbar>
</presentation>
<presentation>
<name>main</name>
<size width="400" height="400" />
<location x="200" y="200" />
<title>Trick DP - Online Help</title>
</presentation>
</helpset>

View File

@ -0,0 +1,18 @@
<?xml version='1.0' encoding='ISO-8859-1' ?>
<!DOCTYPE toc
PUBLIC "-//Sun Microsystems Inc.//DTD JavaHelp TOC Version 2.0//EN"
"http://java.sun.com/products/javahelp/toc_2_0.dtd">
<toc version="2.0">
<tocitem text="Trick DP" image="toplevelfolder">
<tocitem text="Introduction to Trick DP" target="trickdp.intro"/>
<tocitem text="General Usage" target="trickdp.generalusage" />
<tocitem text="How to Organize Data" target="trickdp.howtoorganize"/>
<tocitem text="Importing Data" target="trickdp.importingdata"/>
<tocitem text="Quickplot" target="trickdp.quickplot"/>
<tocitem text="Using Gnuplot" target="trickdp.usinggnuplot"/>
<tocitem text="FAQ" target="trickdp.faq"/>
</tocitem>
</toc>

Some files were not shown because too many files have changed in this diff Show More