/*
* Main.java
*
* Created on November 7, 2007, 1:04 PM
*
* This is the file which contains all of the main classes, and functions for
* running BioLegato.
*
* Current serializable number:
* private static final long serialVersionUID = 7526472295622777040L;
*
* Released numbers:
*/
package org.biolegato.main;
import java.awt.BorderLayout;
import java.awt.Component;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Pattern;
import javax.swing.AbstractAction;
import javax.swing.JApplet;
import javax.swing.JFrame;
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 org.biopcd.parser.PCDIO;
/**
* The main program and generic function class.
*
* This class is used to generate the main window, do all startup
* processing, and run the program. This class also contains most
* of the utility functions.
*
**
* @author Graham Alvare
* @author Brian Fristensky
* @version 1.1.2 25-Mar-2011
*/
public abstract class DataCanvas extends JApplet implements PCDIO {
/////////////////////////
//*********************//
//* PROGRAM CONSTANTS *//
//*********************//
/////////////////////////
/**
* This constant stores an empty string (to avoid recreation)
*/
public static final String EMPTY_STRING = "";
/**
* This constant is used for Serialization
*/
public static final long serialVersionUID = 7526472295622776147L;
/**
* The menu item for BioLegato's "About..."
*/
public final JMenuItem ABOUT_MENUITEM = new JMenuItem(
new AbstractAction("About...") {
/* Serialization number - required for no warnings*/
private static final long serialVersionUID = 7526472295622776157L;
{
putValue(MNEMONIC_KEY, new Integer(java.awt.event.KeyEvent.VK_A));
} /* Sets the mnemonic for the event */
public void actionPerformed(java.awt.event.ActionEvent evt) {
// NOTE: 1.1.2 is replaced with the actual version number
// by BioLegato's Apache Ant build script.
JOptionPane.showMessageDialog(window,
"BioLegato version 1.1.2\n"
+ "\n"
+ "Please cite:\n"
+ "Alvare G, Roche-Lima A, Fristensky B\n"
+ "BioLegato: a programmable, object-oriented graphic user interface.\n"
+ "BMC Bioinformatics 24, 316 (2023)\n"
+ "https://doi.org/10.1186/s12859-023-05436-4\n",
"About BioLegato",
JOptionPane.QUESTION_MESSAGE);
}
});
/**
* The menu item for BioLegato's "Exit..."
*/
public final JMenuItem EXIT_MENUITEM = new JMenuItem(
new AbstractAction("Exit") {
/* Serialization number - required for no warnings*/
private static final long serialVersionUID = 7526472295622776157L;
{
putValue(MNEMONIC_KEY, new Integer(java.awt.event.KeyEvent.VK_X));
} /* Sets the mnemonic for the event */
public void actionPerformed(java.awt.event.ActionEvent evt) {
window.dispose();
}
});
/////////////////
//*************//
//* VARIABLES *//
//*************//
/////////////////
/**
* Reference to the main canvas's window
* (intended to be used for creating modal child dialogue boxes)
*/
private JFrame window = null;
/**
* Reference to the main canvas's menu
*/
private JMenuBar menu;
/**
* Stores the properties for BioLegato.
*
* Please see the manpage (within the jar, manpage.txt) for a list of
* available properties.
*
* This properties class will read properties files from the directory
* containing BioLegato, the user directory and finally the directory
* BioLegato was launched from. Please note that this behaviour can
* be changed using the BL_PROPERTIES environment variable.
*
* NOTE: for path properties BioLegato will replace all $'s with the
* appropriate environment variables if set.
*/
protected Properties properties = new Properties() {
{
// load the default properties JAR file.
// ensure this is done by the catch statement, otherwise exit.
try {
load(DataCanvas.class.getResourceAsStream(
"/default.properties"));
} catch (IOException ioe) {
System.err.println("FATAL ERROR - CORRUPT JAR FILE");
ioe.printStackTrace(System.err);
System.exit(1);
}
}
/**
* Changes a property within the BLProperties object
**
* @param key the key of the property to alter.
* @param value the new value of the property.
* @return the old value of the property changed
* (null if no previous value).
*/
@Override
public Object setProperty(String key, String value) {
Object result = null;
// ensure that the key and value parameters are not null
if (key != null && value != null) {
// make sure the key is always lower case
key = key.toLowerCase();
// the old value of the property changed
result = super.setProperty(key, value);
}
// return the function
return result;
}
/**
* Obtains a property from the BLProperties object.
**
* @param key the key of the property.
* @return the current value of the property (returns "" if not set).
*/
@Override
public String getProperty(String key) {
// make sure the key is always lower case
key = key.toLowerCase();
String result = super.getProperty(key);
if (result == null) {
result = EMPTY_STRING;
} else {
result = BLMain.envreplace(result);
}
return result;
}
};
/**
* Stores all of the menu headings in BioLegato's main window.
* This hashtable is used to add menu items to BioLegato's menu headings.
* The key of the hashtable corresponds to the label of the menu heading.
* The value of the hashtable is the menu heading's object.
*/
private Map menuHeadings =
new HashMap();
/**
* This constant stores the program's name
*/
public String NAME = getProperty("title");
/////////////////////////
//*********************//
//* STARTUP FUNCTIONS *//
//*********************//
/////////////////////////
/**
* Constructs a default instance of a DataCanvas
*/
public DataCanvas() {
this((Map) null);
}
/**
* Constructs a new instance of a DataCanvas, importing a properties
* map to overwrite default program properties.
**
* @param importProperties a map containing the properties to overwrite
*/
public DataCanvas(Map extends Object, ? extends Object>
importProperties) {
// Import the properties specified by the importProperties map.
if (importProperties != null) {
this.properties.putAll(importProperties);
}
// Create the menu bar.
menu = new JMenuBar();
setJMenuBar(menu);
// Add File and Edit to the menu headings -- to ensure that they
// are the 1st and 2nd menu headings (from the left) on the
// program's menu bar.
addMenuHeading("File");
addMenuHeading("Edit");
}
/**
* Starts BioLegato Applet version.
*/
@Override
public void init() {
javax.swing.JRootPane grootPane = this.getRootPane();
grootPane.putClientProperty("defeatSystemEventQueueCheck",
Boolean.TRUE);
//Execute a job on the event-dispatching thread;
// creating this applet's GUI.
try {
////////////
//********//
//* MENU *//
//********//
////////////
javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
public void run() {
// Ensure that the File and Edit headings come first.
addMenuHeading("File");
addMenuHeading("Edit");
// Event handlers - add the Exit and About menu items.
addMenuHeading("File").add(EXIT_MENUITEM);
addMenuHeading("Help").add(ABOUT_MENUITEM);
JPanel panel = new JPanel();
panel.setLayout(new BorderLayout());
panel.add(BorderLayout.SOUTH, new JLabel("Count: "
+ menu.getMenuCount()));
panel.add(BorderLayout.NORTH, menu);
panel.add(BorderLayout.CENTER, display());
add(panel);
}
});
} catch (Exception e) {
System.err.println("createGUI didn't complete successfully");
}
//main(new String[0]);
}
////////////////////////////
//************************//
//* PROPERTIES FUNCTIONS *//
//************************//
////////////////////////////
/**
* Retrieves individual settings for BioLegato.
* This is used to obtain values of properties in BioLeagato
**
* @param property the property key to retrieve the value for
* @return the property value corresponding to the key parameter
*/
public String getProperty(String property) {
return properties.getProperty(property);
}
////////////////////////
//********************//
//* WINDOW FUNCTIONS *//
//********************//
////////////////////////
/**
* Provides access for other classes to the main program window JFrame
* object.
**
* @return the JFrame object corresponding to the main program window.
*/
public JFrame getJFrame() {
return window;
}
/**
* Adds a menu heading (JMenu) to our menu (BLMenu).
**
* @param name the name of the menu heading
* @return either the JMenu which was added or the JMenu that
* corresponds to the existing menu heading.
*/
public final JMenu addMenuHeading(String name) {
JMenu heading = menuHeadings.get(name); // the JMenu object to add
// check if the heading already exists in the menu.
// (null indicates that the menu heading is new)
if (heading == null) {
// create a new menu heading object
heading = new JMenu(name);
// set the mnemonic
if (name != null && name.length() >= 1
&& ((name.charAt(0) >= 'a' && name.charAt(0) <= 'z')
|| (name.charAt(0) >= 'A' && name.charAt(0) <= 'Z'))) {
heading.setMnemonic(name.charAt(0));
}
// add the heading
menuHeadings.put(name, heading);
menu.add(heading);
}
// return the menu heading object
return heading;
}
/**
* Adds a menu heading (JMenu) to our menu (BLMenu).
**
* @param order the position to place the menu tag
* @param name the name of the menu heading
* @return either the JMenu which was added or the JMenu
* that corresponds to the existing menu heading.
*/
public JMenu addMenuHeading(int order, String name) {
// the hading to add the item to.
JMenu heading = addMenuHeading(name);
// ensure that the menu heading is in the correct order
if (menu.getComponentIndex(heading) != order) {
menu.remove(heading);
menu.add(heading, order);
}
return heading;
}
/////////////////////////
//*********************//
//* GENERAL FUNCTIONS *//
//*********************//
/////////////////////////
/**
* Sends an error message to BioLegato's standard err.
**
* @param message the error message to send.
* @param location the location the error occurred.
*/
public void error(String message, String location) {
// print the error to the error stream
System.err.println(NAME + ((location != null
&& !"".equals(location.trim()))
? " (" + location + ")" : "") + ": ERROR --- " + message);
}
/**
* Sends an warning message to BioLegato's standard err.
**
* @param message the warning message to send.
* @param location the location the error occurred.
*/
public void warning(String message, String location) {
// prints the warning to BioLegato's error stream
System.err.println(NAME + ((location != null
&& !"".equals(location.trim()))
? " (" + location + ")" : "") + ": WARNING --- " + message);
}
/**
* Sends a message to BioLegato's standard out.
**
* @param message the message to send.
* @param location the location the message was sent from.
*/
public void message(String message, String location) {
// prints the warning to BioLegato's error stream
System.out.println(NAME + ((location != null
&& !"".equals(location.trim()))
? " (" + location + ")" : "") + ": " + message);
}
/**
* Checks if a character array is all digits.
**
* @param test the character array to test.
* @return true if the array only contains digits.
*/
public static boolean testNumber(String test) {
return Pattern.matches("^-?\\d+$", test);
}
/**
* Used to create a JFrame containing the current canvas
*/
public final void createJFrame() {
window = new JFrame(getProperty("title"));
window.setJMenuBar(menu);
window.add(display());
// center and draw the frame on the screen
window.pack();
window.setVisible(true);
window.setLocationRelativeTo(null);
window.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
}
/**
* Displays the main pane of the data canvas
**
* @return the swing or awt component to display as the canvas.
*/
public abstract Component display();
/**
* Possible vestigial code!
* This code is used to provide a plugin name for the canvas. The purpose
* of the plugin name system was to allow multiple canvases to be loaded
* (via. BioLegato's plugin system), and then have the properties select
* which canvas to use based on the plugin names. This architecture has
* since been replaced, and so this code may no longer be used.
**
* @return the name to display for the canvas in
* all program text referring to it.
* @deprecated vestigial code from a previous BioLegato framework structure.
*/
public abstract String getPluginName ();
}