001    /* 
002     * Copyright (c) Holger Pfaff - http://pfaff.ws
003     *
004     * This software maybe used for any purpose provided the
005     * above copyright notice is retained. It is supplied as is.
006     * No warranty expressed or implied - Use at your own risk.
007     */
008    
009    import java.awt.*;
010    import java.awt.event.*;
011    import java.util.*;
012    
013    /**
014      * (#)MenuKnob.java
015      * @author   Holger Pfaff
016      * @version  3.2 19-Mar-2004<br><br> 
017      *
018      * A button that has a popup menu attatched to it
019      *
020      */
021    
022    public class MenuKnob extends Knob implements ActionListener {
023    
024      /**   
025       * String that is recognized as a separator
026       */
027      public static final String SEPARATOR = "---";
028      
029      /**   
030       * fifo that holds the menu items
031       */
032      protected Fifo   menuItems = new Fifo();
033      
034      /**   
035       * currently selected item 0 = first
036       */
037      protected int selectedItem = 0;
038      
039      /**
040       * Standard constructor - no label - empty menu
041       */
042      public MenuKnob() {
043        this(new String[0]);
044      }
045      
046      /**
047       * MenuKnob constructor - no label - initial menu
048       *
049       * @param   menuItems   initial menu items
050       */
051      public MenuKnob(String[] menuItems) {
052        this("", menuItems);
053      }
054      
055      /**
056       * MenuKnob constructor - initial label - initial menu
057       *
058       * @param   label   initial label
059       * @param   menuItems   initial menu items
060       */
061      public MenuKnob(String label, String[] menuItems) {
062        super(label);
063        for(int i = 0; i < menuItems.length; ++i) {
064          this.menuItems.in(menuItems[i]);
065        }
066        iconDist = 3;
067        iconPos  = RIGHT;
068        mode     = LEFT;
069      }
070      
071      /**
072       * replace this widgets datamodel - give it a new menu
073       *
074       * @param   f   fifo holding menu items
075       */
076      public void setFifo(Fifo f) {
077        menuItems = f;
078      }
079      
080      /**
081       * append a menu item
082       *
083       * @param   item   item to append
084       */
085      public void addItem(String item) {
086        menuItems.in(item);
087        doMeasure();
088      }
089      
090      /**
091       * return a menu item
092       *
093       * @param   i  index of item to return
094       */
095      public String getItem(int i) {
096        return (String) menuItems.elementAt(i);
097      }
098      
099      /**
100       * return number of items in menu
101       */
102      public int getItemCount() {
103        return menuItems.size();
104      }
105      
106      /**
107       * return index of currently selected item
108       */
109      public int getSelectedIndex() {
110        return selectedItem;
111      }
112      
113      /**
114       * set selected item
115       *
116       * @param   i  index of item to select
117       */
118      public void setSelectedIndex(int i) {
119        select(i);
120      }
121      
122      /**
123       * return currently selected item
124       */
125      public String getSelectedItem() {
126        return (String) menuItems.elementAt(selectedItem);
127      }
128      
129      /**
130       * set selected item - first matching
131       *
132       * @param   i  string of item to select
133       */
134      public void select(String i) {
135        select(menuItems.indexOf(i));
136      }
137      
138      /**
139       * set selected item
140       *
141       * @param   i  index of item to select
142       */
143      public void select(int i) {
144        if(i > 0 && i < menuItems.size()) {
145          selectedItem = i;
146          repaint();
147        }
148      }
149      
150      /**
151       * return dims needed for icon
152       */
153      public Dimension measureIcon() {
154        int h = measureCaption("X", getFont(), getFont(), "").height;
155        return new Dimension(h, h);
156      }
157    
158      /**
159       * Paint the Icon
160       *
161       * @param   g       Graphics object to use
162       * @param   x       x-position of describing rect
163       * @param   y       y-position of describing rect
164       * @param   w       width of describing rect
165       * @param   h       height of describing rect
166       */
167      public void paintIcon(Graphics g, int x, int y, int w, int h) {
168        drawTriangle(g, getBackground(), x + 1, y + 1, w - 2, h - 2, 1, RAISED | S);
169      }
170    
171      /**
172       * pop up the menu
173       */
174      public void onPress() {
175        synchronized(this) {
176          PopupMenu popup = new PopupMenu();
177          popup.addActionListener(this);
178          removeAll(); 
179          add(popup);
180          popup.setFont(getFont());
181          //popup.setBackground(getBackground());
182          //popup.setForeground(getForeground());
183          for(int i = 0; i < getItemCount(); ++i) {
184            if(getItem(i).equals(SEPARATOR)) {
185              popup.addSeparator();
186            } else {
187              popup.add(getItem(i));
188            }
189          }
190          popup.show(this, insets.left, this.getSize().height - insets.bottom);
191          setEntered(false);
192        }
193      }
194      
195      /**
196       * notify our listeners
197       */
198      public void actionPerformed(ActionEvent e) {
199        selectedItem = menuItems.indexOf(e.getActionCommand()); repaint(); 
200        notifyItemListeners(new ItemEvent(this, selectedItem, menuItems.elementAt(selectedItem), ItemEvent.SELECTED));
201      }
202      
203      /**
204       * implement ItemSelectable
205       */
206      public Object[] getSelectedObjects() {
207        Object[] obj = new Object[1];
208        obj[0] = menuItems.elementAt(selectedItem);
209        return obj;
210      }
211    }