KickJava   Java API By Example, From Geeks To Geeks.

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


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 package org.eclipse.jface.viewers;
12
13 import org.eclipse.core.runtime.ListenerList;
14 import org.eclipse.core.runtime.Assert;
15 import org.eclipse.jface.util.SafeRunnable;
16 import org.eclipse.swt.events.HelpEvent;
17 import org.eclipse.swt.events.HelpListener;
18 import org.eclipse.swt.widgets.Control;
19 import org.eclipse.swt.widgets.Item;
20
21 /**
22  * A viewer is a model-based adapter on a widget.
23  * <p>
24  * A viewer can be created as an adapter on a pre-existing control (e.g.,
25  * creating a <code>ListViewer</code> on an existing <code>List</code> control).
26  * All viewers also provide a convenience constructor for creating the control.
27  * </p>
28  * <p>
29  * Implementing a concrete viewer typically involves the following steps:
30  * <ul>
31  * <li>
32  * create SWT controls for viewer (in constructor) (optional)
33  * </li>
34  * <li>
35  * initialize SWT controls from input (inputChanged)
36  * </li>
37  * <li>
38  * define viewer-specific update methods
39  * </li>
40  * <li>
41  * support selections (<code>setSelection</code>, <code>getSelection</code>)
42  * </li>
43  * </ul>
44  * </p>
45  */

