home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / IFC_112 / netscape / application / MenuItem.java < prev    next >
Encoding:
Text File  |  1999-05-28  |  27.1 KB  |  871 lines  |  [TEXT/CWIE]

  1. // MenuItem.java
  2. // By Ned Etcode
  3. // Copyright 1996, 1997 Netscape Communications Corp.  All rights reserved.
  4.  
  5. package netscape.application;
  6.  
  7. import netscape.util.*;
  8.  
  9. /** Object subclass representing a single item in a Menu. MenuItems are used
  10.   * as both wrappers for AWT-based native MenuItems as well as for
  11.   * IFC View-based pure
  12.   * java Menus. Their behavior is determined by whether or not a given Menu
  13.   * that holds the MenuItem
  14.   * is set directly on an ExternalWindow with <b>setMenu</b>, or if a MenuView
  15.   * holding a Menu (with the MenuItem)
  16.   * is added to a Window with <b>setMenuView</b>. A MenuItem stores a
  17.   * reference to a java.awt.MenuItem, as well as implementing
  18.   * <b>drawInRect</b> for use in MenuViews.
  19.   * A MenuItem may or may not have a submenu. In general, you don't
  20.   * create MenuItems yourself, but instead use Menu's <b>addItem()</b> and
  21.   * <b>addItemWithSubmenu()</b> methods.
  22.   * @see Menu
  23.   * @note 1.0 completely rewritten
  24.   * @note 1.0 added support for MenuShortcuts in JDK 1.1.1
  25.   */
  26.  
  27. public class MenuItem implements Codable, Cloneable, EventProcessor {
  28.     Menu                  submenu, supermenu;
  29.     java.awt.MenuItem     foundationMenuItem;
  30.     String                command;
  31.     String                title;
  32.     Target                target;
  33.     char                  commandKey;
  34.     Font                  font;
  35.     Image                 checkedImage, uncheckedImage;
  36.     Image                 image, selectedImage;
  37.     Color                 selectedColor, selectedTextColor;
  38.     Color                 textColor, disabledColor;
  39.     boolean               selected, separator, state, enabled;
  40.     Object                data;
  41.  
  42.     final static String   SUBMENU_KEY = "submenu",
  43.                           SUPERMENU_KEY = "supermenu",
  44.                           COMMAND_KEY = "command",
  45.                           TITLE_KEY = "title",
  46.                           TARGET_KEY = "target",
  47.                           COMMANDKEY_KEY = "commandKey",
  48.                           FONT_KEY = "font",
  49.                           CHECKEDIMAGE_KEY = "checkedImage",
  50.                           UNCHECKEDIMAGE_KEY = "uncheckedImage",
  51.                           IMAGE_KEY = "image",
  52.                           SELECTEDIMAGE_KEY = "selectedImage",
  53.                           SELECTEDCOLOR_KEY = "selectedColor",
  54.                           SELECTEDTEXTCOLOR_KEY = "selectedTextColor",
  55.                           TEXTCOLOR_KEY = "textColor",
  56.                           DISABLEDCOLOR_KEY = "disabledColor",
  57.                           SEPARATOR_KEY = "separator",
  58.                           STATE_KEY = "state",
  59.                           ENABLED_KEY = "enabled",
  60.                           DATA_KEY = "data";
  61.  
  62.     /** Constructs an empty MenuItem.
  63.       */
  64.     public MenuItem() {
  65.         this("", (char)0, null, null, false);
  66.     }
  67.  
  68.     /** Constructs a MenuItem with the specified title, command, and
  69.       * Target.
  70.       */
  71.     public MenuItem(String title, String command, Target target) {
  72.         this(title, (char)0, command, target, false);
  73.     }
  74.  
  75.     /** Constructs a MenuItem with the specified title, command key
  76.       * equivalent, command, and Target.
  77.       */
  78.     public MenuItem(String title, char key, String command, Target target) {
  79.         this(title, key, command, target, false);
  80.     }
  81.  
  82.     /** Constructs a MenuItem with the specified title, command, and Target.
  83.       * If <b>isCheckbox</b> is true, this will be a checkbox MenuItem.
  84.       *
  85.       */
  86.     public MenuItem(String title, String command, Target target,
  87.                     boolean isCheckbox) {
  88.         this(title, (char)0, command, target, isCheckbox);
  89.     }
  90.  
  91.     /** Constructs a MenuItem with the specified title, command key
  92.       * equivalent, command, and Target. If <b>isCheckbox</b> is true,
  93.       * this will be a checkbox MenuItem.
  94.       *
  95.       */
  96.     public MenuItem(String title, char key, String command, Target target,
  97.                     boolean isCheckbox) {
  98.         super();
  99.  
  100.         commandKey = Character.toUpperCase(key);
  101.         if (!isCheckbox) {
  102.             foundationMenuItem = new FoundationMenuItem(title, this);
  103.         } else {
  104.             foundationMenuItem = new FoundationCheckMenuItem(title, this);
  105.             setUncheckedImage(Bitmap.bitmapNamed(
  106.                                  "netscape/application/RadioButtonOff.gif"));
  107.             setCheckedImage(Bitmap.bitmapNamed(
  108.                                  "netscape/application/RadioButtonOn.gif"));
  109.             setImage(uncheckedImage);
  110.             setSelectedImage(uncheckedImage);
  111.         }
  112.         setEnabled(true);
  113.         setFont(new Font("Helvetica", Font.PLAIN, 12));
  114.         setTitle(title);
  115.         setTarget(target);
  116.         setCommand(command);
  117.  
  118.         selectedColor = Color.white;
  119.         textColor = Color.black;
  120.         selectedTextColor = Color.black;
  121.         disabledColor = Color.gray;
  122.     }
  123.  
  124.     /** Clones the MenuItem. Menu adds addtional items by cloning its
  125.       * prototype MenuItem.
  126.       */
  127.     public Object clone() {
  128.         try {
  129.             return super.clone();
  130.         } catch (CloneNotSupportedException e) {
  131.             throw new InconsistencyException(
  132.                                 this + ": clone() not supported :" + e);
  133.         }
  134.     }
  135.  
  136.     /** Returns the FoundationMenuItem associated with this MenuItem. You
  137.       * should only be concerned with this FoundationMenuItem if you are
  138.       * using AWT-based native Menus.
  139.       */
  140.     java.awt.MenuItem foundationMenuItem() {
  141.         return foundationMenuItem;
  142.     }
  143.  
  144.     /** Sets this MenuItem to be a separator if <b>isSeparator</b> is true.
  145.       *
  146.       */
  147.     public void setSeparator(boolean isSeparator) {
  148.         separator = isSeparator;
  149.         if (isSeparator) {
  150.             setEnabled(true);
  151.         }
  152.     }
  153.  
  154.     /** Returns <b>true</b> if this MenuItem is a separator, <b>false</b>
  155.       * otherwise.
  156.       *
  157.       */
  158.     public boolean isSeparator() {
  159.         return separator;
  160.     }
  161.  
  162.     /** Sets the MenuItem's data, a storage place for arbitrary data associated
  163.       * with the MenuItem.
  164.       */
  165.     public void setData(Object data)    {
  166.         this.data = data;
  167.     }
  168.  
  169.     /** Returns the MenuItem's data.
  170.       * @see #setData
  171.       */
  172.     public Object data()    {
  173.         return this.data;
  174.     }
  175.  
  176.     /** Sets this MenuItem to have the specified submenu. Note that in
  177.       * order for a Menu structure to work properly, MenuItems should be
  178.       * added directly to Menus with <b>addItem</b> and
  179.       * <b>addItemWithSubmenur</b>. It is not sufficient to create a
  180.       * MenuItem and call <b>setSubmenu</b> with a given Menu. You should
  181.       * not call this method directly.
  182.       */
  183.     public void setSubmenu(Menu aMenu) {
  184.         submenu = aMenu;
  185.         if (submenu != null) {
  186.             submenu.setSuperitem(this);
  187.         }
  188.     }
  189.  
  190.     /** Returns the MenuItem's submenu, <b>null</b> if it doesn't have one.
  191.       */
  192.     public Menu submenu() {
  193.         return submenu;
  194.     }
  195.  
  196.     /** Returns <b>true</b> if this MenuItem has a submenu.
  197.       * @see #setSubmenu
  198.       */
  199.     public boolean hasSubmenu() {
  200.         if (submenu != null) {
  201.             return true;
  202.         } else {
  203.             return false;
  204.         }
  205.     }
  206.  
  207.     /** Sets the MenuItem's supermenu. Note that in
  208.       * order for a Menu structure to work properly, MenuItems should be
  209.       * added directly to Menus with <b>addItem</b> and
  210.       * <b>addItemWithSubmenur</b>. It is not sufficient to create a
  211.       * MenuItem and call <b>setSupermenu</b> with a given Menu. You should
  212.       * not call this method directly.
  213.       */
  214.     public void setSupermenu(Menu aMenu) {
  215.         supermenu = aMenu;
  216.     }
  217.  
  218.     /** Returns the MenuItem's supermenu.
  219.       * @see #setSupermenu
  220.       */
  221.     public Menu supermenu() {
  222.         return supermenu;
  223.     }
  224.  
  225.     /** Sets the MenuItem's command key equivalent.
  226.       */
  227.     public void setCommandKey(char key) {
  228.         commandKey = Character.toUpperCase(key);
  229.         setTitle(title);
  230.     }
  231.  
  232.     /** Returns the MenuItem's command key equivalent, '\0' if it doesn't have
  233.       * one.
  234.       * @see #setCommandKey
  235.       */
  236.     public char commandKey() {
  237.         return commandKey;
  238.     }
  239.  
  240.     /** Sets the MenuItem's state if this is a checkbox MenuItem. This does
  241.       * nothing if this is a regular MenuItem.
  242.       *
  243.       */
  244.     public void setState(boolean aState) {
  245.         state = aState;
  246.         if (foundationMenuItem instanceof FoundationCheckMenuItem) {
  247.             ((FoundationCheckMenuItem)foundationMenuItem).setState(state);
  248.             if (state) {
  249.                 setImage(checkedImage());
  250.                 setSelectedImage(checkedImage());
  251.             } else {
  252.                 setImage(uncheckedImage());
  253.                 setSelectedImage(uncheckedImage());
  254.             }
  255.         }
  256.     }
  257.  
  258.     /** Returns the current state of the MenuItem. If this is not a checkbox
  259.       * MenuItem, returns false.
  260.       *
  261.       */
  262.     public boolean state() {
  263.         if (foundationMenuItem instanceof FoundationCheckMenuItem) {
  264.             //return ((FoundationCheckMenuItem)foundationMenuItem).getState();
  265.             return state;
  266.         }
  267.         return false;
  268.     }
  269.  
  270.     /** Sets the Image the MenuItem displays next to its title.
  271.       * @see #setSelectedImage
  272.       */
  273.     public void setImage(Image theImage) {
  274.         image = theImage;
  275.     }
  276.  
  277.     /** Returns the Image the MenuItem displays next to its title.
  278.       * @see #setImage
  279.       *
  280.       */
  281.     public Image image() {
  282.         return image;
  283.     }
  284.  
  285.     /** Sets the Image the MenuItem displays next to its title when
  286.       * selected.
  287.       * @see #setImage
  288.       *
  289.       */
  290.     public void setSelectedImage(Image theImage) {
  291.         selectedImage = theImage;
  292.     }
  293.  
  294.     /** Returns the Image the MenuItem displays next to its title when
  295.       * selected.
  296.       * @see #setSelectedImage
  297.       */
  298.     public Image selectedImage() {
  299.         return selectedImage;
  300.     }
  301.  
  302.     /** Sets the Image displayed on the MenuItem if it is a checkbox
  303.       * MenuItem and its state is true.
  304.       *
  305.       */
  306.     public void setCheckedImage(Image theImage) {
  307.         checkedImage = theImage;
  308.         if (foundationMenuItem instanceof FoundationCheckMenuItem) {
  309.             if (state() == true) {
  310.                 setImage(checkedImage);
  311.                 setSelectedImage(checkedImage);
  312.             }
  313.         }
  314.     }
  315.  
  316.     /** Returns the Image displayed on the MenuItem if it is a checkbox
  317.       * MenuItem and its state is true.
  318.       *
  319.       */
  320.     public Image checkedImage() {
  321.         return checkedImage;
  322.     }
  323.  
  324.     /** Sets the Image displayed on the MenuItem if it is a checkbox
  325.       * MenuItem and its state is false.
  326.       *
  327.       */
  328.     public void setUncheckedImage(Image theImage) {
  329.         uncheckedImage = theImage;
  330.         if (foundationMenuItem instanceof FoundationCheckMenuItem) {
  331.             if (state() == false) {
  332.                 setImage(uncheckedImage);
  333.                 setSelectedImage(uncheckedImage);
  334.             }
  335.         }
  336.     }
  337.  
  338.     /** Returns the Image displayed on the MenuItem if it is a checkbox
  339.       * MenuItem and its state is false.
  340.       *
  341.       */
  342.     public Image uncheckedImage() {
  343.         return uncheckedImage;
  344.     }
  345.  
  346.     /** Sets the color the MenuItem uses to draw its background when
  347.       * selected.
  348.       *
  349.       */
  350.     public void setSelectedColor(Color color) {
  351.         selectedColor = color;
  352.     }
  353.  
  354.     /** Returns the color the MenuItem uses to draw its background when
  355.       * selected.
  356.       *
  357.       */
  358.     public Color selectedColor() {
  359.         return selectedColor;
  360.     }
  361.  
  362.     /** Sets the color the MenuItem uses to draw its foreground text when
  363.       * selected.
  364.       *
  365.       */
  366.     public void setSelectedTextColor(Color color) {
  367.         selectedTextColor = color;
  368.     }
  369.  
  370.     /** Returns the color the MenuItem uses to draw its foreground text when
  371.       * selected.
  372.       *
  373.       */
  374.     public Color selectedTextColor() {
  375.         return selectedTextColor;
  376.     }
  377.  
  378.     /** Sets the color the MenuItem uses to draw its foreground text.
  379.       *
  380.       */
  381.     public void setTextColor(Color color) {
  382.         textColor = color;
  383.     }
  384.  
  385.     /** Returns the color the MenuItem uses to draw its foreground text.
  386.       *
  387.       */
  388.     public Color textColor() {
  389.         return textColor;
  390.     }
  391.  
  392.     /** Sets the color the MenuItem uses to draw its text when disabled.
  393.       *
  394.       */
  395.     public void setDisabledColor(Color color) {
  396.         disabledColor = color;
  397.     }
  398.  
  399.     /** Returns the color the MenuItem uses to draw its text when disabled.
  400.       *
  401.       */
  402.     public Color disabledColor() {
  403.         return disabledColor;
  404.     }
  405.  
  406.     /** Sets this MenuItem to be selected if <b>isSelected</b> is
  407.       * <b>true</b>, or unselected if <b>false</b>.
  408.       *
  409.       */
  410.     public void setSelected(boolean isSelected) {
  411.         if (!isEnabled())
  412.             isSelected = false;
  413.  
  414.         selected = isSelected;
  415.     }
  416.  
  417.     /** Returns <b>true</b> if the MenuItem is selected.
  418.       * @see #setSelected
  419.       *
  420.       */
  421.     public boolean isSelected() {
  422.         return selected;
  423.     }
  424.  
  425.     /** Sets the MenuItem's command.
  426.       */
  427.     public void setCommand(String newCommand) {
  428.         command = newCommand;
  429.     }
  430.  
  431.     /** Returns the MenuItem's command.
  432.       * @see #setCommand
  433.       */
  434.     public String command() {
  435.         return command;
  436.     }
  437.  
  438.     /** Sets the MenuItem's Target.
  439.       */
  440.     public void setTarget(Target aTarget) {
  441.         target = aTarget;
  442.     }
  443.  
  444.     /** Returns the MenuItem's Target.
  445.       * @see #setTarget
  446.       */
  447.     public Target target() {
  448.         return target;
  449.     }
  450.  
  451.     /** Called by the EventLoop to process a selection event. Calls
  452.       * <b>sendCommand()</b>.
  453.       */
  454.     public void processEvent(Event event) {
  455.         sendCommand();
  456.     }
  457.  
  458.     /** Tells the MenuItem to send its command to its Target.
  459.       * @see #setTarget
  460.       */
  461.     public void sendCommand() {
  462.         if (target != null) {
  463.             target.performCommand(command, this);
  464.         }
  465.     }
  466.  
  467.     // ALERT.  This is doing OS checks.  Be afraid.
  468.     private boolean canUseTabFormatter() {
  469.         // ALERT.  it's not guaranteed that all windows platforms
  470.         // can handle the tab key, so we can't depend on it
  471.         return false;
  472.         /*
  473.         if ("x86".equals(System.getProperty("os.arch")) ||
  474.             "Pentium".equals(System.getProperty("os.arch"))) {
  475.             return true;
  476.         } else {
  477.             return false;
  478.         }
  479.         */
  480.     }
  481.  
  482.     /** Sets the MenuItem's title.
  483.       */
  484.     public void setTitle(String aString) {
  485.         FontMetrics   metrics;
  486.         String        tmpString;
  487.         StringBuffer  buf;
  488.         int           numSpaces, i, maxWidth, width;
  489.  
  490.         tmpString = aString;
  491.         title = aString;
  492.         if (commandKey() != 0) {
  493.             if (JDK11AirLock.setMenuShortcut(this, commandKey())) {
  494.                 tmpString = aString;
  495.             } else if (canUseTabFormatter()) {
  496.                 tmpString = aString + "\tCtrl+" + commandKey();
  497.             } else {
  498.                 buf = new StringBuffer();
  499.                 metrics = font().fontMetrics();
  500.                 if (supermenu() != null) {
  501.                     maxWidth = supermenu().minItemWidth();
  502.                 } else {
  503.                     maxWidth = minWidth();
  504.                 }
  505.                 width = metrics.stringWidth(aString);
  506.  
  507.                 buf.append(aString);
  508.                 numSpaces = (maxWidth - width) / metrics.stringWidth(" ");
  509.                 for (i = 0; i < numSpaces; i++) {
  510.                     buf.append(' ');
  511.                 }
  512.                 tmpString = buf.toString() + "  Ctrl+" + commandKey();
  513.             }
  514.         }
  515.         foundationMenuItem.setLabel(tmpString);
  516.     }
  517.  
  518.     /** Returns the MenuItem's title.
  519.       */
  520.     public String title() {
  521.         return title;
  522.     }
  523.  
  524.     /** Returns the minimum height required to display the MenuItem's title.
  525.       *
  526.       */
  527.     public int minHeight() {
  528.         int    height = 0;
  529.  
  530.         if (font() != null) {
  531.             height = font().fontMetrics().stringHeight();
  532.         }
  533.  
  534.         return height;
  535.     }
  536.  
  537.     /** Returns the minimum width required to display the MenuItem's title
  538.       * and Image, if any.
  539.       *
  540.       */
  541.     public int minWidth() {
  542.         int        width = 0;
  543.  
  544.         if (image != null)
  545.             width = image.width();
  546.  
  547.         if (selectedImage != null)
  548.             if (selectedImage.width() > width)
  549.                 width = selectedImage.width();
  550.  
  551.         if (font() != null)
  552.             width += font().fontMetrics().stringWidth(title);
  553.  
  554.         // Beware of magic constant!  ALERT!
  555.         if (width > 0) {
  556.             width += 11;
  557.         }
  558.  
  559.         width += commandKeyWidth();
  560.  
  561.         return width;
  562.     }
  563.  
  564.     /** Returns the width required to display the command key expression
  565.       * on the right of the MenuItem.
  566.       */
  567.     int commandKeyWidth() {
  568.         int   width = 0;
  569.  
  570.         // More scary magic constants!  ALERT!
  571.         if (font() != null && commandKey() != (char)0) {
  572.             width = font().fontMetrics().stringWidth("Ctrl+W");
  573.             width += 10;
  574.         }
  575.  
  576.         return width;
  577.     }
  578.  
  579.     /** Enables or disables the MenuItem. Disabled MenuItems cannot be
  580.       * selected and render their title using <b>disabledColor</b>.
  581.       */
  582.     public void setEnabled(boolean isEnabled) {
  583.         enabled = isEnabled;
  584.         if (hasSubmenu()) {
  585.             submenu.awtMenu().enable(isEnabled);
  586.         } else {
  587.             foundationMenuItem.enable(isEnabled);
  588.         }
  589.         requestDraw();
  590.     }
  591.  
  592.     /** Returns <b>true</b> if the MenuItem is enabled, <b>false</b> otherwise.
  593.       * @see #setEnabled
  594.       */
  595.     public boolean isEnabled() {
  596.         return enabled;
  597.         /*
  598.         if (hasSubmenu()) {
  599.             return submenu.awtMenu().isEnabled();
  600.         } else {
  601.             return foundationMenuItem.isEnabled();
  602.         }
  603.         */
  604.     }
  605.  
  606.     /** Sets the Font used to display the MenuItem's title.
  607.       */
  608.     public void setFont(Font aFont) {
  609.         java.awt.Font awtFont;
  610.  
  611.         font = aFont;
  612.         awtFont = AWTCompatibility.awtFontForFont(font);
  613.         foundationMenuItem.setFont(awtFont);
  614.     }
  615.  
  616.     /** Returns the Font used to display the MenuItem's title.
  617.       * @see #setFont
  618.       */
  619.     public Font font() {
  620.         //Font font;
  621.  
  622.         //font = AWTCompatibility.fontForAWTFont(foundationMenuItem.getFont());
  623.         return font;
  624.     }
  625.  
  626.     /** Convenience method for this MenuItem to redraw.
  627.       *
  628.       */
  629.     public void requestDraw() {
  630.         if (supermenu() != null) {
  631.             if (supermenu().menuView != null) {   // ALERT! menuView backptr
  632.                 supermenu().menuView.drawItemAt(supermenu().indexOfItem(this));
  633.             }
  634.         }
  635.     }
  636.  
  637.     /** Called from <b>drawInRect()</b> to draw the MenuItem if it is
  638.       * a separator. Subclasses can override this method to do custom
  639.       * drawing. This method has no meaning for MenuItems that are being used
  640.       * in AWT-based native Menus.
  641.       *
  642.       */
  643.     protected void drawSeparator(Graphics g, Rect boundsRect) {
  644.         int  midHeight, width;
  645.  
  646.         midHeight = boundsRect.y + (boundsRect.height / 2);
  647.         width = boundsRect.x + boundsRect.width;
  648.  
  649.         g.setColor(Color.gray153);
  650.         g.drawLine(boundsRect.x, midHeight - 1, width, midHeight - 1);
  651.         g.setColor(Color.gray231);
  652.         g.drawLine(boundsRect.x, midHeight, width, midHeight);
  653.     }
  654.  
  655.     /** Called from <b>drawInRect()</b> to draw the MenuItem's background.
  656.       * Subclasses can override this method to draw custom backgrounds.
  657.       * This method has no meaning for MenuItems that are being used
  658.       * in AWT-based native Menus.
  659.       *
  660.       */
  661.     protected void drawBackground(Graphics g, Rect boundsRect) {
  662.         if (isSelected()) {
  663.             g.setColor(selectedColor);
  664.             g.fillRect(boundsRect);
  665.         }
  666.     }
  667.  
  668.     /** Called from <b>drawInRect()</b> to draw the MenuItem's title.
  669.       * Subclasses can override this method to draw the title string in a
  670.       * special way. This method has no meaning for MenuItems that are
  671.       * being used in AWT-based native Menus.
  672.       *
  673.       */
  674.     protected void drawStringInRect(Graphics g, String title,
  675.                                     Font titleFont, Rect textBounds,
  676.                                     int justification) {
  677.         String   string;
  678.         Rect     textRect;
  679.         int      width = 0;
  680.         Font     font;
  681.  
  682.         if (isEnabled() && !isSelected()) {
  683.             g.setColor(textColor);
  684.         } else if (isEnabled() && isSelected()) {
  685.             g.setColor(selectedTextColor);
  686.         } else {
  687.             g.setColor(disabledColor);
  688.         }
  689.         g.setFont(titleFont);
  690.         g.drawStringInRect(title, textBounds, justification);
  691.  
  692.         if (commandKey() != (char)0) {
  693.             font = font();
  694.             if (font != null) {
  695.                 width = font.fontMetrics().stringWidth("Ctrl+W");
  696.                 width += 10;   // ALERT
  697.             }
  698.  
  699.             textRect = new Rect(textBounds.x + textBounds.width - width,
  700.                                 textBounds.y, width, textBounds.height);
  701.             string = "Ctrl+" + commandKey();
  702.             g.drawStringInRect(string, textRect, Graphics.LEFT_JUSTIFIED);
  703.         }
  704.     }
  705.  
  706.     /** Called by Menu to draw the MenuItem. If the MenuItem is
  707.       * transparent, its Menu will have already drawn its background.  If
  708.       * not, the MenuItem should entirely fill <b>boundsRect</b>. If
  709.       * <b>showsArrow</b> is true and this MenuItem has a submenu, a
  710.       * submenu arrow will be drawn on the right edge.
  711.       * This method has no meaning for MenuItems that are being used
  712.       * in AWT-based native Menus.
  713.       *
  714.       */
  715.     public void drawInRect(Graphics g, Rect boundsRect, boolean
  716.                            showsArrow) {
  717.         Image   theImage;
  718.         Rect    tmpRect;
  719.         int     width, height;
  720.  
  721.         if (isSeparator()) {
  722.             drawSeparator(g, boundsRect);
  723.             return;
  724.         }
  725.  
  726.         drawBackground(g, boundsRect);
  727.  
  728.         if (isSelected()) {
  729.             theImage = selectedImage;
  730.         } else {
  731.             theImage = image;
  732.         }
  733.  
  734.         width = height = 0;
  735.         if (image != null) {
  736.             width = image.width();
  737.             height = image.height();
  738.         }
  739.         if (selectedImage != null) {
  740.             if (selectedImage.width() > width) {
  741.                 width = selectedImage.width();
  742.             }
  743.             if (selectedImage.height() > height) {
  744.                 height = selectedImage.height();
  745.             }
  746.         }
  747.  
  748.         if (theImage != null) {
  749.             theImage.drawAt(g, boundsRect.x,
  750.                             boundsRect.y + (boundsRect.height - height)/2);
  751.         }
  752.  
  753.         if (title != null && title.length() > 0) {
  754.             tmpRect = Rect.newRect(boundsRect.x + 2 + width, boundsRect.y,
  755.                                    boundsRect.width - 2 - width,
  756.                                    boundsRect.height);
  757.             drawStringInRect(g, title, font(), tmpRect,
  758.                              Graphics.LEFT_JUSTIFIED);
  759.  
  760.             Rect.returnRect(tmpRect);
  761.         }
  762.  
  763.         if (showsArrow && hasSubmenu()) {
  764.             theImage = Bitmap.bitmapNamed(
  765.                               "netscape/application/ScrollRightArrow.gif");
  766.             width = theImage.width();
  767.             height = theImage.height();
  768.  
  769.             theImage.drawAt(g, boundsRect.x + boundsRect.width - width,
  770.                             boundsRect.y + (boundsRect.height - height)/2);
  771.         }
  772.     }
  773.  
  774.     /** Describes the MenuItem class' information.
  775.       * @see Codable#describeClassInfo
  776.       */
  777.     public void describeClassInfo(ClassInfo info) {
  778.         info.addClass("netscape.application.MenuItem", 1);
  779.         info.addField(SUBMENU_KEY, OBJECT_TYPE);
  780.         info.addField(SUPERMENU_KEY, OBJECT_TYPE);
  781.  
  782.         info.addField(COMMAND_KEY, STRING_TYPE);
  783.         info.addField(TITLE_KEY, STRING_TYPE);
  784.         info.addField(TARGET_KEY, OBJECT_TYPE);
  785.         info.addField(COMMANDKEY_KEY, CHAR_TYPE);
  786.  
  787.         info.addField(FONT_KEY, OBJECT_TYPE);
  788.         info.addField(CHECKEDIMAGE_KEY, OBJECT_TYPE);
  789.         info.addField(UNCHECKEDIMAGE_KEY, OBJECT_TYPE);
  790.         info.addField(IMAGE_KEY, OBJECT_TYPE);
  791.         info.addField(SELECTEDIMAGE_KEY, OBJECT_TYPE);
  792.         info.addField(SELECTEDCOLOR_KEY, OBJECT_TYPE);
  793.         info.addField(SELECTEDTEXTCOLOR_KEY, OBJECT_TYPE);
  794.         info.addField(TEXTCOLOR_KEY, OBJECT_TYPE);
  795.         info.addField(DISABLEDCOLOR_KEY, OBJECT_TYPE);
  796.  
  797.         //info.addField(SELECTED_KEY, BOOLEAN_TYPE);
  798.         info.addField(SEPARATOR_KEY, BOOLEAN_TYPE);
  799.         info.addField(ENABLED_KEY, BOOLEAN_TYPE);
  800.         info.addField(STATE_KEY, BOOLEAN_TYPE);
  801.  
  802.         info.addField(DATA_KEY, OBJECT_TYPE);
  803.     }
  804.  
  805.     /** Archives the MenuItem instance.
  806.       * @see Codable#encode
  807.       */
  808.     public void encode(Encoder encoder) throws CodingException {
  809.         encoder.encodeObject(SUBMENU_KEY, submenu);
  810.         encoder.encodeObject(SUPERMENU_KEY, supermenu);
  811.  
  812.         encoder.encodeString(COMMAND_KEY, command);
  813.         encoder.encodeString(TITLE_KEY, title);
  814.         encoder.encodeObject(TARGET_KEY, target);
  815.         encoder.encodeChar(COMMANDKEY_KEY, commandKey);
  816.  
  817.         encoder.encodeObject(FONT_KEY, font);
  818.         encoder.encodeObject(CHECKEDIMAGE_KEY, checkedImage);
  819.         encoder.encodeObject(UNCHECKEDIMAGE_KEY, uncheckedImage);
  820.         encoder.encodeObject(IMAGE_KEY, image);
  821.         encoder.encodeObject(SELECTEDIMAGE_KEY, selectedImage);
  822.         encoder.encodeObject(SELECTEDCOLOR_KEY, selectedColor);
  823.         encoder.encodeObject(SELECTEDTEXTCOLOR_KEY, selectedTextColor);
  824.         encoder.encodeObject(TEXTCOLOR_KEY, textColor);
  825.         encoder.encodeObject(DISABLEDCOLOR_KEY, disabledColor);
  826.  
  827.         //encoder.encodeBoolean(SELECTED_KEY, selected);
  828.         encoder.encodeBoolean(SEPARATOR_KEY, separator);
  829.         encoder.encodeBoolean(ENABLED_KEY, enabled);
  830.         encoder.encodeBoolean(STATE_KEY, state);
  831.  
  832.         encoder.encodeObject(DATA_KEY, data);
  833.     }
  834.  
  835.     /** Unarchives the MenuItem instance.
  836.       * @see Codable#decode
  837.       */
  838.     public void decode(Decoder decoder) throws CodingException {
  839.         submenu = (Menu)decoder.decodeObject(SUBMENU_KEY);
  840.         supermenu = (Menu)decoder.decodeObject(SUPERMENU_KEY);
  841.  
  842.         command = (String)decoder.decodeString(COMMAND_KEY);
  843.         title = (String)decoder.decodeString(TITLE_KEY);
  844.         target = (Target)decoder.decodeObject(TARGET_KEY);
  845.         commandKey = (char)decoder.decodeChar(COMMANDKEY_KEY);
  846.  
  847.         font = (Font)decoder.decodeObject(FONT_KEY);
  848.         checkedImage = (Image)decoder.decodeObject(CHECKEDIMAGE_KEY);
  849.         uncheckedImage = (Image)decoder.decodeObject(UNCHECKEDIMAGE_KEY);
  850.         image = (Image)decoder.decodeObject(IMAGE_KEY);
  851.         selectedImage = (Image)decoder.decodeObject(SELECTEDIMAGE_KEY);
  852.         selectedColor = (Color)decoder.decodeObject(SELECTEDCOLOR_KEY);
  853.         selectedTextColor = (Color)decoder.decodeObject(SELECTEDTEXTCOLOR_KEY);
  854.         textColor = (Color)decoder.decodeObject(TEXTCOLOR_KEY);
  855.         disabledColor = (Color)decoder.decodeObject(DISABLEDCOLOR_KEY);
  856.  
  857.         //selected = (boolean)decoder.decodeBoolean(SELECTED_KEY);
  858.         separator = (boolean)decoder.decodeBoolean(SEPARATOR_KEY);
  859.         enabled = (boolean)decoder.decodeBoolean(ENABLED_KEY);
  860.         state = (boolean)decoder.decodeBoolean(STATE_KEY);
  861.  
  862.         data = (Object)decoder.decodeObject(DATA_KEY);
  863.     }
  864.  
  865.     /** Finishes the MenuItem's unarchiving.
  866.       * @see Codable#finishDecoding
  867.       */
  868.     public void finishDecoding() throws CodingException {
  869.     }
  870. }
  871.