Source for javax.swing.plaf.metal.MetalComboBoxUI

   1: /* MetalComboBoxUI.java
   2:    Copyright (C) 2005 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package javax.swing.plaf.metal;
  40: 
  41: import java.awt.Container;
  42: import java.awt.Dimension;
  43: import java.awt.Graphics;
  44: import java.awt.Insets;
  45: import java.awt.LayoutManager;
  46: import java.awt.Rectangle;
  47: import java.awt.event.MouseEvent;
  48: import java.beans.PropertyChangeEvent;
  49: import java.beans.PropertyChangeListener;
  50: 
  51: import javax.swing.CellRendererPane;
  52: import javax.swing.ComboBoxEditor;
  53: import javax.swing.Icon;
  54: import javax.swing.JButton;
  55: import javax.swing.JComboBox;
  56: import javax.swing.JComponent;
  57: import javax.swing.plaf.ComponentUI;
  58: import javax.swing.plaf.basic.BasicComboBoxUI;
  59: import javax.swing.plaf.basic.BasicComboPopup;
  60: import javax.swing.plaf.basic.ComboPopup;
  61: 
  62: 
  63: /**
  64:  * A UI delegate for the {@link JComboBox} component.
  65:  */
  66: public class MetalComboBoxUI extends BasicComboBoxUI
  67: {
  68:   /**
  69:    * A layout manager that arranges the editor component (if active) and the
  70:    * button that make up the combo box.
  71:    */
  72:   public class MetalComboBoxLayoutManager
  73:     extends BasicComboBoxUI.ComboBoxLayoutManager
  74:   {
  75:     /**
  76:      * Creates a new instance of the layout manager.
  77:      */
  78:     public MetalComboBoxLayoutManager()
  79:     {
  80:       // Nothing to do here.
  81:     }
  82:     
  83:     /**
  84:      * Arranges the editor (if visible) and button that comprise the combo
  85:      * box.
  86:      * 
  87:      * @param parent  the parent.
  88:      */
  89:     public void layoutContainer(Container parent)
  90:     {
  91:       JComboBox cb = (JComboBox) parent;
  92:       if (!cb.isEditable())
  93:         {
  94:           Rectangle bounds = parent.getBounds();
  95:           arrowButton.setBounds(0, 0, bounds.width, bounds.height);
  96:         }
  97:       else 
  98:         superLayout(parent);
  99:     }
 100:     
 101:     /**
 102:      * Calls the <code>layoutContainer(Container)</code> method in the super 
 103:      * class.
 104:      * 
 105:      * @param parent  the container.
 106:      */
 107:     public void superLayout(Container parent)
 108:     {
 109:       super.layoutContainer(parent);
 110:     }
 111:   }
 112:   
 113:   /**
 114:    * A listener used to handle property changes in the {@link JComboBox} 
 115:    * component, to ensure that the UI delegate accurately reflects the current
 116:    * state in the rendering onscreen.
 117:    */
 118:   public class MetalPropertyChangeListener
 119:     extends BasicComboBoxUI.PropertyChangeHandler
 120:   {
 121:     /**
 122:      * Creates a new listener.
 123:      */
 124:     public MetalPropertyChangeListener()
 125:     {
 126:       // Nothing to do here.
 127:     }
 128:     
 129:     /**
 130:      * Handles a property change event, updating the UI components as
 131:      * appropriate.
 132:      * 
 133:      * @param e  the event.
 134:      */
 135:     public void propertyChange(PropertyChangeEvent e)
 136:     {
 137:       if (e.getPropertyName().equals("editable"))
 138:         editablePropertyChanged(e);
 139:       super.propertyChange(e);
 140:     }
 141:   }
 142: 
 143:   /**
 144:    * A popup menu for the combo-box.
 145:    * 
 146:    * @see #createPopup()
 147:    *
 148:    * @deprecated 1.4
 149:    */
 150:   public class MetalComboPopup extends BasicComboPopup
 151:   {
 152:     /**
 153:      * Creates a new popup.
 154:      * 
 155:      * @param cBox  the combo box.
 156:      */
 157:     public MetalComboPopup(JComboBox cBox)
 158:     {
 159:       super(cBox); 
 160:     }
 161:     
 162:     public void delegateFocus(MouseEvent e)
 163:     {
 164:       super.delegateFocus(e);
 165:     }
 166:   }
 167:   
 168:   /**
 169:    * Constructs a new instance of MetalComboBoxUI.
 170:    */
 171:   public MetalComboBoxUI()
 172:   {
 173:     super();
 174:   }
 175: 
 176:   /**
 177:    * Returns an instance of MetalComboBoxUI.
 178:    *
 179:    * @param component the component for which we return an UI instance
 180:    *
 181:    * @return an instance of MetalComboBoxUI
 182:    */
 183:   public static ComponentUI createUI(JComponent component)
 184:   {
 185:     return new MetalComboBoxUI();
 186:   }
 187:   
 188:   /**
 189:    * Creates an editor for the combo box.
 190:    * 
 191:    * @return An editor.
 192:    */
 193:   protected ComboBoxEditor createEditor()
 194:   {
 195:     return new MetalComboBoxEditor.UIResource();   
 196:   }
 197:   
 198:   /**
 199:    * Creates a popup for the combo box.
 200:    * 
 201:    * @return A popup.
 202:    */
 203:   protected ComboPopup createPopup()
 204:   {
 205:     return new MetalComboPopup(comboBox);
 206:   }
 207:   
 208:   /**
 209:    * Creates a new button for use in rendering the JComboBox.
 210:    * 
 211:    * @return A button.
 212:    */
 213:   protected JButton createArrowButton()
 214:   {
 215:     JButton button = new MetalComboBoxButton(comboBox, new MetalComboBoxIcon(), 
 216:             new CellRendererPane(), listBox);  
 217:     button.setMargin(new Insets(0, 1, 1, 3));
 218:     return button;
 219:   }
 220:   
 221:   /**
 222:    * Creates a new property change listener.
 223:    * 
 224:    * @return A new property change listener.
 225:    */
 226:   public PropertyChangeListener createPropertyChangeListener()
 227:   {
 228:     return new MetalPropertyChangeListener();
 229:   }
 230:   
 231:   public void paint(Graphics g, JComponent c)
 232:   {
 233:     // do nothing, the button and text field are painted elsewhere
 234:   }
 235:   
 236:   /**
 237:    * Updates the button and text field to reflect a change in the 'editable'
 238:    * property.
 239:    * 
 240:    * @param e  the event.
 241:    * 
 242:    * @deprecated 1.4
 243:    */
 244:   protected void editablePropertyChanged(PropertyChangeEvent e)
 245:   {
 246:     if (arrowButton instanceof MetalComboBoxButton)
 247:       {
 248:         MetalComboBoxButton b = (MetalComboBoxButton) arrowButton;
 249:         b.setIconOnly(comboBox.isEditable());
 250:       }
 251:     if (comboBox.isEditable())
 252:       {
 253:         arrowButton.setText(null);
 254:         if (editor != null)
 255:           editor.setVisible(true);
 256:       }
 257:     else
 258:       {
 259:         String text = "";
 260:         Object selected = comboBox.getSelectedItem();
 261:         if (selected != null)
 262:           text = selected.toString();
 263:         arrowButton.setText(text);
 264:         if (editor != null)
 265:           editor.setVisible(true);
 266:       }
 267:   }
 268:   
 269:   /**
 270:    * Creates a new layout manager for the UI delegate.
 271:    * 
 272:    * @return A new layout manager.
 273:    */
 274:   protected LayoutManager createLayoutManager()
 275:   {
 276:     return new MetalComboBoxLayoutManager();
 277:   }
 278:   
 279:   /**
 280:    * Not used in Classpath.
 281:    * 
 282:    * @deprecated 1.4
 283:    */
 284:   protected void removeListeners()
 285:   {
 286:     // no longer used in JDK 1.4 
 287:   }
 288:   
 289:   /**
 290:    * Returns the minimum size for the combo.
 291:    * 
 292:    * @param c  the component
 293:    * 
 294:    * @return The minimum size for the combo box.
 295:    */
 296:   public Dimension getMinimumSize(JComponent c)
 297:   {
 298:     Dimension d = getDisplaySize();
 299:     MetalComboBoxButton b = (MetalComboBoxButton) arrowButton;
 300:     Insets insets = b.getInsets();
 301:     int insetsH = insets.top + insets.bottom;
 302:     int insetsW = insets.left + insets.right;
 303:     if (!comboBox.isEditable())
 304:       {
 305:         Icon icon = b.getComboIcon();
 306:         int iconWidth = icon.getIconWidth() + 6;
 307:         return new Dimension(d.width + insetsW + iconWidth, d.height + insetsH);
 308:       }
 309:     else
 310:       // FIXME: the following dimensions pass most of the Mauve tests, but
 311:       // I don't yet understand the logic behind this...it is probably wrong
 312:       return new Dimension(d.width + insetsW + (d.height + insetsH) - 4, 
 313:           d.height + insetsH + 1);
 314:   }
 315:   
 316:   /**
 317:    * Configures the editor for this combo box.
 318:    */
 319:   public void configureEditor()
 320:   {
 321:     ComboBoxEditor cbe = comboBox.getEditor();
 322:     if (cbe != null)
 323:       {
 324:         cbe.getEditorComponent().setFont(comboBox.getFont());
 325:         cbe.setItem(comboBox.getSelectedItem());
 326:         cbe.addActionListener(comboBox);
 327:       }
 328:   }
 329:   
 330:   /**
 331:    * Unconfigures the editor for this combo box.
 332:    */
 333:   public void unconfigureEditor()
 334:   {
 335:     ComboBoxEditor cbe = comboBox.getEditor();
 336:     if (cbe != null)
 337:       {
 338:         cbe.getEditorComponent().setFont(null);
 339:         cbe.setItem(null);
 340:         cbe.removeActionListener(comboBox);
 341:       }
 342:   }
 343:   
 344:   /** 
 345:    * Lays out the ComboBox
 346:    */
 347:   public void layoutComboBox(Container parent,
 348:                              MetalComboBoxUI.MetalComboBoxLayoutManager manager)
 349:   {
 350:     manager.layoutContainer(parent);
 351:   }
 352: }