KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jface > viewers > CellEditor


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.jface.viewers;
13
14 import org.eclipse.core.runtime.ListenerList;
15 import org.eclipse.core.runtime.Assert;
16 import org.eclipse.jface.util.IPropertyChangeListener;
17 import org.eclipse.jface.util.PropertyChangeEvent;
18 import org.eclipse.jface.util.SafeRunnable;
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.events.KeyEvent;
21 import org.eclipse.swt.widgets.Composite;
22 import org.eclipse.swt.widgets.Control;
23
24 /**
25  * Abstract base class for cell editors. Implements property change listener handling,
26  * and SWT window management.
27  * <p>
28  * Subclasses implement particular kinds of cell editors. This package contains various
29  * specialized cell editors:
30  * <ul>
31  * <li><code>TextCellEditor</code> - for simple text strings</li>
32  * <li><code>ColorCellEditor</code> - for colors</li>
33  * <li><code>ComboBoxCellEditor</code> - value selected from drop-down combo box</li>
34  * <li><code>CheckboxCellEditor</code> - boolean valued checkbox</li>
35  * <li><code>DialogCellEditor</code> - value from arbitrary dialog</li>
36  * </ul>
37  * </p>
38  */

39 public abstract class CellEditor {
40
41     /**
42      * List of cell editor listeners (element type: <code>ICellEditorListener</code>).
43      */

44     private ListenerList listeners = new ListenerList();
45
46     /**
47      * List of cell editor property change listeners
48      * (element type: <code>IPropertyChangeListener</code>).
49      */

50     private ListenerList propertyChangeListeners = new ListenerList();
51
52     /**
53      * Indicates whether this cell editor's current value is valid.
54      */

55     private boolean valid = false;
56
57     /**
58      * Optional cell editor validator; <code>null</code> if none.
59      */

60     private ICellEditorValidator validator = null;
61
62     /**
63      * The error message string to display for invalid values;
64      * <code>null</code> if none (that is, the value is valid).
65      */

66     private String JavaDoc errorMessage = null;
67
68     /**
69      * Indicates whether this cell editor has been changed recently.
70      */

71     private boolean dirty = false;
72
73     /**
74      * This cell editor's control, or <code>null</code>
75      * if not created yet.
76      */

77     private Control control = null;
78
79     /**
80      * Default cell editor style
81      */

82     private static final int defaultStyle = SWT.NONE;
83
84     /**
85      * This cell editor's style
86      */

87     private int style = defaultStyle;
88
89     /**
90      * Struct-like layout data for cell editors, with reasonable defaults
91      * for all fields.
92      */

93     public static class LayoutData {
94         /**
95          * Horizontal alignment; <code>SWT.LEFT</code> by default.
96          */

97         public int horizontalAlignment = SWT.LEFT;
98
99         /**
100          * Indicates control grabs additional space; <code>true</code> by default.
101          */

102         public boolean grabHorizontal = true;
103
104         /**
105          * Minimum width in pixels; <code>50</code> pixels by default.
106          */

107         public int minimumWidth = 50;
108     }
109
110     /**
111      * Property name for the copy action
112      */

113     public static final String JavaDoc COPY = "copy"; //$NON-NLS-1$
114

115     /**
116      * Property name for the cut action
117      */

118     public static final String JavaDoc CUT = "cut"; //$NON-NLS-1$
119

120     /**
121      * Property name for the delete action
122      */

123     public static final String JavaDoc DELETE = "delete"; //$NON-NLS-1$
124

125     /**
126      * Property name for the find action
127      */

128     public static final String JavaDoc FIND = "find"; //$NON-NLS-1$
129

130     /**
131      * Property name for the paste action
132      */

133     public static final String JavaDoc PASTE = "paste"; //$NON-NLS-1$
134

135     /**
136      * Property name for the redo action
137      */

138     public static final String JavaDoc REDO = "redo"; //$NON-NLS-1$
139

140     /**
141      * Property name for the select all action
142      */

143     public static final String JavaDoc SELECT_ALL = "selectall"; //$NON-NLS-1$
144

145     /**
146      * Property name for the undo action
147      */

148     public static final String JavaDoc UNDO = "undo"; //$NON-NLS-1$
149

150     /**
151      * Creates a new cell editor with no control
152      * The cell editor has no cell validator.
153      * @since 2.1
154      */

155     protected CellEditor() {
156     }
157
158     /**
159      * Creates a new cell editor under the given parent control.
160      * The cell editor has no cell validator.
161      *
162      * @param parent the parent control
163      */

164     protected CellEditor(Composite parent) {
165         this(parent, defaultStyle);
166     }
167
168     /**
169      * Creates a new cell editor under the given parent control.
170      * The cell editor has no cell validator.
171      *
172      * @param parent the parent control
173      * @param style the style bits
174      * @since 2.1
175      */

176     protected CellEditor(Composite parent, int style) {
177         this.style = style;
178         create(parent);
179     }
180
181     /**
182      * Activates this cell editor.
183      * <p>
184      * The default implementation of this framework method
185      * does nothing. Subclasses may reimplement.
186      * </p>
187      */

188     public void activate() {
189     }
190
191     /**
192      * Adds a listener to this cell editor.
193      * Has no effect if an identical listener is already registered.
194      *
195      * @param listener a cell editor listener
196      */

197     public void addListener(ICellEditorListener listener) {
198         listeners.add(listener);
199     }
200
201     /**
202      * Adds a property change listener to this cell editor.
203      * Has no effect if an identical property change listener
204      * is already registered.
205      *
206      * @param listener a property change listener
207      */

208     public void addPropertyChangeListener(IPropertyChangeListener listener) {
209         propertyChangeListeners.add(listener);
210     }
211
212     /**
213      * Creates the control for this cell editor under the given parent control.
214      * <p>
215      * This framework method must be implemented by concrete
216      * subclasses.
217      * </p>
218      *
219      * @param parent the parent control
220      * @return the new control, or <code>null</code> if this cell editor has no control
221      */

222     protected abstract Control createControl(Composite parent);
223
224     /**
225      * Creates the control for this cell editor under the given parent control.
226      *
227      * @param parent the parent control
228      * @since 2.1
229      */

230     public void create(Composite parent) {
231         Assert.isTrue(control == null);
232         control = createControl(parent);
233         // See 1GD5CA6: ITPUI:ALL - TaskView.setSelection does not work
234
// Control is created with getVisible()==true by default.
235
// This causes composite.setFocus() to work incorrectly.
236
// The cell editor's control grabs focus instead, even if it is not active.
237
// Make the control invisible here by default.
238
deactivate();
239     }
240
241     /**
242      * Hides this cell editor's control. Does nothing if this
243      * cell editor is not visible.
244      */

245     public void deactivate() {
246         if (control != null && !control.isDisposed()) {
247             control.setVisible(false);
248         }
249     }
250
251     /**
252      * Disposes of this cell editor and frees any associated SWT resources.
253      */

254     public void dispose() {
255         if (control != null && !control.isDisposed()) {
256             control.dispose();
257         }
258         control = null;
259     }
260
261     /**
262      * Returns this cell editor's value.
263      * <p>
264      * This framework method must be implemented by concrete subclasses.
265      * </p>
266      *
267      * @return the value of this cell editor
268      * @see #getValue
269      */

270     protected abstract Object JavaDoc doGetValue();
271
272     /**
273      * Sets the focus to the cell editor's control.
274      * <p>
275      * This framework method must be implemented by concrete subclasses.
276      * </p>
277      *
278      * @see #setFocus
279      */

280     protected abstract void doSetFocus();
281
282     /**
283      * Sets this cell editor's value.
284      * <p>
285      * This framework method must be implemented by concrete subclasses.
286      * </p>
287      *
288      * @param value the value of this cell editor
289      * @see #setValue
290      */

291     protected abstract void doSetValue(Object JavaDoc value);
292
293     /**
294      * Notifies all registered cell editor listeners of an apply event.
295      * Only listeners registered at the time this method is called are notified.
296      *
297      * @see ICellEditorListener#applyEditorValue
298      */

299     protected void fireApplyEditorValue() {
300         Object JavaDoc[] array = listeners.getListeners();
301         for (int i = 0; i < array.length; i++) {
302             final ICellEditorListener l = (ICellEditorListener) array[i];
303             SafeRunnable.run(new SafeRunnable() {
304                 public void run() {
305                     l.applyEditorValue();
306                 }
307             });
308         }
309     }
310
311     /**
312      * Notifies all registered cell editor listeners that editing has been
313      * canceled.
314      *
315      * @see ICellEditorListener#cancelEditor
316      */

317     protected void fireCancelEditor() {
318         Object JavaDoc[] array = listeners.getListeners();
319         for (int i = 0; i < array.length; i++) {
320             final ICellEditorListener l = (ICellEditorListener) array[i];
321             SafeRunnable.run(new SafeRunnable() {
322                 public void run() {
323                     l.cancelEditor();
324                 }
325             });
326         }
327     }
328
329     /**
330      * Notifies all registered cell editor listeners of a value change.
331      *
332      * @param oldValidState the valid state before the end user changed the value
333      * @param newValidState the current valid state
334      * @see ICellEditorListener#editorValueChanged
335      */

336     protected void fireEditorValueChanged(final boolean oldValidState,
337             final boolean newValidState) {
338         Object JavaDoc[] array = listeners.getListeners();
339         for (int i = 0; i < array.length; i++) {
340             final ICellEditorListener l = (ICellEditorListener) array[i];
341             SafeRunnable.run(new SafeRunnable() {
342                 public void run() {
343                     l.editorValueChanged(oldValidState, newValidState);
344                 }
345             });
346         }
347     }
348
349     /**
350      * Notifies all registered property listeners
351      * of an enablement change.
352      *
353      * @param actionId the id indicating what action's enablement has changed.
354      */

355     protected void fireEnablementChanged(final String JavaDoc actionId) {
356         Object JavaDoc[] array = propertyChangeListeners.getListeners();
357         for (int i = 0; i < array.length; i++) {
358             final IPropertyChangeListener l = (IPropertyChangeListener) array[i];
359             SafeRunnable.run(new SafeRunnable() {
360                 public void run() {
361                     l.propertyChange(new PropertyChangeEvent(this, actionId,
362                             null, null));
363                 }
364             });
365         }
366     }
367
368     /**
369      * Sets the style bits for this cell editor.
370      *
371      * @param style the SWT style bits for this cell editor
372      * @since 2.1
373      */

374     public void setStyle(int style) {
375         this.style = style;
376     }
377
378     /**
379      * Returns the style bits for this cell editor.
380      *
381      * @return the style for this cell editor
382      * @since 2.1
383      */

384     public int getStyle() {
385         return style;
386     }
387
388     /**
389      * Returns the control used to implement this cell editor.
390      *
391      * @return the control, or <code>null</code> if this cell editor has no control
392      */

393     public Control getControl() {
394         return control;
395     }
396
397     /**
398      * Returns the current error message for this cell editor.
399      *
400      * @return the error message if the cell editor is in an invalid state,
401      * and <code>null</code> if the cell editor is valid
402      */

403     public String JavaDoc getErrorMessage() {
404         return errorMessage;
405     }
406
407     /**
408      * Returns a layout data object for this cell editor.
409      * This is called each time the cell editor is activated
410      * and controls the layout of the SWT table editor.
411      * <p>
412      * The default implementation of this method sets the
413      * minimum width to the control's preferred width.
414      * Subclasses may extend or reimplement.
415      * </p>
416      *
417      * @return the layout data object
418      */

419     public LayoutData getLayoutData() {
420         LayoutData result = new LayoutData();
421         Control control = getControl();
422         if (control != null) {
423             result.minimumWidth = control.computeSize(SWT.DEFAULT, SWT.DEFAULT,
424                     true).x;
425         }
426         return result;
427     }
428
429     /**
430      * Returns the input validator for this cell editor.
431      *
432      * @return the input validator, or <code>null</code> if none
433      */

434     public ICellEditorValidator getValidator() {
435         return validator;
436     }
437
438     /**
439      * Returns this cell editor's value provided that it has a valid one.
440      *
441      * @return the value of this cell editor, or <code>null</code>
442      * if the cell editor does not contain a valid value
443      */

444     public final Object JavaDoc getValue() {
445         if (!valid) {
446             return null;
447         }
448
449         return doGetValue();
450     }
451
452     /**
453      * Returns whether this cell editor is activated.
454      *
455      * @return <code>true</code> if this cell editor's control is
456      * currently activated, and <code>false</code> if not activated
457      */

458     public boolean isActivated() {
459         // Use the state of the visible style bit (getVisible()) rather than the
460
// window's actual visibility (isVisible()) to get correct handling when
461
// an ancestor control goes invisible, see bug 85331.
462
return control != null && control.getVisible();
463     }
464
465     /**
466      * Returns <code>true</code> if this cell editor is
467      * able to perform the copy action.
468      * <p>
469      * This default implementation always returns
470      * <code>false</code>.
471      * </p>
472      * <p>
473      * Subclasses may override
474      * </p>
475      * @return <code>true</code> if copy is possible,
476      * <code>false</code> otherwise
477      */

478     public boolean isCopyEnabled() {
479         return false;
480     }
481
482     /**
483      * Returns whether the given value is valid for this cell editor.
484      * This cell editor's validator (if any) makes the actual determination.
485      * @param value the value to check for
486      *
487      * @return <code>true</code> if the value is valid, and <code>false</code>
488      * if invalid
489      */

490     protected boolean isCorrect(Object JavaDoc value) {
491         errorMessage = null;
492         if (validator == null) {
493             return true;
494         }
495
496         errorMessage = validator.isValid(value);
497         return (errorMessage == null || errorMessage.equals(""));//$NON-NLS-1$
498
}
499
500     /**
501      * Returns <code>true</code> if this cell editor is
502      * able to perform the cut action.
503      * <p>
504      * This default implementation always returns
505      * <code>false</code>.
506      * </p>
507      * <p>
508      * Subclasses may override
509      * </p>
510      * @return <code>true</code> if cut is possible,
511      * <code>false</code> otherwise
512      */

513     public boolean isCutEnabled() {
514         return false;
515     }
516
517     /**
518      * Returns <code>true</code> if this cell editor is
519      * able to perform the delete action.
520      * <p>
521      * This default implementation always returns
522      * <code>false</code>.
523      * </p>
524      * <p>
525      * Subclasses may override
526      * </p>
527      * @return <code>true</code> if delete is possible,
528      * <code>false</code> otherwise
529      */

530     public boolean isDeleteEnabled() {
531         return false;
532     }
533
534     /**
535      * Returns whether the value of this cell editor has changed since the
536      * last call to <code>setValue</code>.
537      *
538      * @return <code>true</code> if the value has changed, and <code>false</code>
539      * if unchanged
540      */

541     public boolean isDirty() {
542         return dirty;
543     }
544
545     /**
546      * Marks this cell editor as dirty.
547      * @since 2.1
548      */

549     protected void markDirty() {
550         dirty = true;
551     }
552
553     /**
554      * Returns <code>true</code> if this cell editor is
555      * able to perform the find action.
556      * <p>
557      * This default implementation always returns
558      * <code>false</code>.
559      * </p>
560      * <p>
561      * Subclasses may override
562      * </p>
563      * @return <code>true</code> if find is possible,
564      * <code>false</code> otherwise
565      */

566     public boolean isFindEnabled() {
567         return false;
568     }
569
570     /**
571      * Returns <code>true</code> if this cell editor is
572      * able to perform the paste action.
573      * <p>
574      * This default implementation always returns
575      * <code>false</code>.
576      * </p>
577      * <p>
578      * Subclasses may override
579      * </p>
580      * @return <code>true</code> if paste is possible,
581      * <code>false</code> otherwise
582      */

583     public boolean isPasteEnabled() {
584         return false;
585     }
586
587     /**
588      * Returns <code>true</code> if this cell editor is
589      * able to perform the redo action.
590      * <p>
591      * This default implementation always returns
592      * <code>false</code>.
593      * </p>
594      * <p>
595      * Subclasses may override
596      * </p>
597      * @return <code>true</code> if redo is possible,
598      * <code>false</code> otherwise
599      */

600     public boolean isRedoEnabled() {
601         return false;
602     }
603
604     /**
605      * Returns <code>true</code> if this cell editor is
606      * able to perform the select all action.
607      * <p>
608      * This default implementation always returns
609      * <code>false</code>.
610      * </p>
611      * <p>
612      * Subclasses may override
613      * </p>
614      * @return <code>true</code> if select all is possible,
615      * <code>false</code> otherwise
616      */

617     public boolean isSelectAllEnabled() {
618         return false;
619     }
620
621     /**
622      * Returns <code>true</code> if this cell editor is
623      * able to perform the undo action.
624      * <p>
625      * This default implementation always returns
626      * <code>false</code>.
627      * </p>
628      * <p>
629      * Subclasses may override
630      * </p>
631      * @return <code>true</code> if undo is possible,
632      * <code>false</code> otherwise
633      */

634     public boolean isUndoEnabled() {
635         return false;
636     }
637
638     /**
639      * Returns whether this cell editor has a valid value.
640      * The default value is false.
641      *
642      * @return <code>true</code> if the value is valid, and <code>false</code>
643      * if invalid
644      *
645      * @see #setValueValid(boolean)
646      */

647     public boolean isValueValid() {
648         return valid;
649     }
650
651     /**
652      * Processes a key release event that occurred in this cell editor.
653      * <p>
654      * The default implementation of this framework method cancels editing
655      * when the ESC key is pressed. When the RETURN key is pressed the current
656      * value is applied and the cell editor deactivates.
657      * Subclasses should call this method at appropriate times.
658      * Subclasses may also extend or reimplement.
659      * </p>
660      *
661      * @param keyEvent the key event
662      */

663     protected void keyReleaseOccured(KeyEvent keyEvent) {
664         if (keyEvent.character == '\u001b') { // Escape character
665
fireCancelEditor();
666         } else if (keyEvent.character == '\r') { // Return key
667
fireApplyEditorValue();
668             deactivate();
669         }
670     }
671
672     /**
673      * Processes a focus lost event that occurred in this cell editor.
674      * <p>
675      * The default implementation of this framework method applies the current
676      * value and deactivates the cell editor.
677      * Subclasses should call this method at appropriate times.
678      * Subclasses may also extend or reimplement.
679      * </p>
680      */

681     protected void focusLost() {
682         if (isActivated()) {
683             fireApplyEditorValue();
684             deactivate();
685         }
686     }
687
688     /**
689      * Performs the copy action.
690      * This default implementation does nothing.
691      * <p>
692      * Subclasses may override
693      * </p>
694      */

695     public void performCopy() {
696     }
697
698     /**
699      * Performs the cut action.
700      * This default implementation does nothing.
701      * <p>
702      * Subclasses may override
703      * </p>
704      */

705     public void performCut() {
706     }
707
708     /**
709      * Performs the delete action.
710      * This default implementation does nothing.
711      * <p>
712      * Subclasses may override
713      * </p>
714      */

715     public void performDelete() {
716     }
717
718     /**
719      * Performs the find action.
720      * This default implementation does nothing.
721      * <p>
722      * Subclasses may override
723      * </p>
724      */

725     public void performFind() {
726     }
727
728     /**
729      * Performs the paste action.
730      * This default implementation does nothing.
731      * <p>
732      * Subclasses may override
733      * </p>
734      */

735     public void performPaste() {
736     }
737
738     /**
739      * Performs the redo action.
740      * This default implementation does nothing.
741      * <p>
742      * Subclasses may override
743      * </p>
744      */

745     public void performRedo() {
746     }
747
748     /**
749      * Performs the select all action.
750      * This default implementation does nothing.
751      * <p>
752      * Subclasses may override
753      * </p>
754      */

755     public void performSelectAll() {
756     }
757
758     /**
759      * Performs the undo action.
760      * This default implementation does nothing.
761      * <p>
762      * Subclasses may override
763      * </p>
764      */

765     public void performUndo() {
766     }
767
768     /**
769      * Removes the given listener from this cell editor.
770      * Has no affect if an identical listener is not registered.
771      *
772      * @param listener a cell editor listener
773      */

774     public void removeListener(ICellEditorListener listener) {
775         listeners.remove(listener);
776     }
777
778     /**
779      * Removes the given property change listener from this cell editor.
780      * Has no affect if an identical property change listener is not
781      * registered.
782      *
783      * @param listener a property change listener
784      */

785     public void removePropertyChangeListener(IPropertyChangeListener listener) {
786         propertyChangeListeners.remove(listener);
787     }
788
789     /**
790      * Sets or clears the current error message for this cell editor.
791      * <p>
792      * No formatting is done here, the message to be set is expected to be fully formatted
793      * before being passed in.
794      * </p>
795      * @param message the error message, or <code>null</code> to clear
796      */

797     protected void setErrorMessage(String JavaDoc message) {
798         errorMessage = message;
799     }
800
801     /**
802      * Sets the focus to the cell editor's control.
803      */

804     public void setFocus() {
805         doSetFocus();
806     }
807
808     /**
809      * Sets the input validator for this cell editor.
810      *
811      * @param validator the input validator, or <code>null</code> if none
812      */

813     public void setValidator(ICellEditorValidator validator) {
814         this.validator = validator;
815     }
816
817     /**
818      * Sets this cell editor's value.
819      *
820      * @param value the value of this cell editor
821      */

822     public final void setValue(Object JavaDoc value) {
823         valid = isCorrect(value);
824         dirty = false;
825         doSetValue(value);
826     }
827
828     /**
829      * Sets the valid state of this cell editor.
830      * The default value is false.
831      * Subclasses should call this method on construction.
832      *
833      * @param valid <code>true</code> if the current value is valid,
834      * and <code>false</code> if invalid
835      *
836      * @see #isValueValid
837      */

838     protected void setValueValid(boolean valid) {
839         this.valid = valid;
840     }
841
842     /**
843      * The value has changed.
844      * Updates the valid state flag, marks this cell editor as dirty,
845      * and notifies all registered cell editor listeners of a value change.
846      *
847      * @param oldValidState the valid state before the end user changed the value
848      * @param newValidState the current valid state
849      * @see ICellEditorListener#editorValueChanged
850      */

851     protected void valueChanged(boolean oldValidState, boolean newValidState) {
852         valid = newValidState;
853         dirty = true;
854         fireEditorValueChanged(oldValidState, newValidState);
855     }
856     
857     /**
858      * Activate the editor but also inform the editor which event triggered its activation.
859      * <b>The default implementation simply calls {@link #activate()}</b>
860      *
861      * @param activationEvent the editor activation event
862      * @since 3.3
863      */

864     public void activate(ColumnViewerEditorActivationEvent activationEvent) {
865         activate();
866     }
867     
868     /**
869      * This method is for interal use in {@link ColumnViewerEditor} to not break clients
870      * who don't implement the {@link ICellEditorListener} appropiately
871      *
872      * @return <code>true</code> to indicate that a focus listener has to be attached
873      */

874     boolean dependsOnExternalFocusListener() {
875         return true;
876     }
877 }
878
Popular Tags