Skip to content
Snippets Groups Projects
Splash.java 36.7 KiB
Newer Older
tjc's avatar
tjc committed
/* Splash.java
 *
 * This file is part of Artemis
 *
 * Copyright (C) 2000,2002  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.
 */

package uk.ac.sanger.artemis.components;

import uk.ac.sanger.artemis.Options;
import uk.ac.sanger.artemis.EntrySourceVector;
import uk.ac.sanger.artemis.Logger;
import uk.ac.sanger.artemis.util.InputStreamProgressListener;
import uk.ac.sanger.artemis.util.InputStreamProgressEvent;
tjc's avatar
tjc committed
import uk.ac.sanger.artemis.util.StringVector;
import uk.ac.sanger.artemis.sequence.Bases;
import uk.ac.sanger.artemis.sequence.AminoAcidSequence;
tjc's avatar
tjc committed

tcarver's avatar
tcarver committed
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
tjc's avatar
tjc committed
import java.lang.management.ManagementFactory;
tcarver's avatar
tcarver committed
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Frame;
import java.awt.Graphics;
tcarver's avatar
tcarver committed
import java.awt.Graphics2D;
tcarver's avatar
tcarver committed
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.Point;
tcarver's avatar
tcarver committed
import java.awt.RenderingHints;
tcarver's avatar
tcarver committed
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
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 javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
tjc's avatar
tjc committed
import javax.swing.UIManager.LookAndFeelInfo;
tjc's avatar
tjc committed

tcarver's avatar
tcarver committed
import java.util.Enumeration;
import java.util.Properties;
tjc's avatar
tjc committed

/**
 *  Base class that creates a generic "Splash Screen"
tcarver's avatar
tcarver committed
 *  @author Kim Rutherford
tjc's avatar
tjc committed
 **/

