Source for javax.swing.DefaultCellEditor

   1: /* DefaultCellEditor.java --
   2:    Copyright (C) 2002, 2004, 2006, 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;
  40: 
  41: import java.awt.Component;
  42: import java.awt.event.ActionEvent;
  43: import java.awt.event.ActionListener;
  44: import java.awt.event.ItemEvent;
  45: import java.awt.event.ItemListener;
  46: import java.awt.event.MouseEvent;
  47: import java.io.Serializable;
  48: import java.util.EventObject;
  49: 
  50: import javax.swing.JTable;
  51: import javax.swing.JTextField;
  52: import javax.swing.event.CellEditorListener;
  53: import javax.swing.table.TableCellEditor;
  54: import javax.swing.tree.TreeCellEditor;
  55: 
  56: /**
  57:  * The default implementation of {@link TableCellEditor} and
  58:  * {@link TreeCellEditor}. It provides editor components for
  59:  * some standard object types.
  60:  * 
  61:  * @author Andrew Selkirk
  62:  * @author Audrius Meskauskas
  63:  */
  64: public class DefaultCellEditor
  65:   extends AbstractCellEditor
  66:   implements TableCellEditor, TreeCellEditor
  67: {
  68:   private static final long serialVersionUID = 3564035141373880027L;
  69: 
  70:   /**
  71:    * This changeable module access the editor component in the component
  72:    * specific way. For instance, to set the value for JTextField, we need to 
  73:    * call setText(String), and for JCheckBox we need to call 
  74:    * setSelected(boolean). Each default editor has the component specific
  75:    * derivative of this class. These derivatives are private inner classes of
  76:    * the DefaultCellEditor.
  77:    * 
  78:    * The editor delegate is also set for the editor component as the action
  79:    * listener. It listens for the events that indicate that editing has stopped.
  80:    */
  81:   protected class EditorDelegate
  82:     implements ActionListener, ItemListener, Serializable
  83:   {
  84:     /**
  85:      * Use the serial version UID for interoperability.
  86:      */
  87:     private static final long serialVersionUID = -1420007406015481933L;
  88: 
  89:     /**
  90:      * The object value (updated when getting and setting the value).
  91:      */
  92:     protected Object value;
  93: 
  94:     /**
  95:      * Constructor EditorDelegate
  96:      */
  97:     protected EditorDelegate()
  98:     {
  99:       // Nothing to do here.
 100:     }
 101:     
 102:     /**
 103:      * Set the value for the editor component. This method is normally
 104:      * overridden to set the value in the way, specific for the text
 105:      * component, check box or combo box.
 106:      *
 107:      * @param aValue the value to set (String, Boolean or Number).
 108:      */
 109:     public void setValue(Object aValue)
 110:     {
 111:       value = aValue;
 112:     }
 113: 
 114:     /**
 115:      * Get the value for the editor component. This method is normally
 116:      * overridden to obtain the value in the way, specific for the text
 117:      * component, check box or combo box.
 118:      *
 119:      * @return value the value of the component (String, Boolean or Number).
 120:      */
 121:     public Object getCellEditorValue()
 122:     {
 123:       return value;
 124:     } 
 125: 
 126:     /**
 127:      * The default method returns true for the {@link MouseEvent} and false 
 128:      * for any other events.
 129:      * 
 130:      * @param event the event to check
 131:      *
 132:      * @return true if the passed event is the mouse event and false otherwise.
 133:      */
 134:     public boolean isCellEditable(EventObject event)
 135:     {
 136:       if (event == null || !(event instanceof MouseEvent) ||
 137:           (((MouseEvent) event).getClickCount() >= getClickCountToStart()))
 138:         return true;
 139:       return false;
 140:     } // isCellEditable()
 141: 
 142:     /**
 143:      * Returns true to indicate that the editing cell can be selected.
 144:      * 
 145:      * The default method returns true without action but may be overridden
 146:      * in derived classes for more specific behavior.
 147:      * 
 148:      * @param event unused in default method
 149:      *
 150:      * @return true always
 151:      */
 152:     public boolean shouldSelectCell(EventObject event)
 153:     {
 154:       // return true to indicate that the editing cell may be selected
 155:       return true;
 156:     }
 157: 
 158:     /**
 159:      * Finish the cell editing session. This method notifies the registered
 160:      * cell editor listeners (including the table) that the editing has been
 161:      * stopped. 
 162:      * 
 163:      * @return boolean
 164:      */
 165:     public boolean stopCellEditing()
 166:     {
 167:       fireEditingStopped();
 168:       return true;
 169:     } // stopCellEditing()
 170: 
 171:     /**
 172:      * Cancel the cell editing session. This method notifies the registered
 173:      * cell editor listeners (including the table) that the editing has been
 174:      * canceled.
 175:      */
 176:     public void cancelCellEditing()
 177:     {
 178:       fireEditingCanceled();
 179:     } // cancelCellEditing()
 180: 
 181:     /**
 182:      * Start editing session and returns true to indicate the editing has begun.
 183:      * The default method returns true without action but may be overridden
 184:      * in derived classes for more specific behavior.
 185:      * 
 186:      * @param event  the event.
 187:      * 
 188:      * @return true, always
 189:      */
 190:     public boolean startCellEditing(EventObject event)
 191:     {
 192:       // return true to indicate that editing has begun
 193:       return true;
 194:     } // startCellEditing()
 195: 
 196:     /**
 197:      * This event is fired by the editor component (for instance, by pressing
 198:      * ENTER in the {@link JTextField}. The default method delegates call to
 199:      * the {@link #stopCellEditing}, finishing the editing session. 
 200:      * 
 201:      * @param event unused in default method
 202:      */
 203:     public void actionPerformed(ActionEvent event)
 204:     {
 205:       stopCellEditing();
 206:     } // actionPerformed()
 207: 
 208:     /**
 209:      * This event is fired by the editor component.The default method delegates
 210:      * call to the {@link #stopCellEditing}, finishing the editing session. 
 211:      * 
 212:      * @param event unused in default method
 213:      */
 214:     public void itemStateChanged(ItemEvent event)
 215:     {
 216:       stopCellEditing();
 217:     } // itemStateChanged()
 218: 
 219:     /**
 220:      * Notify the registered listeners (including the table) that the editing
 221:      * has been completed.
 222:      */
 223:     void fireEditingStopped()
 224:     {
 225:       CellEditorListener[] listeners = getCellEditorListeners();
 226:       for (int index = 0; index < listeners.length; index++)
 227:         listeners[index].editingStopped(changeEvent);
 228:       
 229:     }
 230:     
 231:     /**
 232:      * Notify the registered listeners (including the table) that the editing
 233:      * has been canceled.
 234:      */
 235:     void fireEditingCanceled()
 236:     {
 237:       CellEditorListener[] listeners = getCellEditorListeners();
 238:       for (int index = 0; index < listeners.length; index++)
 239:         listeners[index].editingCanceled(changeEvent);
 240:     }
 241:   } // EditorDelegate
 242:   
 243:   /**
 244:    * Provides getter and setter methods to work with the text component.
 245:    * 
 246:    * @author Audrius Meskauskas (audriusa@Bioinformatics.org)
 247:    */
 248:   private class JTextFieldDelegate extends EditorDelegate
 249:   {
 250:     /**
 251:      * Use the serial version UID for interoperability.
 252:      */
 253:     private static final long serialVersionUID = 1;
 254:     
 255:     /**
 256:      * Set the value for the editor component.
 257:      *
 258:      * @param aValue the value to set (toString() will be called).
 259:      */
 260:     public void setValue(Object aValue)
 261:     {
 262:       value = aValue;
 263:       JTextField f = (JTextField) editorComponent;
 264:       if (value == null)
 265:         f.setText("");
 266:       else
 267:         f.setText(value.toString());
 268:     }
 269: 
 270:     /**
 271:      * Get the value for the editor component. 
 272:      *
 273:      * @return value the value of the component (String)
 274:      */
 275:     public Object getCellEditorValue()
 276:     {
 277:       JTextField f = (JTextField) editorComponent;
 278:       return value = f.getText();      
 279:     }     
 280:   }
 281: 
 282:   /**
 283:    * Provides getter and setter methods to work with the combo box.
 284:    * 
 285:    * @author Audrius Meskauskas (audriusa@Bioinformatics.org) 
 286:    */
 287:   private class JComboBoxDelegate extends EditorDelegate
 288:   {
 289:     /**
 290:      * Use the serial version UID for interoperability.
 291:      */
 292:     private static final long serialVersionUID = 1;
 293:     
 294:     /**
 295:      * Set the value for the editor component.
 296:      *
 297:      * @param aValue the value to set.
 298:      */
 299:     public void setValue(Object aValue)
 300:     {
 301:       value = aValue;      
 302:       JComboBox c = (JComboBox) editorComponent;
 303:       if (value != null)
 304:         c.setSelectedItem(value);
 305:     }
 306: 
 307:     /**
 308:      * Get the value for the editor component. 
 309:      *
 310:      * @return value the value of the component (as String)
 311:      */
 312:     public Object getCellEditorValue()
 313:     {
 314:       JComboBox c = (JComboBox) editorComponent;
 315:       return value = c.getSelectedItem();
 316:     } 
 317:     
 318:     /**
 319:      * Returns true to indicate that the editing cell can be selected. If the
 320:      * check box is not editable, expands it. If it is editable, brings
 321:      * focus to the editor field.
 322:      * 
 323:      * @param event unused in default method
 324:      *
 325:      * @return true always
 326:      */
 327:     public boolean shouldSelectCell(EventObject event)
 328:     {
 329:       JComboBox c = (JComboBox) editorComponent;
 330:       if (!c.isEditable)
 331:         c.showPopup();
 332:       return true;
 333:     }    
 334:   }
 335: 
 336:   /**
 337:    * Provides getter and setter methods to work with the check box.
 338:    * 
 339:    * @author Audrius Meskauskas (audriusa@Bioinformatics.org) 
 340:    */
 341:   private class JCheckBoxDelegate extends EditorDelegate
 342:   {
 343:     /**
 344:      * Use the serial version UID for interoperability.
 345:      */
 346:     private static final long serialVersionUID = 1;
 347:     
 348:     /**
 349:      * Set the value for the editor component.
 350:      *
 351:      * @param value the value to set (must be Boolean).
 352:      */
 353:     public void setValue(Object value)
 354:     {
 355:       JCheckBox c = (JCheckBox) editorComponent;
 356:       
 357:       if (value == null)
 358:         c.setSelected(false);
 359:       else
 360:         c.setSelected( ((Boolean) value).booleanValue());
 361:     }
 362: 
 363:     /**
 364:      * Get the value for the editor component. 
 365:      *
 366:      * @return value the value of the component (must be CharSequence)
 367:      */
 368:     public Object getCellEditorValue()
 369:     {
 370:       JCheckBox c = (JCheckBox) editorComponent;
 371:       value = c.isSelected() ? Boolean.TRUE : Boolean.FALSE;
 372:       return value;
 373:     }     
 374:   }
 375:   
 376:   /**
 377:    * The Swing JComponent, performing the editing session.
 378:    */
 379:   protected JComponent editorComponent;
 380: 
 381:   /**
 382:    * The editor delegate, responsible for listening the {@link #editorComponent}
 383:    * events and getting/setting its value.
 384:    */
 385:   protected EditorDelegate delegate;
 386: 
 387:   /**
 388:    * The number of the mouse clicks, required to start the editing session.
 389:    */
 390:   protected int clickCountToStart;
 391: 
 392:   /**
 393:    * Create the DefaultCellEditor that uses the text field as its editor
 394:    * component (appropriate for the text content)
 395:    * 
 396:    * @param textfield the text field as will be used as the editor component
 397:    */
 398:   public DefaultCellEditor(JTextField textfield)
 399:   {
 400:     editorComponent = textfield;
 401:     clickCountToStart = 2;
 402:     delegate = new JTextFieldDelegate();
 403:     textfield.addActionListener(delegate);
 404:   } // DefaultCellEditor()
 405: 
 406:   /**
 407:    * Constructor DefaultCellEditor that uses the checkbox (appropriate
 408:    * for boolean values)
 409:    * 
 410:    * @param checkbox the checkbox that will be used with this editor.
 411:    */
 412:   public DefaultCellEditor(JCheckBox checkbox)
 413:   {
 414:     editorComponent = checkbox;
 415:     clickCountToStart = 1;
 416:     delegate = new JCheckBoxDelegate();
 417:     checkbox.addActionListener(delegate);
 418:   } // DefaultCellEditor()
 419: 
 420:   /**
 421:    * Constructor DefaultCellEditor that uses the combo box.
 422:    * 
 423:    * @param combobox the combo box that will be used with this editor.
 424:    */
 425:   public DefaultCellEditor(JComboBox combobox)
 426:   {
 427:     editorComponent = combobox;
 428:     clickCountToStart = 1;
 429:     delegate = new JComboBoxDelegate();
 430:     combobox.addActionListener(delegate);
 431:   } // DefaultCellEditor()
 432: 
 433:   /**
 434:    * Get the component that performs the editing sessions. It is the same 
 435:    * component that was passed in constructor.
 436:    * 
 437:    * @return the component, performing the editing sessions. 
 438:    */
 439:   public Component getComponent()
 440:   {
 441:     return editorComponent; 
 442:   } // getComponent()
 443: 
 444:   /**
 445:    * Get the number of mouse clicks, required to start the editing session.
 446:    * 
 447:    * @return int the number of mouse clicks, required to start the session
 448:    */
 449:   public int getClickCountToStart()
 450:   {
 451:     return clickCountToStart;
 452:   } // getClickCountToStart()
 453: 
 454:   /**
 455:    * Set the number of mouse clicks, required to start the editing session.
 456:    * 
 457:    * @param count the number of clicks, required to start the session
 458:    */
 459:   public void setClickCountToStart(int count)
 460:   {
 461:     clickCountToStart = count;
 462:   } // setClickCountToStart()
 463: 
 464:   /**
 465:    * Get the value, currently being displayed by the editor component. The 
 466:    * call is forwarded to the {@link #delegate}.
 467:    * 
 468:    * @return Object the value (class depends on the editor component)
 469:    */
 470:   public Object getCellEditorValue()
 471:   {
 472:     return delegate.getCellEditorValue();
 473:   } // getCellEditorValue()
 474: 
 475:   /**
 476:    * Forwards call to the {@link #delegate}.
 477:    * 
 478:    * @param event forwarded to the delegate.
 479:    *
 480:    * @return boolean returned by delegate
 481:    */
 482:   public boolean isCellEditable(EventObject event)
 483:   {
 484:     return delegate.isCellEditable(event);
 485:   } // isCellEditable()
 486: 
 487:   /**
 488:    * Forwards call to the {@link #delegate}.
 489:    * 
 490:    * @param event forwarded to the delegate.
 491:    *
 492:    * @return boolean returned by delegate
 493:    */
 494:   public boolean shouldSelectCell(EventObject event)
 495:   {
 496:     return delegate.shouldSelectCell(event);
 497:   } // shouldSelectCell()
 498: 
 499:   /**
 500:    * Forwards call to the {@link #delegate}.
 501:    * 
 502:    * @return boolean returned by delegate
 503:    */
 504:   public boolean stopCellEditing()
 505:   {
 506:     return delegate.stopCellEditing();
 507:   } // stopCellEditing()
 508: 
 509:   /**
 510:    * Forwards call to the {@link #delegate}.
 511:    */
 512:   public void cancelCellEditing()
 513:   {
 514:     delegate.cancelCellEditing();
 515:   } // cancelCellEditing()
 516: 
 517:   /**
 518:    * Sets an initial value for the editor. 
 519:    * This will cause the editor to stopEditing and lose any partially 
 520:    * edited value if the editor is editing when this method is called.
 521:    * Returns the component that should be added to the client's Component 
 522:    * hierarchy. Once installed in the client's hierarchy this component will 
 523:    * then be able to draw and receive user input. 
 524:    * 
 525:    * @param tree - the JTree that is asking the editor to edit; this 
 526:    * parameter can be null
 527:    * @param value - the value of the cell to be edited
 528:    * @param isSelected - true is the cell is to be renderer with selection
 529:    * highlighting
 530:    * @param expanded - true if the node is expanded
 531:    * @param leaf - true if the node is a leaf node
 532:    * @param row - the row index of the node being edited
 533:    *
 534:    * @return Component the component for editing
 535:    */
 536:   public Component getTreeCellEditorComponent(JTree tree, Object value,
 537:                                               boolean isSelected,
 538:                                               boolean expanded, boolean leaf,
 539:                                               int row)
 540:   {
 541:     delegate.setValue(value);
 542:     return editorComponent;
 543:   } // getTreeCellEditorComponent()
 544: 
 545:   /**
 546:    * Get the cell editor component that will perform the editing session. If
 547:    * returned once, the same component is also returned on the repetetive calls
 548:    * again (reused).
 549:    * 
 550:    * @param table the table where the editing is performed
 551:    * @param value the current value of the table. It is set as the initial 
 552:    *        component value.
 553:    * @param isSelected if true, the cell is currently selected
 554:    * @param row the row of the cell being edited
 555:    * @param column the column of the cell being edited
 556:    * 
 557:    * @return Component the component that will perform the editing session
 558:    */
 559:   public Component getTableCellEditorComponent(JTable table, Object value,
 560:                                                boolean isSelected, int row,
 561:                                                int column)
 562:   {
 563:     // NOTE: as specified by Sun, we don't call new() everytime, we return 
 564:     // editorComponent on each call to getTableCellEditorComponent or
 565:     // getTreeCellEditorComponent.
 566:     delegate.setValue(value);
 567:     return editorComponent;
 568:   } // getTableCellEditorComponent()
 569: 
 570: }