org.sbml.bargraph.MainWindow.java Source code

Java tutorial

Introduction

Here is the source code for org.sbml.bargraph.MainWindow.java

Source

/*
 * ----------------------------------------------------------------------------
 * This file is part of JSBML. Please visit <http://sbml.org/Software/JSBML>
 * for the latest version of JSBML and more information about SBML.
 *
 * Copyright (C) 2009-2017 jointly by the following organizations:
 * 1. The University of Tuebingen, Germany
 * 2. EMBL European Bioinformatics Institute (EBML-EBI), Hinxton, UK
 * 3. The California Institute of Technology, Pasadena, CA, USA
 * 4. The University of California, San Diego, La Jolla, CA, USA
 * 5. The Babraham Institute, Cambridge, UK
 * 
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation. A copy of the license agreement is provided
 * in the file named "LICENSE.txt" included with this software distribution
 * and also available online as <http://sbml.org/Software/JSBML/License>.
 * ----------------------------------------------------------------------------
 */
package org.sbml.bargraph;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.FileDialog;
import java.awt.Font;
import java.awt.Image;
import java.awt.Toolkit;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingConstants;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.StandardChartTheme;
import org.jfree.chart.axis.AxisLocation;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.chart.renderer.category.BarRenderer;
import org.jfree.data.category.DefaultCategoryDataset;

/**
 * Main window for the SBML Bar Graph.
 * @file    Main.java
 * @brief   Main window for SBML Bar Graph.
 * @author  Michael Hucka
 * @date    Created in 2012
 */
public class MainWindow extends JFrame {
    //
    // --------------------------- Public methods -----------------------------
    //

    /**
     * Creates the main application frame.
     * 
     * @param file A file to read and graph upon start up.  If null, nothing
     * is graphed initially.
     */
    public MainWindow(File file) {
        Log.note("Creating main application window.");
        setPlatformProperties();

        setBackground(new Color(255, 255, 255));
        setMaximumSize(new Dimension(2000, 1000));
        setMinimumSize(new Dimension(600, 400));
        setTitle("SBML Bar Graph");
        setSize(new Dimension(600, 400));
        setPreferredSize(new Dimension(600, 400));
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 550, 400);
        contentPane = new JPanel();
        contentPane.setSize(new Dimension(600, 400));
        contentPane.setPreferredSize(new Dimension(600, 400));
        contentPane.setMinimumSize(new Dimension(600, 400));
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        contentPane.setLayout(new BorderLayout(0, 0));
        setContentPane(contentPane);

        fileNamePanel = new JPanel();
        fileNamePanel.setPreferredSize(new Dimension(590, 20));
        fileNamePanel.setMinimumSize(new Dimension(590, 20));
        fileNamePanel.setLayout(new BorderLayout(0, 0));
        contentPane.add(fileNamePanel, BorderLayout.NORTH);

        fileNameField = new JTextField();
        fileNameField.setHorizontalAlignment(SwingConstants.CENTER);
        fileNameField.setText("No file selected");
        fileNameField.setDisabledTextColor(Color.LIGHT_GRAY);
        fileNameField.setFont(new Font("Lucida Grande", Font.ITALIC, 11));
        fileNameField.setBorder(null);
        fileNameField.setOpaque(true);
        fileNameField.setBackground(UIManager.getColor("Separator.foreground"));
        fileNameField.setEnabled(false);
        fileNameField.setSize(new Dimension(590, 0));
        fileNameField.setPreferredSize(new Dimension(590, 28));
        fileNameField.setMinimumSize(new Dimension(590, 28));
        fileNameField.setColumns(10);
        fileNamePanel.add(fileNameField, BorderLayout.CENTER);

        // The bar graph panel.

        chartPanel = new ChartPanel(createModelBarGraph(), false);
        contentPane.add(chartPanel, BorderLayout.CENTER);
        updatePanelForSBMLFile(file);

        // Manual additions for File menu.

        fileMenu = new JMenu();
        fileMenu.setText("File");