tjc's avatar
tjc committed
abstract public class Splash extends JFrame
tjc's avatar
tjc committed
{
  private static final long serialVersionUID = 1L;
tjc's avatar
tjc committed

tcarver's avatar
tcarver committed
  /** Do any necessary cleanup then exit. */
tjc's avatar
tjc committed
  abstract protected void exit();

tcarver's avatar
tcarver committed
  /** A label for status and error messages. */
tjc's avatar
tjc committed
  final private JLabel status_line = new JLabel("");

tcarver's avatar
tcarver committed
  /** The program name that was passed to the constructor. */
tjc's avatar
tjc committed
  private String program_name;

tcarver's avatar
tcarver committed
  /** program version passed to the constructor. */
tjc's avatar
tjc committed
  private String program_version;

tcarver's avatar
tcarver committed
  /** JComponent to draw the main splash screen into */
tjc's avatar
tjc committed
  private JComponent helix_canvas;

  private JMenuBar menu_bar;
  protected JMenu file_menu;
  protected JMenu options_menu;

  private JCheckBoxMenuItem geneCode[];
tjc's avatar
tjc committed
  private String geneticCode;

  private static boolean save_wd_properties = false;
  public static boolean save_display_name = false;
  public static boolean save_systematic_names = false;
tjc's avatar
tjc committed
  /**  The Artemis LogViewer. */
  private final static LogViewer logger = new LogViewer();
  private static String optionsLogString[];
tjc's avatar
tjc committed
  public static org.apache.log4j.Logger logger4j = 
         org.apache.log4j.Logger.getLogger(Splash.class);
  
  public Splash(final String program_title,
                final String program_name)
  {
    super(program_title);
    initLogger();
    
    logger4j.info(System.getProperty("java.version"));
tjc's avatar
tjc committed
    logger4j.info(System.getProperty("java.vendor"));
    logger4j.info(System.getProperty("java.home"));
    logger4j.info(System.getProperty("os.name"));
tjc's avatar
tjc committed
    logger4j.info("Max. Heap Memory / Mb: "+ManagementFactory.getMemoryMXBean().getHeapMemoryUsage().getMax()/1000000);
    logger4j.info("Starting application: "+program_name);
    
    if(optionsLogString != null)
    {
      for(int i=0; i<optionsLogString.length; i++)
        logger4j.info(optionsLogString[i]);
    }
tjc's avatar
tjc committed
  /**
   *  Create a new JFrame for a Splash screen.
   *  @param program_name The full name of the program.
   *  @param program_title The name to use in the title.
   *  @param program_version The version string.
   **/
  public Splash(final String program_name,
                final String program_title,
                final String program_version) 
  {
    this(program_title+" "+program_version, program_name);
tjc's avatar
tjc committed
    
tjc's avatar
tjc committed
    this.program_name    = program_name;
    this.program_version = program_version;
tjc's avatar
tjc committed
    
    final ClassLoader cl = this.getClass().getClassLoader();
    try
    {
      String line;
      InputStream in = cl.getResourceAsStream("etc/versions");
      BufferedReader reader = new BufferedReader(new InputStreamReader(in));
      while((line = reader.readLine()) != null)
      {
        if(line.startsWith(program_title))
tjc's avatar
tjc committed
        {
tjc's avatar
tjc committed
          this.program_version = line.substring( program_title.length() ).trim();
tjc's avatar
tjc committed
          setTitle(program_title+" "+this.program_version);
        }
tjc's avatar
tjc committed
      }
    }
    catch (Exception ex)
    {
      logger4j.debug(ex.getMessage());
    }
tjc's avatar
tjc committed

    addWindowListener(new WindowAdapter() 
    {
      public void windowClosing(WindowEvent event) 
      {
tjc's avatar
tjc committed
        exitApp();
tjc's avatar
tjc committed
      }
    });

tjc's avatar
tjc committed
    //final javax.swing.LookAndFeel look_and_feel =
    //  javax.swing.UIManager.getLookAndFeel();
tjc's avatar
tjc committed

    final javax.swing.plaf.FontUIResource font_ui_resource =
      Options.getOptions().getFontUIResource();

tcarver's avatar
tcarver committed
    final Enumeration<Object> keys = UIManager.getDefaults().keys();
tjc's avatar
tjc committed
    while(keys.hasMoreElements()) 
    {
      Object key = keys.nextElement();
      Object value = UIManager.get(key);
      if(value instanceof javax.swing.plaf.FontUIResource) 
        UIManager.put(key, font_ui_resource);
    }

    getContentPane().setLayout(new BorderLayout());
    makeAllMenus();
    helix_canvas = makeHelixCanvas();
    status_line.setFont(Options.getOptions().getFont());

tcarver's avatar
tcarver committed
    final int font_height = 
        this.getFontMetrics(status_line.getFont()).getHeight()+10;
tjc's avatar
tjc committed

    status_line.setMinimumSize(new Dimension(100, font_height));
    status_line.setPreferredSize(new Dimension(100, font_height));
tcarver's avatar
tcarver committed
    status_line.setBorder(BorderFactory.createCompoundBorder(
        BorderFactory.createRaisedBevelBorder(), BorderFactory.createLoweredBevelBorder()));
tjc's avatar
tjc committed

    getContentPane().add(helix_canvas, "Center");
    getContentPane().add(status_line, "South");

    ImageIcon icon = new ImageIcon(cl.getResource("images/icon.gif"));

    if(icon != null) 
    {
      final Image icon_image = icon.getImage();
      MediaTracker tracker = new MediaTracker(this);
      tracker.addImage(icon_image, 0);

      try
      {
        tracker.waitForAll();
        setIconImage(icon_image);
      }
      catch(InterruptedException e) 
      {
        // ignore and continue
      }
    }
tjc's avatar
tjc committed
    
tjc's avatar
tjc committed
    pack();
    setSize(455, 290);
tjc's avatar
tjc committed

    final Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
    setLocation(new Point((screen.width - getSize().width) / 2,
                          (screen.height - getSize().height) / 2));
tjc's avatar
tjc committed
    registerForMacOSXEvents();
tjc's avatar
tjc committed
  }

tjc's avatar
tjc committed
  public static void initLogger()
  {
    logger.log("");
    logger.getFileViewer().setHideOnClose(true);
tjc's avatar
tjc committed
    final InputStream options_input_stream =
      Splash.class.getResourceAsStream("/etc/log4j.properties");

    if(options_input_stream != null)
    {
      Properties logProperties = new Properties();
      try
      {
        logProperties.load(options_input_stream);
        org.apache.log4j.PropertyConfigurator.configure(logProperties);
      }
      catch(FileNotFoundException e)
      {
      }
      catch(IOException e)
      {
      }
    }
  }

  public static void appendToLog(String s)
  {
    if(optionsLogString == null)
      optionsLogString = new String[]{s};
    else
    {
      String logStringTmp[] = new String[optionsLogString.length];
      for(int i=0; i<logStringTmp.length; i++)
        logStringTmp[i] = optionsLogString[i];
      optionsLogString = new String[logStringTmp.length+1];
      
      for(int i=0; i<logStringTmp.length; i++)
        optionsLogString[i] = logStringTmp[i];
      
      optionsLogString[optionsLogString.length-1] = s;
    }
  }
tjc's avatar
tjc committed
  
tjc's avatar
tjc committed
  /**
   * Generic registration with the Mac OS X application menu
   * Checks the platform, then attempts to register with the Apple EAWT
   */
  private void registerForMacOSXEvents()
  {
    if(isWindows())
      setWorkingDirectory();
tjc's avatar
tjc committed
    if(isMac()) 
    {
      setWorkingDirectory();
tjc's avatar
tjc committed
      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
tcarver's avatar
tcarver committed
        Class<?> splashClass = Class.forName("uk.ac.sanger.artemis.components.Splash");
tjc's avatar
tjc committed
        OSXAdapter.setQuitHandler(this, 
            splashClass.getDeclaredMethod("exitApp", (Class[])null));
        OSXAdapter.setAboutHandler(this, 
            splashClass.getDeclaredMethod("about", (Class[])null));
        //OSXAdapter.setPreferencesHandler(this, 
        //  splashClass.getDeclaredMethod("preferences", (Class[])null));
        OSXAdapter.setFileHandler(this, 
            splashClass.getDeclaredMethod("loadFile", new Class[] { String.class }));
      } 
      catch (Exception e)
      {
        logger4j.error("Error while loading the OSXAdapter:");
        logger4j.error(e.getMessage());
      }
    }
    logger4j.info("Working directory: "+System.getProperty("user.dir"));
  }
  
tjc's avatar
tjc committed
  private boolean isMac() 
  {
tcarver's avatar
tcarver committed
    return System.getProperty("mrj.version") != null ||
           System.getProperty("os.name").toLowerCase().indexOf("mac") >= 0;
tjc's avatar
tjc committed
  }
  
  private boolean isWindows() 
  {  
    String os = System.getProperty("os.name").toLowerCase();
    logger4j.info("os.name "+os);
    return (os.indexOf("win") >= 0);
  }
tjc's avatar
tjc committed
 
tjc's avatar
tjc committed
  protected void about()
tjc's avatar
tjc committed
  {
    ClassLoader cl = this.getClass().getClassLoader();
    ImageIcon icon = new ImageIcon(cl.getResource("images/icon.gif"));

    JOptionPane.showMessageDialog(this,
            getTitle()+ "\nthis is free software and is distributed"+
                        "\nunder the terms of the GNU General Public License.",
            "About", JOptionPane.INFORMATION_MESSAGE,
            icon);
tjc's avatar
tjc committed
  }
  
  /**
   * Web start properties need to begin with "javaws." or "jnlp.
   */
  protected static void processJnlpAttributes()
  {
    // JNLP properties
    final Properties properties = System.getProperties();
    for(String key : properties.stringPropertyNames())
    {
      if( key.equals("jnlp.black_belt_mode") ||
          key.equals("jnlp.chado") ||
          key.equals("jnlp.offset") ||
          key.equals("jnlp.artemis.environment") ||
          key.equals("jnlp.sanger_options") ||
          key.equals("jnlp.read_only") || 
          key.startsWith("jnlp.bam") ||
          key.startsWith("jnlp.userplot") ||
          key.startsWith("jnlp.loguserplot") ||
          key.startsWith("jnlp.show_") )
        System.setProperty(key.substring(5), System.getProperty(key));
    }
  }
  
tjc's avatar
tjc committed
  protected void loadFile(final String fileName)
  {
    if(this instanceof ArtemisMain)
      ((ArtemisMain)this).readArgsAndOptions(new String[]{ fileName }, this);
tjc's avatar
tjc committed
  }


tjc's avatar
tjc committed
  /**
   *  Return a JComponent object that will display a helix and a short
   *  copyright notice.
   **/
  private JComponent makeHelixCanvas() 
  {
tjc's avatar
tjc committed
    return new JPanel() 
    {
      /** */
      private static final long serialVersionUID = 1L;

tjc's avatar
tjc committed
      public void update(Graphics g) 
      {
        paint(g);
      }

      /**
       *  Draws the splash screen text.
       **/
tcarver's avatar
tcarver committed
      public int textPaint(final Graphics graphics)
tjc's avatar
tjc committed
      {
tcarver's avatar
tcarver committed
        FontMetrics fm = this.getFontMetrics(graphics.getFont());
tjc's avatar
tjc committed
        final int font_height = fm.getHeight() + 3;
tcarver's avatar
tcarver committed
        
        Graphics2D g = (Graphics2D) graphics;
        g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                           RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        
tjc's avatar
tjc committed
        g.setColor(Color.black);
tjc's avatar
tjc committed
        final int left_margin = 150;
        final int yPos = helix_height+5;
tjc's avatar
tjc committed

        g.drawString(program_name,
tjc's avatar
tjc committed
                     left_margin, yPos+font_height);
tjc's avatar
tjc committed
        g.drawString(program_version,
tjc's avatar
tjc committed
                     left_margin, yPos+(font_height * 2));
tjc's avatar
tjc committed
        g.drawString(geneticCode,
tjc's avatar
tjc committed
                     left_margin, yPos+(font_height * 3));
tjc's avatar
tjc committed

tjc's avatar
tjc committed
                     left_margin, yPos+(font_height * 9 / 2));
tjc's avatar
tjc committed
        g.drawString("Genome Research Limited",
tjc's avatar
tjc committed
                     left_margin, yPos+(font_height * 11 / 2));
tjc's avatar
tjc committed

        return font_height;
      }

      public void paint(final Graphics g) 
      {
tjc's avatar
tjc committed
        /*final boolean simple_splash_screen =
          Options.getOptions().getPropertyTruthValue("simple_splash_screen");*/
tjc's avatar
tjc committed

        g.setColor(Color.white);

        g.fillRect(0, 0, this.getSize().width, this.getSize().height);

        if(helix == null) 
        {
          ClassLoader cl = this.getClass().getClassLoader();
“kpepper”'s avatar
“kpepper” committed
          ImageIcon helix_icon = new ImageIcon(cl.getResource("images/Wellcome_Sanger_Institute_Logo_Landscape_Digital_RGB_Full_Colour.jpg"));
tjc's avatar
tjc committed
          helix = helix_icon.getImage();

          tracker = new MediaTracker(this);
          tracker.addImage(helix, 0);

          try 
          {
            tracker.waitForAll();
            helix_height = helix.getHeight(this);
tjc's avatar
tjc committed
            //helix_width = helix.getWidth(this);
tjc's avatar
tjc committed
          }
          catch(InterruptedException e) 
          {
            return;
          }
        }

tjc's avatar
tjc committed
        g.drawImage(helix,
                    0, 0, this);
                    //helix_height, this);
tjc's avatar
tjc committed

tjc's avatar
tjc committed
        textPaint(g);
tjc's avatar
tjc committed
      }

tcarver's avatar
tcarver committed
      private MediaTracker tracker = null;
tjc's avatar
tjc committed

tcarver's avatar
tcarver committed
      /** Sanger DNA logo.  This is set in paint() */
tjc's avatar
tjc committed
      private Image helix = null;


tcarver's avatar
tcarver committed
      /** height of the Sanger DNA logo.  This is set in paint(). */
tjc's avatar
tjc committed
      private int helix_height;

    };
  }

  /**
   *  Return the reference of the Label used as a status line.
   **/
  public JLabel getStatusLabel() 
  {
    return status_line;
  }

  /**
   *  The possible sources for reading Entry objects.
   **/
  public EntrySourceVector getEntrySources(final JFrame frame) 
  {
    return Utilities.getEntrySources(frame, stream_progress_listener);
  }

  /**
   *  Return an InputStreamProgressListener which updates the error label with
   *  the current number of chars read while reading
   **/
  public InputStreamProgressListener getInputStreamProgressListener() 
  {
    return stream_progress_listener;
  }

  /**
   *  Force the options files to be re-read and the EntryEdit components to be
   *  redisplayed.
   **/
  private void resetOptions() 
  {
    Options.getOptions().reset();
  }

  /**
   *  Make all the menus and menu items for the main window.  Also sets up
   *  suitable ActionListener objects for each item.
   */
  private void makeAllMenus() 
  {
    menu_bar = new JMenuBar();
    file_menu = new JMenu("File");
tjc's avatar
tjc committed
    file_menu.setMnemonic(KeyEvent.VK_F);

tjc's avatar
tjc committed
    options_menu = new JMenu("Options");
tjc's avatar
tjc committed
    options_menu.setMnemonic(KeyEvent.VK_O);
tjc's avatar
tjc committed

    menu_bar.add(file_menu);
    menu_bar.add(options_menu);

    setJMenuBar(menu_bar);

tjc's avatar
tjc committed
    ActionListener menu_listener = new ActionListener() 
tjc's avatar
tjc committed
    {
      public void actionPerformed(ActionEvent event) 
      {
        resetOptions();
      }
    };
    makeMenuItem(options_menu, "Re-read Options", menu_listener);

    final JCheckBoxMenuItem enable_direct_edit_item =
      new JCheckBoxMenuItem("Enable Direct Editing");
    enable_direct_edit_item.setState(Options.getOptions().canDirectEdit());
    enable_direct_edit_item.addItemListener(new ItemListener() 
    {
      public void itemStateChanged(ItemEvent event) 
      {
        final boolean item_state = enable_direct_edit_item.getState();
        Options.getOptions().setDirectEdit(item_state);
      }
    });
    options_menu.add(enable_direct_edit_item);

    options_menu.addSeparator();
    options_menu.add(new JLabel(" --- Genetic Codes Tables ---"));

    makeGeneticCodeMenu(options_menu);
    options_menu.addSeparator();

tjc's avatar
tjc committed
    final JCheckBoxMenuItem j2ssh_option = new JCheckBoxMenuItem(
                                         "Send Searches via SSH");
tjc's avatar
tjc committed

tcarver's avatar
tcarver committed
    j2ssh_option.setState((System.getProperty("j2ssh") != null));
tjc's avatar
tjc committed
    j2ssh_option.addItemListener(new ItemListener() 
    {
      public void itemStateChanged(ItemEvent event) 
      {
        final boolean item_state = j2ssh_option.getState();
        if(item_state) 
          System.setProperty("j2ssh", "");
        else
          System.setProperty("j2ssh", "false");
      }
    });
    options_menu.add(j2ssh_option);
    options_menu.addSeparator();
tcarver's avatar
tcarver committed

    final JCheckBoxMenuItem autohide_option = new JCheckBoxMenuItem(
                                         "Auto hide scrollbar");
tcarver's avatar
tcarver committed
    autohide_option.setState((System.getProperty("autohide") != null));

    autohide_option.addItemListener(new ItemListener()
    {
      public void itemStateChanged(ItemEvent event)
      {
        final boolean item_state = autohide_option.getState();
        if(item_state)
          System.setProperty("autohide", "");
        else
          System.setProperty("autohide", "false");
      }
    });
    options_menu.add(autohide_option);
    options_menu.addSeparator();
    final JCheckBoxMenuItem highlight_active_entry_item =
      new JCheckBoxMenuItem("Highlight Active Entry");
    final boolean highlight_active_entry_state =
      Options.getOptions().highlightActiveEntryFlag();
    highlight_active_entry_item.setState(highlight_active_entry_state);
    highlight_active_entry_item.addItemListener(new ItemListener() 
    {
      public void itemStateChanged(ItemEvent event) 
      {
        final boolean item_state = highlight_active_entry_item.getState();
        Options.getOptions().setHighlightActiveEntryFlag(item_state);
      }
    });
    options_menu.add(highlight_active_entry_item);

tjc's avatar
tjc committed
    if(Options.getOptions().getProperty("black_belt_mode") != null) 
    {
      final JCheckBoxMenuItem black_belt_mode_item =
        new JCheckBoxMenuItem("Black Belt Mode");
tcarver's avatar
tcarver committed

      black_belt_mode_item.setState(Options.isBlackBeltMode());
      black_belt_mode_item.addItemListener(new ItemListener() 
      {
        public void itemStateChanged(ItemEvent event) 
        {
          final boolean item_state = black_belt_mode_item.getState();
          if(item_state) 
            Options.getOptions().put("black_belt_mode", "true");
          else 
            Options.getOptions().put("black_belt_mode", "false");
        }
      });
      options_menu.add(black_belt_mode_item);
    }

tjc's avatar
tjc committed
    options_menu.addSeparator();
    menu_listener = new ActionListener() 
tjc's avatar
tjc committed
      public void actionPerformed(ActionEvent event) 
tjc's avatar
tjc committed
        showLog();
      }
    };
    makeMenuItem(options_menu, "Show Log Window", menu_listener);
    menu_listener = new ActionListener()
    {
      public void actionPerformed(ActionEvent event)
      {
        Options.getOptions().setProperty("artemis.user.dir.prompt","yes"); 
        setWorkingDirectory();
      }
    };
    makeMenuItem(options_menu, "Set Working Directory...", menu_listener);
