Newer
Older
/* GraphMenu.java
*
* created: Tue Sep 18 2001
*
* This file is part of Artemis
*
* Copyright (C) 2001 Genome Research Limited
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/GraphMenu.java,v 1.9 2009-06-02 15:32:00 tjc Exp $
import uk.ac.sanger.artemis.EntryGroup;
import uk.ac.sanger.artemis.Options;
import uk.ac.sanger.artemis.plot.Algorithm;
import uk.ac.sanger.artemis.plot.BaseAlgorithm;
import uk.ac.sanger.artemis.plot.CodonUsageAlgorithm;
import uk.ac.sanger.artemis.plot.CodonUsageWeight;
import uk.ac.sanger.artemis.plot.UserDataAlgorithm;
import uk.ac.sanger.artemis.sequence.Strand;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.IOException;
import java.io.File;
import java.util.Vector;
import javax.swing.*;
/**
* This menu controls one particular BasePlotGroup.
*
* @author Kim Rutherford <kmr@sanger.ac.uk>
* @version $Id: GraphMenu.java,v 1.9 2009-06-02 15:32:00 tjc Exp $
public class GraphMenu extends JMenu
{
private static final long serialVersionUID = 1L;
/**
* The JFrame reference that was passed to the constructor.
**/
private JFrame frame;
/**
* The BasePlotGroup that was passed to the constructor.
**/
private BasePlotGroup base_plot_group;
/**
* The EntryGroup object that was passed to the constructor.
**/
private EntryGroup entry_group = null;
/**
* The FeatureDisplay that was passed to the constructor.
**/
private FeatureDisplay feature_display;
private JMenu menuSubMenu = new JMenu("Other Graphs");
/**
* This list of the CheckboxMenuItems for the graphs is stored so that we
* can turn them all off with "Hide All Graphs".
**/
private Vector algorithm_menu_items = new Vector ();
/**
* Create a new GraphMenu object and all it's menu items.
* @param frame The JFrame that owns this JMenu.
* @param entry_group The EntryGroup containing the sequence to plot.
* @param base_plot_group The BasePlotGroup that this menu controls.
* @param view_menu This ViewMenu is updated when a usage plot is added.
* @param add_menu This AddMenu is updated when a usage plot is added.
* @param menu_name The name of the new menu.
**/
public GraphMenu (final JFrame frame,
final EntryGroup entry_group,
final BasePlotGroup base_plot_group,
final FeatureDisplay feature_display,
final String menu_name,
final JSplitPane splitPane)
super (menu_name);
this.frame = frame;
this.entry_group = entry_group;
this.base_plot_group = base_plot_group;
this.feature_display = feature_display;
final BaseAlgorithm [] orig_algorithms =
base_plot_group.getPlotAlgorithms ();
final JMenuItem hide_all_graphs_item = new JMenuItem ("Hide All Graphs");
hide_all_graphs_item.addActionListener (new ActionListener ()
{
public void actionPerformed (ActionEvent event)
{
final BaseAlgorithm [] current_algorithms =
base_plot_group.getPlotAlgorithms ();
for (int i = 0 ; i < current_algorithms.length ; ++i)
{
final BaseAlgorithm this_algorithm = current_algorithms[i];
base_plot_group.setVisibleByAlgorithm (this_algorithm, false);
final JCheckBoxMenuItem this_menu_item =
(JCheckBoxMenuItem) algorithm_menu_items.elementAt (i);
this_menu_item.setState (false);
}
// XXX change to revalidate().
frame.validate ();
}
}
});
add (hide_all_graphs_item);
addSeparator ();
final JMenuItem usage_plot_item = new JMenuItem ("Add Usage Plots ...");
usage_plot_item.addActionListener (new ActionListener ()
{
public void actionPerformed (ActionEvent event)
{
}
});
add (usage_plot_item);
final JMenuItem user_plot_item = new JMenuItem ("Add User Plot ...");
user_plot_item.addActionListener (new ActionListener ()
{
public void actionPerformed (ActionEvent event)
{
try
{
addUserPlot ();
adjustSplitPane(true);
}
catch(java.lang.OutOfMemoryError emem)
{
JOptionPane.showMessageDialog(frame,
"Out of memory. Increase the maximum memory"+
"\navailable for this application and try again.",
"Out Of Memory",
JOptionPane.WARNING_MESSAGE);
frame.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
}
});
add (user_plot_item);
addSeparator ();
}
if(this_algorithm.getAlgorithmName().startsWith("Cumulative AT"))
useSubMenu = true;
addAlgorithm (this_algorithm, false, useSubMenu);
if (Options.getOptions ().getProperty ("codon_usage_file") != null)
{
final String codon_usage_file_name =
Options.getOptions ().getProperty ("codon_usage_file");
addUsagePlot (new File (codon_usage_file_name), true, false);
addUsagePlot (new File (codon_usage_file_name), false, false);
new MessageDialog (frame, "error while reading usage data: " + e);
}
}
}
/**
* Create a new GraphMenu object and all it's menu items.
* @param frame The JFrame that owns this JMenu.
* @param entry_group The EntryGroup containing the sequence to plot.
* @param base_plot_group The BasePlotGroup that this menu controls.
* @param view_menu This ViewMenu is updated when a usage plot is added.
* @param add_menu This AddMenu is updated when a usage plot is added.
* @param menu_name The name of the new menu.
**/
public GraphMenu (final JFrame frame,
final EntryGroup entry_group,
final BasePlotGroup base_plot_group,
final FeatureDisplay feature_display,
final JSplitPane splitPane)
this (frame, entry_group, base_plot_group, feature_display, "Graph",splitPane);
}
/**
* Add a menu item for the given algorithm to the Display menu.
* @param is_visible The JCheckBoxMenuItem starts in the true state if and
* only if this is true.
* @return The new JCheckBoxMenuItem
**/
private JCheckBoxMenuItem addAlgorithm (final BaseAlgorithm algorithm,
new JCheckBoxMenuItem (algorithm.getAlgorithmName (), is_visible);
new_item.addItemListener (new ItemListener ()
{
public void itemStateChanged(ItemEvent event)
{
new_item.isSelected());
adjustSplitPane(new_item.isSelected());
if(useSubMenu)
menuSubMenu.add(new_item);
else
add (new_item);
algorithm_menu_items.addElement (new_item);
return new_item;
}
/**
* Adjust the JSplitPane divider position if all plots are
* hidden or if a single graph has been made visible.
* @param thisGraphOn
*/
private void adjustSplitPane(final boolean thisGraphOn)
{
if(splitPane == null)
return;
final BaseAlgorithm [] current_algorithms =
base_plot_group.getPlotAlgorithms ();
int nvisible = 0;
for (int i = 0 ; i < current_algorithms.length ; ++i)
{
final JCheckBoxMenuItem this_menu_item =
(JCheckBoxMenuItem) algorithm_menu_items.elementAt (i);
if(this_menu_item.isSelected())
if(this_menu_item.getText().indexOf("Codon Usage") > -1)
usageDisplayed = true;
else
usageDisplayed = false;
}
}
if(nvisible == 0)
{
splitPane.setDividerSize(0);
splitPane.setDividerLocation(0);
}
else if( ( thisGraphOn && nvisible == 1 ) ||
(usageDisplayed && nvisible == 2) )
{
splitPane.setDividerSize(3);
splitPane.setDividerLocation(0.2d);
}
}
/**
* Ask the user for a file name, then read the codon usage data from that
* file, then make and add forward and a reverse BasePlot component using
* the data.
**/
final JFrame frame = Utilities.getComponentFrame (base_plot_group);
final StickyFileChooser dialog = new StickyFileChooser ();
dialog.setDialogTitle ("Select a codon usage data file name ...");
dialog.setDialogType (JFileChooser.OPEN_DIALOG);
final int status = dialog.showOpenDialog (frame);
if (status != JFileChooser.APPROVE_OPTION ||
return;
}
final File file =
new File (dialog.getCurrentDirectory (),
dialog.getSelectedFile ().getName ());
final BasePlot new_forward_plot =
addUsagePlot (file, true, true);
final BasePlot new_reverse_plot =
addUsagePlot (file, false, true);
final Algorithm forward_algorithm = new_forward_plot.getAlgorithm ();
final Algorithm reverse_algorithm = new_reverse_plot.getAlgorithm ();
base_plot_group.setVisibleByAlgorithm (forward_algorithm, true);
base_plot_group.setVisibleByAlgorithm (reverse_algorithm, true);
new MessageDialog (Utilities.getComponentFrame (base_plot_group),
"error while reading usage data: " + e);
}
}
}
/**
* Read the codon usage data from the given File, then make and add a
* BasePlot component using the data.
* @param use_forward_strand The plot will be a forward plot if and only if
* this is true.
* @param is_visible The plot will start off visible if and only if this is
* true.
* @return The BasePlot that was added.
**/
private BasePlot addUsagePlot (final File codon_usage_file,
final boolean use_forward_strand,
final boolean is_visible)
final Strand forward_strand =
entry_group.getBases ().getForwardStrand ();
final CodonUsageWeight usage_weights =
new CodonUsageWeight (codon_usage_file, forward_strand);
codon_usage_algorithm =
new CodonUsageAlgorithm (forward_strand, usage_weights);
final Strand backward_strand =
entry_group.getBases ().getReverseStrand ();
final CodonUsageWeight usage_weights =
new CodonUsageWeight (codon_usage_file, backward_strand);
codon_usage_algorithm =
new CodonUsageAlgorithm (backward_strand, usage_weights);
}
addAlgorithm (codon_usage_algorithm, is_visible, false);
final BasePlot new_plot =
base_plot_group.addAlgorithm (codon_usage_algorithm);
base_plot_group.setVisibleByAlgorithm (codon_usage_algorithm, is_visible);
// XXX hack to force the BasePlot to initialise
final DisplayAdjustmentEvent event =
new DisplayAdjustmentEvent (this,
feature_display.getFirstVisibleForwardBase (),
feature_display.getLastVisibleForwardBase (),
feature_display.getMaxVisibleBases (),
feature_display.getScaleValue (),
feature_display.getScaleFactor (),
feature_display.isRevCompDisplay (),
DisplayAdjustmentEvent.ALL_CHANGE_ADJUST_EVENT);
base_plot_group.displayAdjustmentValueChanged (event);
return new_plot;
}
/**
* Add a UserDataAlgorithm to the display.
**/
final JFrame frame = Utilities.getComponentFrame (base_plot_group);
final StickyFileChooser dialog = new StickyFileChooser ();
dialog.setDialogTitle ("Select a data file name ...");
dialog.setDialogType (JFileChooser.OPEN_DIALOG);
final JCheckBox logTransform = new JCheckBox("Use log(data+1)", false);
dialog.setAccessory(logTransform);
final int status = dialog.showOpenDialog (frame);
if (status != JFileChooser.APPROVE_OPTION ||
return;
}
final File file =
new File (dialog.getCurrentDirectory (),
dialog.getSelectedFile ().getName ());
frame.setCursor(new Cursor(Cursor.WAIT_CURSOR));
final uk.ac.sanger.artemis.util.Document document =
new uk.ac.sanger.artemis.util.FileDocument (file);
final Strand forward_strand =
getEntryGroup ().getBases ().getForwardStrand ();
new UserDataAlgorithm (forward_strand, document, logTransform.isSelected());
final BasePlot new_base_plot =
base_plot_group.addAlgorithm (new_algorithm);
base_plot_group.setVisibleByAlgorithm (new_algorithm, true);
// XXX hack to force the BasePlot to initialise
final DisplayAdjustmentEvent event =
new DisplayAdjustmentEvent (this,
feature_display.getFirstVisibleForwardBase (),
feature_display.getLastVisibleForwardBase (),
feature_display.getMaxVisibleBases (),
feature_display.getScaleValue (),
feature_display.getScaleFactor (),
feature_display.isRevCompDisplay (),
DisplayAdjustmentEvent.ALL_CHANGE_ADJUST_EVENT);
base_plot_group.displayAdjustmentValueChanged (event);
new MessageDialog (Utilities.getComponentFrame (base_plot_group),
"error while reading user data: " + e);
}
}
frame.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
/**
* Return the JFrame that was passed to the constructor.
**/
return frame;
}
/**
* Return the EntryGroup that was passed to the constructor.
**/