46 public abstract class Viewer implements IInputSelectionProvider {
47
48     /**
49      * List of selection change listeners (element type: <code>ISelectionChangedListener</code>).
50      *
51      * @see #fireSelectionChanged
52      */

53     private ListenerList selectionChangedListeners = new ListenerList();
54
55     /**
56      * List of help request listeners (element type: <code>org.eclipse.swt.events.HelpListener</code>).
57      * Help request listeners.
58      *
59      * @see #handleHelpRequest
60      */

61     private ListenerList helpListeners = new ListenerList();
62
63     /**
64      * The names of this viewer's properties.
65      * <code>null</code> if this viewer has no properties.
66      *
67      * @see #setData
68      */

69     private String JavaDoc[] keys;
70
71     /**
72      * The values of this viewer's properties.
73      * <code>null</code> if this viewer has no properties.
74      * This array parallels the value of the <code>keys</code> field.
75      *
76      * @see #setData
77      */

78     private Object JavaDoc[] values;
79
80     /**
81      * Remembers whether we've hooked the help listener on the control or not.
82      */

83     private boolean helpHooked = false;
84
85     /**
86      * Help listener for the control, created lazily when client's first help listener is added.
87      */

88     private HelpListener helpListener = null;
89
90     /**
91      * Unique key for associating element data with widgets.
92      * @see org.eclipse.swt.widgets.Widget#setData(String, Object)
93      */

94     protected static final String JavaDoc WIDGET_DATA_KEY = "org.eclipse.jface.viewers.WIDGET_DATA";//$NON-NLS-1$
95

96     /**
97      * Creates a new viewer.
98      */

99     protected Viewer() {
100     }
101
102     /**
103      * Adds a listener for help requests in this viewer.
104      * Has no effect if an identical listener is already registered.
105      *
106      * @param listener a help listener
107      */

108     public void addHelpListener(HelpListener listener) {
109         helpListeners.add(listener);
110         if (!helpHooked) {
111             Control control = getControl();
112             if (control != null && !control.isDisposed()) {
113                 if (this.helpListener == null) {
114                     this.helpListener = new HelpListener() {
115                         public void helpRequested(HelpEvent event) {
116                             handleHelpRequest(event);
117                         }
118                     };
119                 }
120                 control.addHelpListener(this.helpListener);
121                 helpHooked = true;
122             }
123         }
124     }
125
126     /* (non-Javadoc)
127      * Method declared on ISelectionProvider.
128      */

129     public void addSelectionChangedListener(ISelectionChangedListener listener) {
130         selectionChangedListeners.add(listener);
131     }
132
133     /**
134      * Notifies any help listeners that help has been requested.
135      * Only listeners registered at the time this method is called are notified.
136      *
137      * @param event a help event
138      *
139      * @see HelpListener#helpRequested(org.eclipse.swt.events.HelpEvent)
140      */

141     protected void fireHelpRequested(HelpEvent event) {
142         Object JavaDoc[] listeners = helpListeners.getListeners();
143         for (int i = 0; i < listeners.length; ++i) {
144             ((HelpListener) listeners[i]).helpRequested(event);
145         }
146     }
147
148     /**
149      * Notifies any selection changed listeners that the viewer's selection has changed.
150      * Only listeners registered at the time this method is called are notified.
151      *
152      * @param event a selection changed event
153      *
154      * @see ISelectionChangedListener#selectionChanged
155      */

156     protected void fireSelectionChanged(final SelectionChangedEvent event) {
157         Object JavaDoc[] listeners = selectionChangedListeners.getListeners();
158         for (int i = 0; i < listeners.length; ++i) {
159             final ISelectionChangedListener l = (ISelectionChangedListener) listeners[i];
160             SafeRunnable.run(new SafeRunnable() {
161                 public void run() {
162                     l.selectionChanged(event);
163                 }
164             });
165         }
166     }
167
168     /**
169      * Returns the primary control associated with this viewer.
170      *
171      * @return the SWT control which displays this viewer's content
172      */

173     public abstract Control getControl();
174
175     /**
176      * Returns the value of the property with the given name,
177      * or <code>null</code> if the property is not found.
178      * <p>
179      * The default implementation performs a (linear) search of
180      * an internal table. Overriding this method is generally not
181      * required if the number of different keys is small. If a more
182      * efficient representation of a viewer's properties is required,
183      * override both <code>getData</code> and <code>setData</code>.
184      * </p>
185      *
186      * @param key the property name
187      * @return the property value, or <code>null</code> if
188      * the property is not found
189      */

190     public Object JavaDoc getData(String JavaDoc key) {
191         Assert.isNotNull(key);
192         if (keys == null) {
193             return null;
194         }
195         for (int i = 0; i < keys.length; i++) {
196             if (keys[i].equals(key)) {
197                 return values[i];
198             }
199         }
200         return null;
201     }
202
203     /* (non-Javadoc)
204      * Copy-down of method declared on <code>IInputProvider</code>.
205      */

206     public abstract Object JavaDoc getInput();
207
208     /* (non-Javadoc)
209      * Copy-down of method declared on <code>ISelectionProvider</code>.
210      */

211     public abstract ISelection getSelection();
212
213     /**
214      * Handles a help request from the underlying SWT control.
215      * The default behavior is to fire a help request,
216      * with the event's data modified to hold this viewer.
217      * @param event the event
218      *
219      */

220     protected void handleHelpRequest(HelpEvent event) {
221         Object JavaDoc oldData = event.data;
222         event.data = this;
223         fireHelpRequested(event);
224         event.data = oldData;
225     }
226
227     /**
228      * Internal hook method called when the input to this viewer is
229      * initially set or subsequently changed.
230      * <p>
231      * The default implementation does nothing. Subclassers may override
232      * this method to do something when a viewer's input is set.
233      * A typical use is populate the viewer.
234      * </p>
235      *
236      * @param input the new input of this viewer, or <code>null</code> if none
237      * @param oldInput the old input element or <code>null</code> if there
238      * was previously no input
239      */

240     protected void inputChanged(Object JavaDoc input, Object JavaDoc oldInput) {
241     }
242
243     /**
244      * Refreshes this viewer completely with information freshly obtained from this
245      * viewer's model.
246      */

247     public abstract void refresh();
248
249     /**
250      * Removes the given help listener from this viewer.
251      * Has no affect if an identical listener is not registered.
252      *
253      * @param listener a help listener
254      */

255     public void removeHelpListener(HelpListener listener) {
256         helpListeners.remove(listener);
257         if (helpListeners.size() == 0) {
258             Control control = getControl();
259             if (control != null && !control.isDisposed()) {
260                 control.removeHelpListener(this.helpListener);
261                 helpHooked = false;
262             }
263         }
264     }
265
266     /* (non-Javadoc)
267      * Method declared on ISelectionProvider.
268      */

269     public void removeSelectionChangedListener(
270             ISelectionChangedListener listener) {
271         selectionChangedListeners.remove(listener);
272     }
273
274     /**
275      * Scrolls the viewer's control down by one item from the given
276      * display-relative coordinates. Returns the newly revealed Item,
277      * or <code>null</code> if no scrolling occurred or if the viewer
278      * doesn't represent an item-based widget.
279      *
280      * @param x horizontal coordinate
281      * @param y vertical coordinate
282      * @return the item scrolled down to
283      */

284     public Item scrollDown(int x, int y) {
285         return null;
286     }
287
288     /**
289      * Scrolls the viewer's control up by one item from the given
290      * display-relative coordinates. Returns the newly revealed Item,
291      * or <code>null</code> if no scrolling occurred or if the viewer
292      * doesn't represent an item-based widget.
293      *
294      * @param x horizontal coordinate
295      * @param y vertical coordinate
296      * @return the item scrolled up to
297      */

298     public Item scrollUp(int x, int y) {
299         return null;
300     }
301
302     /**
303      * Sets the value of the property with the given name to the
304      * given value, or to <code>null</code> if the property is to be
305      * removed. If this viewer has such a property, its value is
306      * replaced; otherwise a new property is added.
307      * <p>
308      * The default implementation records properties in an internal
309      * table which is searched linearly. Overriding this method is generally not
310      * required if the number of different keys is small. If a more
311      * efficient representation of a viewer's properties is required,
312      * override both <code>getData</code> and <code>setData</code>.
313      * </p>
314      *
315      * @param key the property name
316      * @param value the property value, or <code>null</code> if
317      * the property is not found
318      */

319     public void setData(String JavaDoc key, Object JavaDoc value) {
320         Assert.isNotNull(key);
321         /* Remove the key/value pair */
322         if (value == null) {
323             if (keys == null) {
324                 return;
325             }
326             int index = 0;
327             while (index < keys.length && !keys[index].equals(key)) {
328                 index++;
329             }
330             if (index == keys.length) {
331                 return;
332             }
333             if (keys.length == 1) {
334                 keys = null;
335                 values = null;
336             } else {
337                 String JavaDoc[] newKeys = new String JavaDoc[keys.length - 1];
338                 Object JavaDoc[] newValues = new Object JavaDoc[values.length - 1];
339                 System.arraycopy(keys, 0, newKeys, 0, index);
340                 System.arraycopy(keys, index + 1, newKeys, index,
341                         newKeys.length - index);
342                 System.arraycopy(values, 0, newValues, 0, index);
343                 System.arraycopy(values, index + 1, newValues, index,
344                         newValues.length - index);
345                 keys = newKeys;
346                 values = newValues;
347             }
348             return;
349         }
350
351         /* Add the key/value pair */
352         if (keys == null) {
353             keys = new String JavaDoc[] { key };
354             values = new Object JavaDoc[] { value };
355             return;
356         }
357         for (int i = 0; i < keys.length; i++) {
358             if (keys[i].equals(key)) {
359                 values[i] = value;
360                 return;
361             }
362         }
363         String JavaDoc[] newKeys = new String JavaDoc[keys.length + 1];
364         Object JavaDoc[] newValues = new Object JavaDoc[values.length + 1];
365         System.arraycopy(keys, 0, newKeys, 0, keys.length);
366         System.arraycopy(values, 0, newValues, 0, values.length);
367         newKeys[keys.length] = key;
368         newValues[values.length] = value;
369         keys = newKeys;
370         values = newValues;
371     }
372
373     /**
374      * Sets or clears the input for this viewer.
375      *
376      * @param input the input of this viewer, or <code>null</code> if none
377      */

378     public abstract void setInput(Object JavaDoc input);
379
380     /**
381      * The viewer implementation of this <code>ISelectionProvider</code>
382      * method make the new selection for this viewer without making it visible.
383      * <p>
384      * This method is equivalent to <code>setSelection(selection,false)</code>.
385      * </p>
386      * <p>
387      * Note that some implementations may not be able to set the selection
388      * without also revealing it, for example (as of 3.3) TreeViewer.
389      * </p>
390      */

391     public void setSelection(ISelection selection) {
392         setSelection(selection, false);
393     }
394
395     /**
396      * Sets a new selection for this viewer and optionally makes it visible.
397      * <p>
398      * Subclasses must implement this method.
399      * </p>
400      *
401      * @param selection the new selection
402      * @param reveal <code>true</code> if the selection is to be made
403      * visible, and <code>false</code> otherwise
404      */

405     public abstract void setSelection(ISelection selection, boolean reveal);
406 }
407
Popular Tags