tjc's avatar
tjc committed
    JMenu lafMenu = new JMenu("Look and Feel");
    final LookAndFeelInfo[] lafInfo = UIManager.getInstalledLookAndFeels();
    ButtonGroup group = new ButtonGroup();
    for(int i=0; i<lafInfo.length; i++)
    {
      JCheckBoxMenuItem laf = new JCheckBoxMenuItem(lafInfo[i].getName());
      group.add(laf);
      lafMenu.add(laf);
      final LookAndFeelInfo thisLAF = lafInfo[i];
      
      if(UIManager.getLookAndFeel().getClass().getName().equals(thisLAF.getClassName()))
        laf.setSelected(true);
      
      laf.addItemListener(new ItemListener() 
      {
        public void itemStateChanged(ItemEvent event) 
        {
          if(event.getStateChange() == ItemEvent.DESELECTED)
            return;
          
          Frame[] frames = JFrame.getFrames();
          try
          {
            UIManager.setLookAndFeel(thisLAF.getClassName());
          }
          catch(Exception e1)
          {
            e1.printStackTrace();
            return;
          }

          for(int i = 0; i < frames.length; i++)
          {
            SwingUtilities.updateComponentTreeUI(frames[i]);
            frames[i].repaint();
          }
          logger4j.debug("Set look and feel to: " + thisLAF.getClassName());
        }
      });
    }
    options_menu.add(lafMenu);
