Skip to content
Snippets Groups Projects
SelectionMenu.java 17.1 KiB
Newer Older
  • Learn to ignore specific revisions
  • tjc's avatar
    tjc committed
    /* SelectionMenu.java
     *
     * created: Sun Jan 10 1999
     *
     * This file is part of Artemis
     * 
     * Copyright(C) 1998,1999,2000,2001,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.
     *
    
    tjc's avatar
    tjc committed
     * $Header: //tmp/pathsoft/artemis/uk/ac/sanger/artemis/components/SelectionMenu.java,v 1.9 2008-06-11 15:17:43 tjc Exp $
    
    tjc's avatar
    tjc committed
     */
    
    package uk.ac.sanger.artemis.components;
    
    import uk.ac.sanger.artemis.sequence.MarkerRange;
    import uk.ac.sanger.artemis.*;
    
    import java.awt.event.*;
    import javax.swing.*;
    
    tjc's avatar
    tjc committed
    import java.awt.*;
    import java.util.Vector;
    
    tjc's avatar
    tjc committed
    
    /**
     *  This a super class for EditMenu, ViewMenu and GotoMenu.  It is a JMenu that
     *  knows how to get hold of the Selection.  It also has the method
     *  getParentFrame() to find the owning JFrame of the menu.
     *
     *  @author Kim Rutherford
    
    tjc's avatar
    tjc committed
     *  @version $Id: SelectionMenu.java,v 1.9 2008-06-11 15:17:43 tjc Exp $
    
    tjc's avatar
    tjc committed
     **/
    
    public class SelectionMenu extends JMenu 
    {
    
    
      /** */
      private static final long serialVersionUID = 1L;
    
    
    tjc's avatar
    tjc committed
      /** The Selection that was passed to the constructor. */
    
      private Selection selection;
    
    tjc's avatar
    tjc committed
    
      /** The JFrame reference that was passed to the constructor. */
      private JFrame frame = null;
    
      /**
       *  Create a new SelectionMenu object.
       *  @param frame The JFrame that owns this JMenu.
       *  @param name The string to use as the menu title.
       *  @param selection The Selection that the commands in the menu will
       *    operate on.
       **/
      public SelectionMenu(final JFrame frame,
                            final String menu_name,
                            final Selection selection) 
      {
        super(menu_name);
        this.frame = frame;
        this.selection = selection;
      }
    
      /**
       *  Return the JFrame that was passed to the constructor.
       **/
      public JFrame getParentFrame() 
      {
        return frame;
      }
    
      /**
       *  Check that the are some Features in the current selection.  If there are
       *  some features then return true.  If there are no features selected then
       *  popup a message saying so and return false.
       **/
      protected boolean checkForSelectionFeatures() 
      {
        return checkForSelectionFeatures(getParentFrame(), getSelection());
      }
    
      /**
       *  Check that the are some Features in the given selection.  If there are
       *  some features then return true.  If there are no features selected then
       *  popup a message saying so and return false.
       *  @param frame The JFrame to use for MessageDialog components.
       *  @param selection The selected features to check.
       **/
      static boolean checkForSelectionFeatures(final JFrame frame,
                                               final Selection selection) 
      {
        final FeatureVector features_to_check = selection.getAllFeatures();
    
        if(features_to_check.size() == 0) 
        {
          new MessageDialog(frame, "No features selected");
          return false;
        } 
        else 
          return true;
      }
    
      /**
       *  Check that the are some Features in the current selection and that the
       *  selection isn't too big.  If there is more than one feature in the
       *  selection and less than the given maximum then return true.  If there
       *  are no features selected then popup a message saying so and return
       *  false.  If there are more selected features than the given maximum
       *  than display the message in a YesNoDialog component and return the
       *  result of the dialog.
       **/
      protected boolean checkForSelectionFeatures(final int maximum_size,
                                                  final String message) 
      {
        return checkForSelectionFeatures(getParentFrame(), getSelection(),
                                          maximum_size, message);
      }
    
      /**
       *  Check that the are some Features in the given selection and that the
       *  selection isn't too big.  If there is more than one feature in the
       *  selection and less than the given maximum then return true.  If there
       *  are no features selected then popup a message saying so and return
       *  false.  If there are more selected features than the given maximum
       *  than display the message in a YesNoDialog component and return the
       *  result of the dialog.
       *  @param frame The JFrame to use for MessageDialog components.
       *  @param selection The selected features to check.
       **/
      static boolean checkForSelectionFeatures(final JFrame frame,
                                               final Selection selection,
                                               final int maximum_size,
                                               final String message) 
      {
        final FeatureVector features_to_check = selection.getAllFeatures();
    
        if(features_to_check.size() == 0) 
        {
          new MessageDialog(frame, "No features selected");
          return false;
        }
        else 
        {
          if(features_to_check.size() > maximum_size) 
          {
            final YesNoDialog dialog =
              new YesNoDialog(frame, message);
    
            return dialog.getResult();
          }
          else 
            return true;
        }
      }
    
      /**
    
       *  Check that there are only CDS features in the given selection, that there
       *  are some features selected and that the selection isn't too big.  If
       *  there is more than one feature in the selection and less than the given
       *  maximum then return true.  If there are no features selected then popup
       *  a message saying so and return false.  If there are more selected
       *  features than the given maximum than display the message in a
       *  YesNoDialog component and return the result of the dialog.
       *  @param frame The Frame to use for MessageDialog components.
       *  @param selection The selected features to check.
       **/
      static boolean checkForSelectionCDSFeatures(final JFrame frame,
                                                   final Selection selection,
                                                   final int maximum_size,
                                                   final String max_message) 
      {
        final FeatureVector features_to_check = selection.getAllFeatures();
    
        if(features_to_check.size() == 0) 
        {
          new MessageDialog(frame, "No CDS features selected");
          return false;
        }
        else
        {
          for(int i = 0 ; i < features_to_check.size() ; ++i) 
          {
            final Feature this_feature = features_to_check.elementAt(i);
            if(!this_feature.isCDS()) 
            {
              final String message =
                "a non-CDS feature(" + this_feature.getIDString() +
                ") is selected - can't continue";
              final MessageDialog dialog =
                new MessageDialog(frame, message);
              return false;
            }
          }
    
          if(features_to_check.size() > maximum_size) 
          {
            final YesNoDialog dialog =
              new YesNoDialog(frame, max_message);
    
            return dialog.getResult();
          }
          else 
            return true;
        }
      }
    
      /**
       *  Check that the are some FeatureSegments in the current selection and
       *  that the selection isn't too big.  If there is more than one
       *  FeatureSegments in the selection and less than the given maximum then
       *  return true.  If there are no FeatureSegments selected then popup a
       *  message saying so and return false.  If there are more selected
       *  FeatureSegments than the given maximum than display the message in a
       *  YesNoDialog component and return the result of the dialog.
       **/
      protected boolean checkForSelectionFeatureSegments(final int maximum_size,
                                                         final String message) 
      {
        final FeatureSegmentVector segments_to_check =
    
          getSelection().getAllSegments();
    
    tjc's avatar
    tjc committed
    
        if(segments_to_check.size() == 0) 
        {
          new MessageDialog(getParentFrame(), "No exons selected");
          return false;
        } 
        else 
        {
          if(segments_to_check.size() > maximum_size) 
          {
            final YesNoDialog dialog =
              new YesNoDialog(getParentFrame(), message);
    
            return dialog.getResult();
          } 
          else 
            return true;
        }
      }
    
      /**
       *  Check that the current selection contains a MarkerRange.  If it does
       *  then return true.  If not then popup a message saying so and return
       *  false.
       **/
      protected boolean checkForSelectionRange() 
      {
        return checkForSelectionRange(getParentFrame(), getSelection());
      }
    
      /**
       *  Check that the current selection contains a MarkerRange.  If it does
       *  then return true.  If not then popup a message saying so and return
       *  false.
       *  @param frame The JFrame to use for MessageDialog components.
       *  @param selection The selected features to check.
       **/
    
    tjc's avatar
    tjc committed
      public static boolean checkForSelectionRange(final JFrame frame,
    
    tjc's avatar
    tjc committed
                                            final Selection selection) 
      {
        final MarkerRange marker_range = selection.getMarkerRange();
    
        if(marker_range == null) 
        {
          new MessageDialog(frame, "No bases selected");
          return false;
        } 
        else 
          return true;
      }
    
      /**
       *  Return the Selection object that was passed to the constructor.
       **/
      protected Selection getSelection() 
      {
        return selection;
      }
      
      /**
       *
       **/
      protected static KeyStroke makeMenuKeyStroke(final int key_code)
      {
    
        return KeyStroke.getKeyStroke(key_code, 
                      Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()); //InputEvent.CTRL_MASK);
    
    tjc's avatar
    tjc committed
      }
    
    
    tcarver's avatar
    tcarver committed
      private void getJMenuItems(JMenu menu, Vector<JMenuItem> menu_items)
    
    tjc's avatar
    tjc committed
      {
    
    tjc's avatar
    tjc committed
        final Component menus[] = menu.getMenuComponents();
    
    tjc's avatar
    tjc committed
        for(int i=0; i<menus.length; i++)
        {
          if(menus[i] instanceof JMenuItem)
    
    tcarver's avatar
    tcarver committed
            menu_items.add((JMenuItem) menus[i]);
    
    tjc's avatar
    tjc committed
        }
      }
    
    tcarver's avatar
    tcarver committed
      
      private Vector<JMenuItem> getSelectionMenuItems()
    
    tjc's avatar
    tjc committed
      {
    
    tcarver's avatar
    tcarver committed
        final Vector<JMenuItem> menu_items = new Vector<JMenuItem>();
    
    tjc's avatar
    tjc committed
        final Component menus[] = getMenuComponents();
    
    tjc's avatar
    tjc committed
        for(int i=0; i<menus.length; i++)
        {
          if(menus[i] instanceof JMenu)
          {
    
    tcarver's avatar
    tcarver committed
            menu_items.add((JMenu)menus[i]);
    
    tjc's avatar
    tjc committed
            getJMenuItems((JMenu)menus[i], menu_items);
          }
          else if(menus[i] instanceof JMenuItem)
    
    tcarver's avatar
    tcarver committed
            menu_items.add((JMenuItem)menus[i]);
    
    tjc's avatar
    tjc committed
        }
    
    tcarver's avatar
    tcarver committed
        return menu_items;
      }
    
    tjc's avatar
    tjc committed
    
    
    tcarver's avatar
    tcarver committed
      protected Vector<String> getUsedShortCutKeys()
      {
        final Vector<String> sc = new Vector<String>();
        final Vector<JMenuItem> menu_items = getSelectionMenuItems();
        for(JMenuItem mi : menu_items)
          if(mi.getAccelerator() != null)
            sc.add(getKeyText(mi.getAccelerator().getKeyCode()));
        return sc;
      }
      
      protected JScrollPane getShortCuts(Vector<String> usedShortCutKeys)
      {
        usedShortCutKeys.add("C"); // Create menu
        usedShortCutKeys.add("G"); // Goto menu
        final Vector<JMenuItem> menu_items = getSelectionMenuItems();
        final Box bdown = Box.createVerticalBox();
        final String alist[] = 
                 { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
                   "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
                   "W", "X", "Y", "Z", "--"};
        final String mod_list[] = { "Default", "Alt", "Ctrl", "Shift" };
        
        for(final JMenuItem mi : menu_items)
    
    tjc's avatar
    tjc committed
        {
    
    tcarver's avatar
    tcarver committed
          final Box bacross = Box.createHorizontalBox();
          if(mi instanceof JMenu)
    
    tjc's avatar
    tjc committed
          {
    
    tcarver's avatar
    tcarver committed
            bacross.add(new JLabel( mi.getText() ));
    
    tjc's avatar
    tjc committed
            bacross.add(Box.createHorizontalGlue());
            bdown.add(bacross);
            continue;
          }
    
          bacross.add(new JLabel(mi.getText()));
    
    
    tjc's avatar
    tjc committed
    // short cut
    
    tjc's avatar
    tjc committed
          final JComboBox combo = new JComboBox(alist);
    
    tcarver's avatar
    tcarver committed
          combo.setRenderer(new ComboBoxRenderer(usedShortCutKeys));
    
    tjc's avatar
    tjc committed
          final JComboBox mod_combo = new JComboBox(mod_list);
    
    tcarver's avatar
    tcarver committed
          final KeyStroke ks = mi.getAccelerator();
    
    tjc's avatar
    tjc committed
          if(ks != null)
    
    tjc's avatar
    tjc committed
            combo.setSelectedItem( getKeyText(ks.getKeyCode()) );
    
            mod_combo.setSelectedItem( getModifierFromInt(ks.getModifiers()) );
          }
    
    tjc's avatar
    tjc committed
          else
    
    tjc's avatar
    tjc committed
            combo.setSelectedItem("--");
    
            mod_combo.setSelectedItem("Default");
          }
    
    tjc's avatar
    tjc committed
    
          Dimension dim = combo.getPreferredSize();
          dim = new Dimension(100, dim.height);
          combo.setPreferredSize(dim);
          combo.setMaximumSize(dim);
          combo.addItemListener(new ItemListener()
          {
            public void itemStateChanged(ItemEvent e) 
            {
              if(e.getStateChange() == ItemEvent.SELECTED)
    
    tjc's avatar
    tjc committed
                setAccelerator(combo,mod_combo,mi);
            }
          });
    
    // modifier
          mod_combo.setPreferredSize(dim);
          mod_combo.setMaximumSize(dim);
          mod_combo.addItemListener(new ItemListener()
          {
            public void itemStateChanged(ItemEvent e)
            {
              if(e.getStateChange() == ItemEvent.SELECTED)
                setAccelerator(combo,mod_combo,mi);
    
    tjc's avatar
    tjc committed
            }
          });
    
          bacross.add(Box.createHorizontalGlue());
          bacross.add(combo);
    
    tjc's avatar
    tjc committed
          bacross.add(mod_combo);
    
    tjc's avatar
    tjc committed
          bdown.add(bacross);
        }
    
        bdown.add(Box.createVerticalGlue());
    
    
    tjc's avatar
    tjc committed
        final JScrollPane jsp = new JScrollPane(bdown);
    
    tjc's avatar
    tjc committed
        final Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
        jsp.setPreferredSize(new Dimension(jsp.getPreferredSize().width,
                             screen.height/2));
        return jsp;
      }
    
    
    tjc's avatar
    tjc committed
      private void setAccelerator(final JComboBox combo, final JComboBox mod_combo, 
                                  final JMenuItem mi)
      {
        if(combo.getSelectedItem() == "--")
          mi.setAccelerator(null);
        else
        {
          char c[] = ((String)combo.getSelectedItem()).toCharArray();
    
          int modifier = getModifierFromString((String)mod_combo.getSelectedItem()); 
    
    tjc's avatar
    tjc committed
          mi.setAccelerator(KeyStroke.getKeyStroke(c[0], modifier));
        }
    
    
        if(ShortCut.usingCache())
          new ShortCut(getText(), mi.getText(), mi.getAccelerator());
      }
      
      private int getModifierFromString(String modStr)
    
    tjc's avatar
    tjc committed
      {
    
        int modifier = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
        if( modStr.equals("Alt") )
          modifier = InputEvent.ALT_MASK;
        else if( modStr.equals("Ctrl") )
          modifier = InputEvent.CTRL_MASK;
        else if( modStr.equals("Shift") )
          modifier = InputEvent.SHIFT_MASK;
        return modifier;
      }
    
    tjc's avatar
    tjc committed
      
    
      private String getModifierFromInt(int mod)
      {
        if( (InputEvent.ALT_MASK & mod) == InputEvent.ALT_MASK)
          return "Alt";
        else if( (InputEvent.CTRL_MASK & mod) == InputEvent.CTRL_MASK)
          return "Ctrl";
        else if( (InputEvent.SHIFT_MASK & mod) == InputEvent.SHIFT_MASK)
          return "Shift";
        return "Default";
      }
      
    
    tjc's avatar
    tjc committed
      public static String getKeyText(int keyCode)
      {
        if(keyCode >= KeyEvent.VK_0 && keyCode <= KeyEvent.VK_9 ||
           keyCode >= KeyEvent.VK_A && keyCode <= KeyEvent.VK_Z) 
          return String.valueOf((char)keyCode);
        
        switch(keyCode) 
        {
          case KeyEvent.VK_BACK_SPACE: return "BACK_SPACE";
          case KeyEvent.VK_CONTROL: return "CONTROL";
          case KeyEvent.VK_LEFT: return "LEFT";
          case KeyEvent.VK_UP: return "UP";
          case KeyEvent.VK_RIGHT: return "RIGHT";
          case KeyEvent.VK_DOWN: return "DOWN";
        
          case KeyEvent.VK_DELETE: return "DELETE";
        
          case KeyEvent.VK_BACK_QUOTE: return "BACK_QUOTE";
        
          case KeyEvent.VK_KP_UP: return "KP_UP";
          case KeyEvent.VK_KP_DOWN: return "KP_DOWN";
          case KeyEvent.VK_KP_LEFT: return "KP_LEFT";
          case KeyEvent.VK_KP_RIGHT: return "KP_RIGHT";
        }
        
        return "unknown(0x" + Integer.toString(keyCode, 16) + ")";
      }
    
      
      /**
       * True if this menu has editable shortcuts
       * @return
       */
      protected boolean isEditableShortCutMenu()
      {
        if(this instanceof SelectMenu ||
           this instanceof EditMenu ||
           this instanceof ViewMenu )
          return true;
        return false;
      }
      
      /**
       * Override to apply any cached shortcuts
       */
      public JMenuItem add(JMenuItem menuItem)
      {
        JMenuItem mi = super.add(menuItem);
        if(isEditableShortCutMenu() && ShortCut.usingCache())
          ShortCut.applyShortCutFromCache(getText(), menuItem);
        return mi;
      }
      
    
    tjc's avatar
    tjc committed
    }
    
    
    tcarver's avatar
    tcarver committed
    class ComboBoxRenderer implements ListCellRenderer 
    {
      protected DefaultListCellRenderer defaultRenderer = new DefaultListCellRenderer();
      private Vector<String> usedShortCutKeys;
      public ComboBoxRenderer(Vector<String> usedShortCutKeys)
      {
        this.usedShortCutKeys = usedShortCutKeys;
      }
      
      public Component getListCellRendererComponent(JList list, Object value, int index,
          boolean isSelected, boolean cellHasFocus) 
      {
        JLabel renderer = (JLabel) defaultRenderer.getListCellRendererComponent(list, value, index,
            isSelected, cellHasFocus);
        if (usedShortCutKeys.contains(value)) 
          renderer.setBackground(Color.lightGray);
        return renderer;
      }
    }
    
    
    /**
     * Editable shortcut sub-menu
     */
    class SelectionSubMenu extends JMenu
    {
    
    tcarver's avatar
    tcarver committed
      private static final long serialVersionUID = 1L;
    
      private String parentMenuStr;
      public SelectionSubMenu(SelectionMenu parentMenu, String str)
      {
        super(str);
        parentMenuStr = parentMenu.getText();
      }
    
      public JMenuItem add(JMenuItem menuItem)
      {
        JMenuItem mi = super.add(menuItem);
        if(ShortCut.usingCache())
          ShortCut.applyShortCutFromCache(parentMenuStr, menuItem);
        return mi;
      }
    }