        openFileMenuItem = new JMenuItem();
        openFileMenuItem
                .setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, shortcutKeyMask));
        openFileMenuItem.setText("Open...");
        openFileMenuItem.setToolTipText("Open file to be graphed");
        openFileMenuItem.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                openFileHandler(evt);
            }
        });

        fileMenu.add(openFileMenuItem);
        menuBar = new javax.swing.JMenuBar();
        menuBar.add(fileMenu);

        setJMenuBar(menuBar);

        // Replace the default Java window icon with our own.
        // This only has an effect on non-Mac OS systems.

        URL iconImageURL = getClass().getResource(Config.RES_ICON_APP);
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        Image img = toolkit.createImage(iconImageURL);
        setIconImage(img);

        Log.note("Finished constructing panel and menu bar");
    }

    /**
     * Creates an empty bar graph.
     * @return
     */
    public JFreeChart createModelBarGraph() {
        // Initialize the style. Have to do this before creating charts.

        BarRenderer.setDefaultShadowsVisible(false);
        ChartFactory.setChartTheme(StandardChartTheme.createLegacyTheme());

        // Create the actual chart.

        chartData = new DefaultCategoryDataset();
        JFreeChart chart = ChartFactory.createBarChart(null, // chart title
                null, // domain axis label
                "Total count", // range axis label
                chartData, // data
                PlotOrientation.HORIZONTAL, // orientation
                false, // include legend
                false, // tooltips?
                false // URLs?
        );

        CategoryPlot plot = (CategoryPlot) chart.getPlot();
        plot.setBackgroundPaint(Color.white);
        plot.setRangeGridlinePaint(Color.lightGray);
        plot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_LEFT);

        NumberAxis rangeAxis = (NumberAxis) plot.getRangeAxis();
        rangeAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
        rangeAxis.setTickLabelFont(new Font("SansSerif", Font.PLAIN, 12));

        CategoryAxis domainAxis = plot.getDomainAxis();
        domainAxis.setTickLabelFont(new Font("SansSerif", Font.PLAIN, 12));

        BarRenderer renderer = (BarRenderer) plot.getRenderer();
        renderer.setSeriesPaint(0, new Color(0, 101, 178));

        return chart;
    }

    /**
     * Updates the bar graph and other panels in the main window using
     * data derived by reading the given @p file.
     * 
     * @param file The SBML file to parse and analyze for the graph.
     */
    public void updatePanelForSBMLFile(File file) {
        if (file == null) {
            return;
        }

        SBMLStats stats;
        try {
            stats = new SBMLStats(file);
        } catch (javax.xml.stream.XMLStreamException e) {
            Log.warning("Exception while parsing '" + file.getPath() + "':");
            Log.warning(e.getMessage());
            Dialog.error(this, "Unable to parse the given SBML File: " + e.getMessage(), "File parsing error");
            return;
        } catch (java.io.IOException e) {
            Log.warning("Exception while parsing '" + file.getPath() + "':");
            Log.warning(e.getMessage());
            Dialog.error(this, "I/O error trying to read the given SBML File: " + e.getMessage(),
                    "File parsing error");
            return;
        }

        Log.note("Graphing data: " + stats.asString());

        fileNameField.setText(stats.getFile().getPath());
        fileNameField.setDisabledTextColor(Color.BLACK);

        // The row could be called anything, since we don't display the name.
        String row = "Row 1";

        chartData.clear();
        chartData.addValue(stats.getNumSpecies(), row, "Species");
        chartData.addValue(stats.getNumCompartments(), row, "Compartments");
        chartData.addValue(stats.getNumReactions(), row, "Reactions");
        chartData.addValue(stats.getNumParameters(), row, "Parameters");
        chartData.addValue(stats.getNumRules(), row, "Rules");
        chartData.addValue(stats.getNumUnitDefinitions(), row, "Unit definitions");

        if (stats.getSBMLLevel() >= 2) {
            chartData.addValue(stats.getNumEvents(), row, "Events");
            chartData.addValue(stats.getNumFunctionDefinitions(), row, "Function definitions");

            if (stats.getSBMLVersion() >= 2) {
                chartData.addValue(stats.getNumConstraints(), row, "Constraints");
                chartData.addValue(stats.getNumInitialAssignments(), row, "Initial assignments");
            }

            if (stats.getSBMLVersion() >= 2 && stats.getSBMLLevel() < 3) {
                chartData.addValue(stats.getNumSpeciesTypes(), row, "Species types");
                chartData.addValue(stats.getNumCompartmentTypes(), row, "Compartment types");
            }
        }

        validate();
        repaint();
    }

    /**
     * Configure the windows for platform the user is running.
     */
    public void setPlatformProperties() {
        if (Config.runningMac()) {
            // Extra settings for making the app look natural on Mac OS X.

            Log.note("This is a Mac; setting properties appropriately.");
            System.setProperty("apple.laf.useScreenMenuBar", "true");
            System.setProperty("com.apple.mrj.application.apple.menu.about.name", Config.APP_NAME);
            System.setProperty("apple.awt.showGrowBox", "true");
        }

        try {
            // Set System L&F
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (UnsupportedLookAndFeelException e) {
            Log.warning("Unable to set look and feel. Proceeding anyway.");
        } catch (Exception e) {
            Log.warning("Unexpected look & feel configuration failure -- " + "something more serious may be wrong");
        }
    }

    /**
     * Performs misc. initializations and makes the main window visible.
     * @throws Exception
     */
    public void initAndShow() throws Exception {
        pack();
        setLocationRelativeTo(null);

        if (Config.runningMac()) {
            Log.note("Registering for Mac OS X GUI events");
            registerForMacOSXEvents();
        } else {
            Log.note("Registering for GUI events");
            registerForEvents();
        }

        Log.note("Making main application window visible.");
        setVisible(true);
    }

    /**
     * Sets up menus using adapters for the Mac OS X look and feel.
     */
    public void registerForMacOSXEvents() {
        Log.note("Setting up the Mac OS X application menu.");
        try {
            // Generate and register the OSXAdapter, passing it a hash
            // of all the methods we wish to use as delegates for
            // various com.apple.eawt.ApplicationListener methods

            Class<?> c = getClass();
            Method quit = c.getDeclaredMethod("quit", (Class[]) null);
            Method about = c.getDeclaredMethod("about", (Class[]) null);

            OSXAdapter.setQuitHandler(this, quit);
            OSXAdapter.setAboutHandler(this, about);
        } catch (Exception e) {
            Log.error("Unable to set up MacOS application menu", e);
            Main.quit(Main.STATUS_ERROR);
        }
    }

    /**
     * Set up menus when running under Windows.
     */
    public void registerForEvents() {
        Log.note("Setting up the Windows menus.");

        JMenuItem fileExitItem = new JMenuItem();
        fileExitItem
                .setAccelerator(javax.swing.KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_W, shortcutKeyMask));
        fileExitItem.setMnemonic(java.awt.event.KeyEvent.VK_C);
        fileExitItem.setText("Exit");
        fileExitItem.setToolTipText("Exit application");
        fileExitItem.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                quit();
            }
        });

        fileMenu.addSeparator();
        fileMenu.add(fileExitItem);

        JMenu helpMenu = new JMenu();
        helpMenu.setText("Help");

        JMenuItem aboutMenuItem = new JMenuItem();
        aboutMenuItem.setText("About " + Config.APP_NAME);
        aboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                about();
            }
        });

        helpMenu.add(aboutMenuItem);
        menuBar.add(helpMenu);
    }

    /**
     * Handles the "Open" menu item in the File menu.
     * @param evt
     */
    public void openFileHandler(java.awt.event.ActionEvent evt) {
        Log.note("'Open' menu item invoked.");
        FileDialog dialog = new FileDialog(this, "Choose file to graph");
        dialog.setVisible(true);

        if (dialog.getFile() == null) {
            Log.note("User cancelled file selection");
            return;
        }

        VerifiableFile theFile = new VerifiableFile(dialog.getDirectory() + dialog.getFile());
        if (theFile.isVerifiedFile()) {
            Log.note("User selected file '" + theFile.getPath() + "'");
            try {
                updatePanelForSBMLFile(theFile);
            } catch (Exception e) {
                Log.error(e.getMessage());
            }
        } else {
            Log.note("Invalid file selected: '" + theFile.getPath() + "'");
            Dialog.error(this, "Invalid file selected: " + theFile.getName(), "File error");
        }
    }

    /**
     * Handles the "About" menu item.
     */
    public void about() {
        Log.note("'About' invoked.");
        AboutPane aboutPane = new AboutPane();
        aboutPane.setVisible(true);
    }

    /**
     * Handles the "Quit" menu item and window closings.
     * 
     * @return returns a boolean value if user wants to quit
     */
    public boolean quit() {
        String action;
        if (Config.runningMac()) {
            action = "Quit";
        } else {
            action = "Exit";
        }

        Log.note("'" + action + "' invoked.");
        if (Dialog.yesNo(this, action + " the " + Config.APP_NAME + "?", action + "?")) {
            Main.quit(Main.STATUS_NORMAL);
        }
        return false;
    }

    /**
     * Testing harness.
     * @param args
     */
    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    MainWindow mainWindow = new MainWindow(null);
                    mainWindow.initAndShow();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    //
    // ---------------------- Private data members ----------------------------
    //

    /**
     * 
     */
    private JPanel contentPane;
    /**
     * 
     */
    private JPanel fileNamePanel;
    /**
     * 
     */
    private JTextField fileNameField;
    /**
     * 
     */
    private JMenuBar menuBar;
    /**
     * 
     */
    private JMenu fileMenu;
    /**
     * 
     */
    private JMenuItem openFileMenuItem;
    /**
     * 
     */
    private ChartPanel chartPanel;
    /**
     * 
     */
    private DefaultCategoryDataset chartData;
    /**
     * 
     */
    private static int shortcutKeyMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();

    /**
     * 
     */
    private static final long serialVersionUID = 1L;

}