tjc's avatar
tjc committed
    
    // list JFrames that are open
    final JMenu framesMenu = new JMenu("Windows");
    menu_bar.add(framesMenu);
    framesMenu.addItemListener(new ItemListener()
    {
      public void itemStateChanged(ItemEvent event)
      {
        framesMenu.removeAll();
        Frame[] frames = JFrame.getFrames();
        for(int i=0;i<frames.length;i++)
        {
          if( !(frames[i] instanceof JFrame) ||
              !frames[i].isVisible())
            continue;
          
          final JFrame thisFrame = (JFrame)frames[i];
          JCheckBoxMenuItem menuItem = new JCheckBoxMenuItem(thisFrame.getTitle(), false);
          if(thisFrame.isActive())
            menuItem.setSelected(true);
          framesMenu.add(menuItem);
          
          menuItem.addActionListener(new ActionListener()
          {
            public void actionPerformed(ActionEvent e)
            {
              thisFrame.toFront();
              thisFrame.requestFocus();
            }
          });
        }
      }
    });
tjc's avatar
tjc committed
  }

  /**
   *
   * Set the working directory, used by the file manager.
   *
   */
  public static void setWorkingDirectory()
  {
    final JTextField wdir = new JTextField(System.getProperty("user.dir")+"   ");

    if(Options.getOptions() != null &&
       Options.getOptions().getProperty("artemis.user.dir") != null)
      wdir.setText( Options.getOptions().getProperty("artemis.user.dir") );

    if( Options.getOptions().getProperty("artemis.user.dir.prompt") != null &&
       !Options.getOptions().getPropertyTruthValue("artemis.user.dir.prompt") )
      return;
    
tjc's avatar
tjc committed
    Box bdown   = Box.createVerticalBox();
    Box bacross = Box.createHorizontalBox();
    JButton browse = new JButton("Browse...");
    browse.addActionListener(new ActionListener ()
    {
      public void actionPerformed (ActionEvent e)
      {
        final StickyFileChooser file_dialog = new StickyFileChooser();
        file_dialog.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        final int status = file_dialog.showOpenDialog(null);
        if(status == JFileChooser.APPROVE_OPTION)
          wdir.setText(file_dialog.getSelectedFile().getAbsolutePath());
      }
    });
    bacross.add(wdir);
    bacross.add(browse);
    bdown.add(bacross);

    bacross = Box.createHorizontalBox();
    JCheckBox saveDir = new JCheckBox("Save between sessions", false);
tjc's avatar
tjc committed
    bacross.add(saveDir);
    bacross.add(Box.createHorizontalGlue());
    bdown.add(bacross);
    
    
    bacross = Box.createHorizontalBox();
    JCheckBox hide = new JCheckBox("Do not show this prompt again", false);
    bacross.add(hide);
    bacross.add(Box.createHorizontalGlue());
    bdown.add(bacross);
    
    
tjc's avatar
tjc committed
    Object[] possibleValues = { "OK" };
tjc's avatar
tjc committed
    JOptionPane.showOptionDialog(null,
tjc's avatar
tjc committed
                               bdown,
                               "Set Working Directory",
                               JOptionPane.DEFAULT_OPTION,
                               JOptionPane.QUESTION_MESSAGE,null,
                               possibleValues, possibleValues[0]);

    if(hide.isSelected() || 
       Options.getOptions().getProperty("artemis.user.dir.prompt") != null )
    {
      Options.getOptions().setProperty("artemis.user.dir.prompt",
          Boolean.toString(!hide.isSelected())); 
    }
    
tjc's avatar
tjc committed
    if( (new File(wdir.getText().trim())).exists() )
    {
      System.setProperty("user.dir", wdir.getText().trim());
      if(saveDir.isSelected())
        save_wd_properties = true;
tjc's avatar
tjc committed
    }
  }

  protected static void exitApp()
  {
    if(save_wd_properties    || save_display_name || save_systematic_names || 
       Options.getOptions().getProperty("artemis.user.dir.prompt") != null)
tjc's avatar
tjc committed
      saveProperties();
    
    // write the user project properties
    ProjectProperty.writeProperties();
tjc's avatar
tjc committed
    System.exit(0);
  }

  /**
   *
   * Save properties (working directory) between sessions.
   *
   */
  private static void saveProperties()
  {
    String uhome = System.getProperty("user.home");
    String fs = System.getProperty("file.separator");
    String prop = uhome+fs+".artemis_options";

    writeProperties(prop);
tjc's avatar
tjc committed
  }

  /**
  *
  * Write or re-write properties and insert/update the user.dir property
  * @param jemProp      properties file
  * @param uHome        user working directory
  *
  */
