Mega Code Archive

 
Categories / Java / Swing JFC
 

Applet Menu Bar Demo

/*  * Copyright (c) 2000 David Flanagan. All rights reserved. This code is from the  * book Java Examples in a Nutshell, 2nd Edition. It is provided AS-IS, WITHOUT  * ANY WARRANTY either expressed or implied. You may study, use, and modify it  * for any non-commercial purpose. You may distribute it non-commercially as  * long as you retain this notice. For a commercial use license, or to purchase  * the book (recommended), visit http://www.davidflanagan.com/javaexamples2.  */ import java.applet.Applet; import java.awt.AWTEvent; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Insets; import java.awt.Panel; import java.awt.PopupMenu; import java.awt.event.MouseEvent; import java.util.Vector; public class AppletMenuBarDemo extends Applet {   public void init() {     AppletMenuBar menubar = new AppletMenuBar();     menubar.setForeground(Color.black);     menubar.setHighlightColor(Color.red);     menubar.setFont(new Font("helvetica", Font.BOLD, 12));     this.setLayout(new BorderLayout());     this.add(menubar, BorderLayout.NORTH);     PopupMenu file = new PopupMenu();     file.add("New...");     file.add("Open...");     file.add("Save As...");     PopupMenu edit = new PopupMenu();     edit.add("Cut");     edit.add("Copy");     edit.add("Paste");     menubar.addMenu("File", file);     menubar.addMenu("Edit", edit);   } } /*  * Copyright (c) 2000 David Flanagan. All rights reserved. This code is from the  * book Java Examples in a Nutshell, 2nd Edition. It is provided AS-IS, WITHOUT  * ANY WARRANTY either expressed or implied. You may study, use, and modify it  * for any non-commercial purpose. You may distribute it non-commercially as  * long as you retain this notice. For a commercial use license, or to purchase  * the book (recommended), visit http://www.davidflanagan.com/javaexamples2.  */ class AppletMenuBar extends Panel {   // Menubar contents   Vector labels = new Vector();   Vector menus = new Vector();   // Properties   Insets margins = new Insets(3, 10, 3, 10); // top, left, bottom, right   int spacing = 10; // Space between menu labels   Color highlightColor; // Rollover color for labels   // internal stuff   boolean remeasure = true; // Whether the labels need to be remeasured   int[] widths; // The width of each label   int[] startPositions; // Where each label starts   int ascent, descent; // Font metrics   Dimension prefsize = new Dimension(); // How big do we want to be?   int highlightedItem = -1; // Which item is the mouse over?   /**    * Create a new component that simulates a menubar by displaying the    * specified labels. Whenever the user clicks the specified label, popup up    * the PopupMenu specified in the menus array. Elements of the menus arra    * may be a static PopupMenu object, or a PopupMenuFactory object for    * dynamically creating menus. Perhaps we'll also provide some other kind of    * constructor or factory method that reads popup menus out of a config    * file.    */   public AppletMenuBar() {     // We'd like these kinds of events to be delivered     enableEvents(AWTEvent.MOUSE_EVENT_MASK         | AWTEvent.MOUSE_MOTION_EVENT_MASK);   }   /** Add a popup menu to the menubar */   public void addMenu(String label, PopupMenu menu) {     insertMenu(label, menu, -1);   }   /** Insert a popup menu into the menubar */   public void insertMenu(String label, PopupMenu menu, int index) {     if (index < 0)       index += labels.size() + 1; // Position to put it at     this.add(menu); // Popup belongs to us     labels.insertElementAt(label, index); // Remember the label     menus.insertElementAt(menu, index); // Remember the menu     remeasure = true; // Remeasure everything     invalidate(); // Container must relayout   }   /** Property accessor methods for margins property */   public Insets getMargins() {     return (Insets) margins.clone();   }   public void setMargins(Insets margins) {     this.margins = margins;     remeasure = true;     invalidate();   }   /** Property accessor methods for spacing property */   public int getSpacing() {     return spacing;   }   public void setSpacing(int spacing) {     if (this.spacing != spacing) {       this.spacing = spacing;       remeasure = true;       invalidate();     }   }   /** Accessor methods for highlightColor property */   public Color getHighlightColor() {     if (highlightColor == null)       return getForeground();     else       return highlightColor;   }   public void setHighlightColor(Color c) {     if (highlightColor != c) {       highlightColor = c;       repaint();     }   }   /** We override the setFont() method so we can remeasure */   public void setFont(Font f) {     super.setFont(f);     remeasure = true;     invalidate();   }   /** Override these color property setter method so we can repaint */   public void setForeground(Color c) {     super.setForeground(c);     repaint();   }   public void setBackground(Color c) {     super.setBackground(c);     repaint();   }   /**    * This method is called to draw tell the component to redraw itself. If we    * were implementing a Swing component, we'd override paintComponent()    * instead    */   public void paint(Graphics g) {     if (remeasure)       measure(); // Remeasure everything first, if needed     // Figure out Y coordinate to draw at     Dimension size = getSize();     int baseline = size.height - margins.bottom - descent;     // Set the font to draw with     g.setFont(getFont());     // Loop through the labels     int nummenus = labels.size();     for (int i = 0; i < nummenus; i++) {       // Set the drawing color. Highlight the current item       if ((i == highlightedItem) && (highlightColor != null))         g.setColor(getHighlightColor());       else         g.setColor(getForeground());       // Draw the menu label at the position computed in measure()       g.drawString((String) labels.elementAt(i), startPositions[i],           baseline);     }     // Now draw a groove at the bottom of the menubar.     Color bg = getBackground();     g.setColor(bg.darker());     g.drawLine(0, size.height - 2, size.width, size.height - 2);     g.setColor(bg.brighter());     g.drawLine(0, size.height - 1, size.width, size.height - 1);   }   /** Called when a mouse event happens over the menubar */   protected void processMouseEvent(MouseEvent e) {     int type = e.getID(); // What type of event?     int item = findItemAt(e.getX()); // Over which menu label?     if (type == MouseEvent.MOUSE_PRESSED) {       // If it was a mouse down event, then pop up the menu       if (item == -1)         return;       Dimension size = getSize();       PopupMenu pm = (PopupMenu) menus.elementAt(item);       if (pm != null)         pm.show(this, startPositions[item] - 3, size.height);     } else if (type == MouseEvent.MOUSE_EXITED) {       // If the mouse left the menubar, then unhighlight       if (highlightedItem != -1) {         highlightedItem = -1;         if (highlightColor != null)           repaint();       }     } else if ((type == MouseEvent.MOUSE_MOVED)         || (type == MouseEvent.MOUSE_ENTERED)) {       // If the mouse moved, change the highlighted item, if necessary       if (item != highlightedItem) {         highlightedItem = item;         if (highlightColor != null)           repaint();       }     }   }   /** This method is called when the mouse moves */   protected void processMouseMotionEvent(MouseEvent e) {     processMouseEvent(e);   }   /** This utility method converts an X coordinate to a menu label index */   protected int findItemAt(int x) {     // This could be a more efficient search...     int nummenus = labels.size();     int halfspace = spacing / 2 - 1;     int i;     for (i = nummenus - 1; i >= 0; i--) {       if ((x >= startPositions[i] - halfspace)           && (x <= startPositions[i] + widths[i] + halfspace))         break;     }     return i;   }   /**    * Measure the menu labels, and figure out their positions, so we can    * determine when a click happens, and so we can redraw efficiently.    */   protected void measure() {     // Get information about the font     FontMetrics fm = this.getFontMetrics(getFont());     // Remember the basic font size     ascent = fm.getAscent();     descent = fm.getDescent();     // Create arrays to hold the measurements and positions     int nummenus = labels.size();     widths = new int[nummenus];     startPositions = new int[nummenus];     // Measure the label strings and     // figure out the starting position of each label     int pos = margins.left;     for (int i = 0; i < nummenus; i++) {       startPositions[i] = pos;       String label = (String) labels.elementAt(i);       widths[i] = fm.stringWidth(label);       pos += widths[i] + spacing;     }     // Compute our preferred size from this data     prefsize.width = pos - spacing + margins.right;     prefsize.height = ascent + descent + margins.top + margins.bottom;     // We've don't need to be remeasured anymore.     remeasure = false;   }   /**    * These methods tell the container how big the menubar wants to be.    *      */   public Dimension getMinimumSize() {     return getPreferredSize();   }   public Dimension getPreferredSize() {     if (remeasure)       measure();     return prefsize;   }   /** @deprecated Here for compatibility with Java 1.0 */   public Dimension minimumSize() {     return getPreferredSize();   }   /** @deprecated Here for compatibility with Java 1.0 */   public Dimension preferredSize() {     return getPreferredSize();   }   /**    * This method is called when the underlying AWT component is created. We    * can't measure ourselves (no font metrics) until this is called.    */   public void addNotify() {     super.addNotify();     measure();   }   /** This method tells the container not to give us keyboard focus */   public boolean isFocusTraversable() {     return false;   } }