home *** CD-ROM | disk | FTP | other *** search
/ Java 1.2 How-To / JavaHowTo.iso / 3rdParty / jbuilder / unsupported / JDK1.2beta3 / SOURCE / SRC.ZIP / java / awt / swing / JMenuBar.java < prev    next >
Encoding:
Java Source  |  1998-03-20  |  17.4 KB  |  603 lines

  1. /*
  2.  * @(#)JMenuBar.java    1.49 98/02/05
  3.  *
  4.  * Copyright (c) 1997 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  */
  20.  
  21. package java.awt.swing;
  22.  
  23. import java.awt.Component;
  24. import java.awt.Dimension;
  25. import java.awt.Graphics;
  26. import java.awt.Insets;
  27. import java.awt.LayoutManager;
  28. import java.awt.Point;
  29. import java.awt.Rectangle;
  30. import java.awt.event.*;
  31. import java.util.Vector;
  32. import java.util.Enumeration;
  33.  
  34. import java.io.Serializable;
  35. import java.io.ObjectOutputStream;
  36. import java.io.ObjectInputStream;
  37. import java.io.IOException;
  38.  
  39. import java.awt.swing.event.*;
  40. import java.awt.swing.border.Border;
  41. import java.awt.swing.plaf.*;
  42. import java.awt.accessibility.*;
  43.  
  44. /**
  45.  * An implementation of a MenuBar. You add JMenu objects to the
  46.  * menu bar to construct a menu. When the user selects a JMenu
  47.  * object, its associated JPopupMenu is displayed, allowing the
  48.  * user to select one of the JMenuItems on it.
  49.  * <p>
  50.  * Warning: serialized objects of this class will not be compatible with
  51.  * future swing releases.  The current serialization support is appropriate 
  52.  * for short term storage or RMI between Swing1.0 applications.  It will
  53.  * not be possible to load serialized Swing1.0 objects with future releases
  54.  * of Swing.  The JDK1.2 release of Swing will be the compatibility
  55.  * baseline for the serialized form of Swing objects.
  56.  *
  57.  * @version 1.49 02/05/98
  58.  * @author Georges Saab
  59.  * @author David Karlton
  60.  * @author Arnaud Weber
  61.  * @see JMenu
  62.  * @see JPopupMenu
  63.  * @see JMenuItem
  64.  */
  65. public class JMenuBar extends JComponent implements Accessible,MenuElement
  66. {    
  67.     /*
  68.      * Model for the selected subcontrol
  69.      */
  70.     private transient SingleSelectionModel selectionModel;
  71.  
  72.     private boolean paintBorder           = true;
  73.     private Insets     margin             = null;
  74.  
  75.     /**
  76.      * Creates a new menu bar.
  77.      */
  78.     public JMenuBar() {
  79.         super();
  80.         setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
  81.         setSelectionModel(new DefaultSingleSelectionModel());
  82.         updateUI();
  83.     }
  84.  
  85.     /**
  86.      * Returns the menubar's current UI.
  87.      * @see setUI
  88.      */
  89.     public MenuBarUI getUI() {
  90.         return (MenuBarUI)ui;
  91.     }
  92.     
  93.     /**
  94.      * Sets the L&F object that renders this component.
  95.      *
  96.      * @param ui the new MenuBarUI L&F object
  97.      * @see UIDefaults#getUI
  98.      */
  99.     public void setUI(MenuBarUI ui) {
  100.         super.setUI(ui);
  101.     }
  102.     
  103.     /**
  104.      * Notification from the UIFactory that the L&F has changed. 
  105.      * Called to replace the UI with the latest version from the 
  106.      * UIFactory.
  107.      *
  108.      * @see JComponent#updateUI
  109.      */
  110.     public void updateUI() {
  111.         setUI((MenuBarUI)UIManager.getUI(this));
  112.     }
  113.  
  114.  
  115.     /**
  116.      * Returns the name of the L&F class that renders this component.
  117.      *
  118.      * @return "MenuBarUI"
  119.      * @see JComponent#getUIClassID
  120.      * @see UIDefaults#getUI
  121.      */
  122.     public String getUIClassID() {
  123.         return "MenuBarUI";
  124.     }
  125.  
  126.  
  127.     /**
  128.      * Returns the model object that handles single selections.
  129.      *
  130.      * @return the SingleSelectionModel in use
  131.      * @see SingleSelectionModel
  132.      */
  133.     public SingleSelectionModel getSelectionModel() {
  134.         return selectionModel;
  135.     }
  136.  
  137.     /**
  138.      * Set the model object to handle single selections.
  139.      *
  140.      * @param model the SingleSelectionModel to use
  141.      * @see SingleSelectionModel
  142.      */
  143.     public void setSelectionModel(SingleSelectionModel model) {
  144.         final JMenuBar thisMenuBar = this;
  145.         selectionModel = model;
  146.     }
  147.  
  148.  
  149.     /**
  150.      * Appends the specified menu to the end of the menu bar.
  151.      *
  152.      * @param c the JMenu component to add
  153.      */
  154.     public JMenu add(JMenu c) {
  155.         Dimension size = c.getSize();
  156.         size.height = Short.MAX_VALUE;
  157.         // c.setMaximumSize(size);
  158.         super.add(c);
  159.         getUI().registerMenu(c);
  160.         return c;
  161.     }
  162.  
  163.     /**
  164.      * Gets the menu at the specified position in the menu bar.
  165.      *
  166.      * @param index  an int giving the position in the menu bar, where
  167.      *               0 is the first position
  168.      * @return the JMenu at that position
  169.      */
  170.     public JMenu getMenu(int index) {
  171.         Component c = getComponentAtIndex(index);
  172.         if (c instanceof JMenu) 
  173.             return (JMenu) c;
  174.         return null;
  175.     }
  176.  
  177.     /**
  178.      * Returns the number of items in the menu bar.
  179.      *
  180.      * @return the number of items in the menu bar
  181.      */
  182.     public int getMenuCount() {
  183.         return getComponentCount();
  184.     }
  185.  
  186.     /**
  187.      * Removes the component at the specified index.
  188.      *
  189.      * @param index  an int specifying the menu bar position, where 0 = first
  190.      */
  191.     public void remove(int index) {
  192.         Component c = getComponent(index);
  193.         if(c instanceof JMenu)
  194.             getUI().unregisterMenu((JMenu)c);
  195.         super.remove(index);
  196.     }
  197.  
  198.     /**
  199.      * Sets the help menu that appears when the user selects the
  200.      * "help" option in the menu bar.
  201.      *
  202.      * @param menu the JMenu that delivers help to the user
  203.      */
  204.     public void setHelpMenu(JMenu menu) {
  205.         throw new Error("setHelpMenu() not yet implemented.");
  206.     }
  207.  
  208.     /**
  209.      * Gets the help menu for the menu bar.
  210.      *
  211.      * @return the JMenu that delivers help to the user
  212.      */
  213.     public JMenu getHelpMenu() {
  214.         throw new Error("getHelpMenu() not yet implemented.");
  215.     }
  216.  
  217.     /**
  218.      * Returns the component at the specified index.
  219.      *
  220.      * @param i an int specifying the position, where 0 = first
  221.      * @return the Component at the position, or null for an
  222.      *         invalid index
  223.      */
  224.     public Component getComponentAtIndex(int i) {
  225.         int ncomponents = this.getComponentCount();
  226.         if (i <= ncomponents) {
  227.             Component[] component = this.getComponents();
  228.             return component[i];
  229.         }
  230.         return null;
  231.     }
  232.  
  233.     /**
  234.      * Returns the index of the specified component.
  235.      *
  236.      * @param c  the Component to find
  237.      * @return an int giving the component's position, where 0 = first
  238.      */
  239.     public int getComponentIndex(Component c) {
  240.         int ncomponents = this.getComponentCount();
  241.         Component[] component = this.getComponents();
  242.         for (int i = 0 ; i < ncomponents ; i++) {
  243.             Component comp = component[i];
  244.             if (comp == c) 
  245.                 return i;
  246.         }
  247.         return -1;
  248.     }
  249.  
  250.     /**
  251.      * Sets the currently selected component, producing a
  252.      * a change to the selection model.
  253.      *
  254.      * @param sel the Component to select
  255.      */
  256.     public void setSelected(Component sel) {    
  257.         SingleSelectionModel model = getSelectionModel();
  258.         int index = getComponentIndex(sel);
  259.         model.setSelectedIndex(index);
  260.     }
  261.  
  262.     /**
  263.      * Returns true if the MenuBar currently has a component selected
  264.      *
  265.      * @return true if a selection has been made, else false
  266.      */
  267.     public boolean isSelected() {       
  268.         return selectionModel.isSelected();
  269.     }
  270.  
  271.     /** 
  272.      * Returns true if a the Menubar's border should be painted.
  273.      *
  274.      * @return  true if the border should be painted, else false
  275.      */
  276.     public boolean isBorderPainted() {
  277.         return paintBorder;
  278.     }
  279.  
  280.     /** 
  281.      * Determines whether the MenuBar's current border will be painted.
  282.      *
  283.      * @param s  true if the border should be painted, else false
  284.      */
  285.     public void setBorderPainted(boolean s) {
  286.         paintBorder = s;
  287.     }
  288.  
  289.     /**
  290.      * Paint the menubar's border if BorderPainted property is true.
  291.      * 
  292.      * @param g the Graphics context to use for painting
  293.      * @see JComponent#paint
  294.      * @see JComponent#setBorder
  295.      */
  296.     protected void paintBorder(Graphics g) {    
  297.         if (isBorderPainted()) {
  298.             super.paintBorder(g);
  299.         }
  300.     }
  301.  
  302.     /**
  303.      * Sets the margin between the menubar's border and
  304.      * its menus. Setting to null will cause the menubar to
  305.      * use the default margins.
  306.      *
  307.      * @param margin an Insets object containing the margin values
  308.      * @see Insets
  309.      */
  310.     public void setMargin(Insets margin) {
  311.         this.margin = margin;
  312.         invalidate();
  313.     }
  314.  
  315.     /**
  316.      * Returns the margin between the menubar's border and
  317.      * its menus.
  318.      * 
  319.      * @return an Insets object containing the margin values
  320.      * @see Insets
  321.      */
  322.     public Insets getMargin() {
  323.         if(margin == null) {
  324.             return new Insets(0,0,0,0);
  325.         } else {
  326.             return margin;
  327.         }
  328.     }
  329.  
  330.  
  331.     /**
  332.      * Implemented to be a MenuElement -- does nothing. 
  333.      *
  334.      * @see #getSubElements
  335.      */
  336.     public void processMouseEvent(MouseEvent event,MenuElement path[],MenuSelectionManager manager) {
  337.     }
  338.  
  339.     /**
  340.      * Implemented to be a MenuElement -- does nothing.
  341.      *
  342.      * @see #getSubElements
  343.      */
  344.     public void processKeyEvent(KeyEvent e,MenuElement path[],MenuSelectionManager manager) {
  345.     }
  346.  
  347.     /** 
  348.      * Implemented to be a MenuElement -- does nothing.
  349.      *
  350.      * @see #getSubElements
  351.      */
  352.     public void menuSelectionChanged(boolean isIncluded) {
  353.     }
  354.     
  355.     /** 
  356.      * Implemented to be a MenuElement -- returns the menus in this menu 
  357.      * bar. This is the reason for implementing the MenuElement
  358.      * interface -- so that the menu bar can be treated the same as
  359.      * other menu elements.
  360.      */
  361.     public MenuElement[] getSubElements() {
  362.         int menuCount = getMenuCount();
  363.         int i;
  364.         MenuElement result[] = new MenuElement[menuCount];
  365.         for(i=0;i<menuCount;i++)
  366.             result[i] = getMenu(i);
  367.         return result;
  368.     }
  369.     
  370.     /** 
  371.      * Implemented to be a MenuElement. Returns this object. 
  372.      *
  373.      * @return the current Component (this)
  374.      * @see #getSubElements
  375.      */
  376.     public Component getComponent() {
  377.         return this;
  378.     }
  379. /////////////////
  380. // Accessibility support
  381. ////////////////
  382.  
  383.     /**
  384.      * Get the AccessibleContext associated with this JComponent
  385.      *
  386.      * @return the AccessibleContext of this JComponent
  387.      */
  388.     public AccessibleContext getAccessibleContext() {
  389.         if (accessibleContext == null) {
  390.             accessibleContext = new AccessibleJMenuBar();
  391.         }
  392.         return accessibleContext;
  393.     }
  394.  
  395.     /**
  396.      * The class used to obtain the accessible role for this object.
  397.      * <p>
  398.      * Warning: serialized objects of this class will not be compatible with
  399.      * future swing releases.  The current serialization support is appropriate
  400.      * for short term storage or RMI between Swing1.0 applications.  It will
  401.      * not be possible to load serialized Swing1.0 objects with future releases
  402.      * of Swing.  The JDK1.2 release of Swing will be the compatibility
  403.      * baseline for the serialized form of Swing objects.
  404.      */
  405.     protected class AccessibleJMenuBar extends AccessibleJComponent 
  406.         implements AccessibleSelection {
  407.  
  408.         /**
  409.          * Get the accessible state set of this object.
  410.          *
  411.          * @return an instance of AccessibleState containing the current state 
  412.          *         of the object
  413.          */
  414.         public AccessibleStateSet getAccessibleStateSet() {
  415.             AccessibleStateSet states = super.getAccessibleStateSet();
  416.             return states;
  417.         }
  418.  
  419.         /**
  420.          * Get the role of this object.
  421.          *
  422.          * @return an instance of AccessibleRole describing the role of the 
  423.          * object
  424.          */
  425.         public AccessibleRole getAccessibleRole() {
  426.             return AccessibleRole.MENU_BAR;
  427.         }
  428.  
  429.         /**
  430.          * Returns 1 if a menu is currently selected in this menu bar.
  431.          *
  432.          * @return 1 if a menu is currently selected, else 0
  433.          */
  434.          public int getAccessibleSelectionCount() {
  435.             if (isSelected()) {
  436.                 return 1;
  437.             } else {
  438.                 return 0;
  439.             }
  440.          }
  441.     
  442.         /**
  443.          * Returns the currently selected menu if one is selected, 
  444.          * otherwise null.
  445.          */
  446.          public Accessible getAccessibleSelection(int i) {
  447.             if (isSelected()) {
  448.                 int j = getSelectionModel().getSelectedIndex();
  449.                 if (getComponentAtIndex(j) instanceof Accessible) {
  450.                     return (Accessible) getComponentAtIndex(j);
  451.                 }           
  452.             }
  453.             return null;
  454.          }
  455.  
  456.         /**
  457.          * Returns true if the current child of this object is selected.
  458.          *
  459.          * @param i the zero-based index of the child in this Accessible 
  460.          * object.
  461.          * @see AccessibleContext#getAccessibleChild
  462.          */
  463.         public boolean isAccessibleChildSelected(int i) {
  464.             return (i == getSelectionModel().getSelectedIndex());
  465.         }
  466.  
  467.         /**
  468.          * Adds the nth selected item in the object to the object's
  469.          * selection.  If the object supports multiple selections,
  470.          * the nth item is added to any existing selection, otherwse
  471.          * it replaces any existing selection in the objct.  If the
  472.          * nth item is already selected, this method has no effect.
  473.          *
  474.          * @param i the zero-based index of selectable items
  475.          * @see #getAccessibleStateSet
  476.          */
  477.          public void addAccessibleSelection(int i) {
  478.             getSelectionModel().setSelectedIndex(i);
  479.          }
  480.     
  481.         /**
  482.          * Removes the nth selected item in the object from the object's
  483.          * selection.  If the nth item isn't currently selected, this
  484.          * method has no effect.
  485.          *
  486.          * @param i the zero-based index of selectable items
  487.          */
  488.          public void removeAccessibleSelection(int i) {
  489.             getSelectionModel().setSelectedIndex(-1);
  490.          }
  491.     
  492.         /**
  493.          * Clears the selection in the object, so that nothing in the
  494.          * object is selected.
  495.          */
  496.         public void clearAccessibleSelection() {
  497.             getSelectionModel().setSelectedIndex(-1);
  498.         }
  499.  
  500.         /**
  501.          * Causes every selected item in the object to be selected
  502.          * if the object supports multiple selections.
  503.          */
  504.         public void selectAllAccessibleSelection() {
  505.         } 
  506.     } // internal class AccessibleJMenuBar
  507.  
  508.  
  509.     /**
  510.      * Returns true to indicate that this component manages focus
  511.      * events internally.
  512.      *
  513.      * @return true
  514.      */
  515.     public boolean isManagingFocus() {
  516.         return true;
  517.     }
  518.  
  519.     KeyboardBinding bindingForKeyStroke(KeyStroke ks,int condition) {
  520.     // Does it exist for the MenuBar?
  521.     KeyboardBinding kbb =  super.bindingForKeyStroke(ks, condition);
  522.     if (kbb != null)
  523.         return kbb;
  524.  
  525.     int i;
  526.     Component subComponents[];
  527.  
  528.     subComponents = getComponents();
  529.     for(i=0 ; i < subComponents.length ; i++) {
  530.         // If 
  531.         if(subComponents[i] instanceof JMenu) {
  532.         kbb = bindingForKeyStrokeRecursive(subComponents[i], ks, condition);
  533.         }
  534.         if (kbb != null)
  535.         return kbb;
  536.     }    
  537.     return null;
  538.     }
  539.  
  540.     static KeyboardBinding bindingForKeyStrokeRecursive(Component c,
  541.                             KeyStroke ks,int condition) {
  542.     KeyboardBinding kbb = null;
  543.  
  544.     if (c==null)
  545.         return null;
  546.  
  547.     if (c instanceof JComponent) {
  548.         kbb = ((JComponent)c).bindingForKeyStroke(ks, condition);        
  549.         if (kbb != null)
  550.         return kbb;
  551.     }
  552.  
  553.     if (c instanceof JMenu) {
  554.         JMenu m = (JMenu)c;
  555.         int i;
  556.         Component subComponents[];
  557.         
  558.         subComponents = m.getMenuComponents();
  559.         for(i=0 ; i < subComponents.length ; i++) {
  560.         if(subComponents[i] instanceof JMenuItem) {
  561.             kbb = bindingForKeyStrokeRecursive(subComponents[i], 
  562.                                ks, condition);
  563.         }        
  564.         if (kbb != null)
  565.             return kbb;
  566.         }
  567.     }
  568.     return kbb;
  569.     }
  570.  
  571.  
  572.     private void writeObject(ObjectOutputStream s) throws IOException {
  573.         s.defaultWriteObject();
  574.  
  575.         Object[] kvData = new Object[4];
  576.         int n = 0;
  577.  
  578.         if (selectionModel instanceof Serializable) {
  579.             kvData[n++] = "selectionModel";
  580.             kvData[n++] = selectionModel;
  581.         }
  582.  
  583.         s.writeObject(kvData);
  584.     }
  585.  
  586.  
  587.     private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException 
  588.     {
  589.         s.defaultReadObject();
  590.         Object[] kvData = (Object[])(s.readObject());
  591.  
  592.         for(int i = 0; i < kvData.length; i += 2) {
  593.             if (kvData[i] == null) {
  594.                 break;
  595.             }
  596.             else if (kvData[i].equals("selectionModel")) {
  597.                 selectionModel = (SingleSelectionModel)kvData[i + 1];
  598.             }
  599.         }
  600.     }
  601. }
  602.  
  603.