tcarver's avatar
tcarver committed
  private static void writeProperties(final String prop)
tjc's avatar
tjc committed
  {
     File file_txt = new File(prop);
     File file_tmp = new File(prop + ".tmp");
     try
     {
       if(file_txt.exists())
       {
         BufferedReader bufferedreader = new BufferedReader(new FileReader(file_txt));
         BufferedWriter bufferedwriter = new BufferedWriter(new FileWriter(file_tmp));
         String line;
tjc's avatar
tjc committed
         
         boolean prompt_saved = false;
         
tjc's avatar
tjc committed
         while ((line = bufferedreader.readLine()) != null)
         {
           if(line.startsWith("artemis.user.dir") && save_wd_properties)
           {
             line = addEscapeChars("artemis.user.dir="+System.getProperty("user.dir"));
             save_wd_properties = false;
           }
           
           if(line.startsWith("artemis.user.dir.prompt"))
           {
             line = addEscapeChars("artemis.user.dir.prompt="+ 
                 Options.getOptions().getProperty("artemis.user.dir.prompt"));
tjc's avatar
tjc committed
             prompt_saved = true;

           if(line.startsWith("display_name_qualifiers") && save_display_name)
           {
             String str = "display_name_qualifiers=";
             StringVector strs = Options.getOptions().getDisplayQualifierNames();
             for(int i=0; i<strs.size(); i++)
               str = str.concat(" "+strs.get(i));
             line = addEscapeChars(str);
             save_display_name = false;
           }
           
           if(line.startsWith("systematic_name_qualifiers") && save_systematic_names)
           {
             String str = "systematic_name_qualifiers=";
             StringVector strs = Options.getOptions().getSystematicQualifierNames();
             for(int i=0; i<strs.size(); i++)
               str = str.concat(" "+strs.get(i));
             line = addEscapeChars(str);
             save_systematic_names = false;
           }
tjc's avatar
tjc committed
           bufferedwriter.write(line);
           bufferedwriter.newLine();
         }
         
         if(save_wd_properties)
         {
           bufferedwriter.write(
               addEscapeChars("artemis.user.dir="+System.getProperty("user.dir")));
           bufferedwriter.newLine();
         }
tjc's avatar
tjc committed
         if(!prompt_saved && Options.getOptions().getProperty("artemis.user.dir.prompt") != null)
         {
           bufferedwriter.write("artemis.user.dir.prompt="+ 
               Options.getOptions().getProperty("artemis.user.dir.prompt"));
           bufferedwriter.newLine();
         }
         
         if(save_display_name)
         {
           String str = "display_name_qualifiers=";
           StringVector strs = Options.getOptions().getDisplayQualifierNames();
           for(int i=0; i<strs.size(); i++)
             str = str.concat(" "+strs.get(i));
           bufferedwriter.write(addEscapeChars(str));
           bufferedwriter.newLine();
         }
         
         if(save_systematic_names)
         {
           String str = "systematic_name_qualifiers=";
           StringVector strs = Options.getOptions().getSystematicQualifierNames();
           for(int i=0; i<strs.size(); i++)
             str = str.concat(" "+strs.get(i));
           bufferedwriter.write(addEscapeChars(str));
           bufferedwriter.newLine();
         }
         
tjc's avatar
tjc committed
         bufferedreader.close();
         bufferedwriter.close();
         file_txt.delete();
         file_tmp.renameTo(file_txt);
       }
       else // no existing options file
tjc's avatar
tjc committed
       {
         BufferedWriter bufferedwriter = new BufferedWriter(new FileWriter(file_txt));
         
         if(save_wd_properties)
         {
           bufferedwriter.write(
               addEscapeChars("artemis.user.dir="+System.getProperty("user.dir")));
           bufferedwriter.newLine();
         }
         
         if(save_display_name)
         {
           String str = "display_name_qualifiers=";
           StringVector strs = Options.getOptions().getDisplayQualifierNames();
           for(int i=0; i<strs.size(); i++)
             str = str.concat(" "+strs.get(i));
           bufferedwriter.write(addEscapeChars(str));
           bufferedwriter.newLine();
         }
         
         if(save_systematic_names)
         {
           String str = "systematic_name_qualifiers=";
           StringVector strs = Options.getOptions().getSystematicQualifierNames();
           for(int i=0; i<strs.size(); i++)
             str = str.concat(" "+strs.get(i));
           bufferedwriter.write(addEscapeChars(str));
           bufferedwriter.newLine();
         }
tjc's avatar
tjc committed
         bufferedwriter.close();
       }
     }
     catch (FileNotFoundException filenotfoundexception)
     {
tcarver's avatar
tcarver committed
       System.err.println(prop+" read error");
tjc's avatar
tjc committed
     }
     catch (IOException e)
     {
tcarver's avatar
tcarver committed
       System.err.println(prop+" i/o error");
tjc's avatar
tjc committed
     }

  }


  /**
  *
  * Add in escape chars (for windows) to the backslash chars
  * @param l    string to insert escape characters to
  *
  */
  private static String addEscapeChars(String l)
  {
    int n = l.indexOf("\\");

    while( n > -1)
    {
      l = l.substring(0,n)+"\\"+l.substring(n,l.length());
      n = l.indexOf("\\",n+2);
    }
    return l;
  }

  /**
  *
  * Construct menu for genetic code tables.
  *
  */
  private void makeGeneticCodeMenu(final JMenu options_menu)
tjc's avatar
tjc committed
    // available genetic codes
tjc's avatar
tjc committed
    StringVector v_genetic_codes = Options.getOptions().getOptionValues("genetic_codes");
    String gcodes[] = (String[])v_genetic_codes.toArray(new String[v_genetic_codes.size()]);
tjc's avatar
tjc committed

    // get the default
    StringVector gcode_default = Options.getOptions().getOptionValues("genetic_code_default");

    // determine default genetic code table
    int default_code = 0;
    if(gcode_default != null)