Skip to content
Snippets Groups Projects
Splash.java 36.7 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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");
    
    
    tjc's avatar
    tjc committed
        //ClassLoader cl = this.getClass().getClassLoader();
    
    tjc's avatar
    tjc committed
        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();
    
    tcarver's avatar
    tcarver committed
        setSize(460, 250);
    
    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
    
    
    Sascha Steinbiss's avatar
    Sascha Steinbiss committed
            g.drawString("Copyright 1998 - 2016",
    
    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();
    
    tcarver's avatar
    tcarver committed
              ImageIcon helix_icon = new ImageIcon(cl.getResource("images/PSUlogo.gif"));
    
    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;