KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 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.Assert;
14 import org.eclipse.swt.events.DisposeEvent;
15 import org.eclipse.swt.events.DisposeListener;
16 import org.eclipse.swt.widgets.Control;
17
18 /**
19  * A content viewer is a model-based adapter on a widget which accesses its
20  * model by means of a content provider and a label provider.
21  * <p>
22  * A viewer's model consists of elements, represented by objects.
23  * A viewer defines and implements generic infrastructure for handling model
24  * input, updates, and selections in terms of elements.
25  * Input is obtained by querying an <code>IContentProvider</code> which returns
26  * elements. The elements themselves are not displayed directly. They are
27  * mapped to labels, containing text and/or an image, using the viewer's
28  * <code>ILabelProvider</code>.
29  * </p>
30  * <p>
31  * Implementing a concrete content viewer typically involves the following steps:
32  * <ul>
33  * <li>
34  * create SWT controls for viewer (in constructor) (optional)
35  * </li>
36  * <li>
37  * initialize SWT controls from input (inputChanged)
38  * </li>
39  * <li>
40  * define viewer-specific update methods
41  * </li>
42  * <li>
43  * support selections (<code>setSelection</code>, <code>getSelection</code>)
44  * </ul>
45  * </p>
46  */

47 public abstract class ContentViewer extends Viewer {
48
49     /**
50      * This viewer's content provider, or <code>null</code> if none.
51      */

52     private IContentProvider contentProvider = null;
53
54     /**
55      * This viewer's input, or <code>null</code> if none.
56      * The viewer's input provides the "model" for the viewer's content.
57      */

58     private Object JavaDoc input = null;
59
60     /**
61      * This viewer's label provider. Initially <code>null</code>, but
62      * lazily initialized (to a <code>SimpleLabelProvider</code>).
63      */

64     private IBaseLabelProvider labelProvider = null;
65
66     /**
67      * This viewer's label provider listener.
68      * Note: Having a viewer register a label provider listener with
69      * a label provider avoids having to define public methods
70      * for internal events.
71      */

72     private final ILabelProviderListener labelProviderListener = new ILabelProviderListener() {
73         public void labelProviderChanged(LabelProviderChangedEvent event) {
74             ContentViewer.this.handleLabelProviderChanged(event);
75         }
76     };
77
78     /**
79      * Creates a content viewer with no input, no content provider, and a
80      * default label provider.
81      */

82     protected ContentViewer() {
83     }
84
85     /**
86      * Returns the content provider used by this viewer,
87      * or <code>null</code> if this view does not yet have a content
88      * provider.
89      * <p>
90      * The <code>ContentViewer</code> implementation of this method returns the content
91      * provider recorded is an internal state variable.
92      * Overriding this method is generally not required;
93      * however, if overriding in a subclass,
94      * <code>super.getContentProvider</code> must be invoked.
95      * </p>
96      *
97      * @return the content provider, or <code>null</code> if none
98      */

99     public IContentProvider getContentProvider() {
100         return contentProvider;
101     }
102
103     /**
104      * The <code>ContentViewer</code> implementation of this <code>IInputProvider</code>
105      * method returns the current input of this viewer, or <code>null</code>
106      * if none. The viewer's input provides the "model" for the viewer's
107      * content.
108      */

109     public Object JavaDoc getInput() {
110         return input;
111     }
112
113     /**
114      * Returns the label provider used by this viewer.
115      * <p>
116      * The <code>ContentViewer</code> implementation of this method returns the label
117      * provider recorded in an internal state variable; if none has been
118      * set (with <code>setLabelProvider</code>) a <code>SimpleLabelProvider</code>
119      * will be created, remembered, and returned.
120      * Overriding this method is generally not required;
121      * however, if overriding in a subclass,
122      * <code>super.getLabelProvider</code> must be invoked.
123      * </p>
124      *
125      * @return a label provider
126      */

127     public IBaseLabelProvider getLabelProvider() {
128         if (labelProvider == null) {
129             labelProvider = new LabelProvider();
130         }
131         return labelProvider;
132     }
133
134     /**
135      * Handles a dispose event on this viewer's control.
136      * <p>
137      * The <code>ContentViewer</code> implementation of this method disposes of this
138      * viewer's label provider and content provider (if it has one).
139      * Subclasses should override this method to perform any additional
140      * cleanup of resources; however, overriding methods must invoke
141      * <code>super.handleDispose</code>.
142      * </p>
143      *
144      * @param event a dispose event
145      */

146     protected void handleDispose(DisposeEvent event) {
147         if (contentProvider != null) {
148             contentProvider.inputChanged(this, getInput(), null);
149             contentProvider.dispose();
150             contentProvider = null;
151         }
152         if (labelProvider != null) {
153             labelProvider.removeListener(labelProviderListener);
154             labelProvider.dispose();
155             labelProvider = null;
156         }
157         input = null;
158     }
159
160     /**
161      * Handles a label provider changed event.
162      * <p>
163      * The <code>ContentViewer</code> implementation of this method calls <code>labelProviderChanged()</code>
164      * to cause a complete refresh of the viewer.
165      * Subclasses may reimplement or extend.
166      * </p>
167      * @param event the change event
168      */

169     protected void handleLabelProviderChanged(LabelProviderChangedEvent event) {
170         labelProviderChanged();
171     }
172
173     /**
174      * Adds event listener hooks to the given control.
175      * <p>
176      * All subclasses must call this method when their control is
177      * first established.
178      * </p>
179      * <p>
180      * The <code>ContentViewer</code> implementation of this method hooks
181      * dispose events for the given control.
182      * Subclasses may override if they need to add other control hooks;
183      * however, <code>super.hookControl</code> must be invoked.
184      * </p>
185      *
186      * @param control the control
187      */

188     protected void hookControl(Control control) {
189         control.addDisposeListener(new DisposeListener() {
190             public void widgetDisposed(DisposeEvent event) {
191                 handleDispose(event);
192             }
193         });
194     }
195
196     /**
197      * Notifies that the label provider has changed.
198      * <p>
199      * The <code>ContentViewer</code> implementation of this method calls <code>refresh()</code>.
200      * Subclasses may reimplement or extend.
201      * </p>
202      */

203     protected void labelProviderChanged() {
204         refresh();
205     }
206
207     /**
208      * Sets the content provider used by this viewer.
209      * <p>
210      * The <code>ContentViewer</code> implementation of this method records the
211      * content provider in an internal state variable.
212      * Overriding this method is generally not required;
213      * however, if overriding in a subclass,
214      * <code>super.setContentProvider</code> must be invoked.
215      * </p>
216      *
217      * @param contentProvider the content provider
218      * @see #getContentProvider
219      */

220     public void setContentProvider(IContentProvider contentProvider) {
221         Assert.isNotNull(contentProvider);
222         IContentProvider oldContentProvider = this.contentProvider;
223         this.contentProvider = contentProvider;
224         if (oldContentProvider != null) {
225             Object JavaDoc currentInput = getInput();
226             oldContentProvider.inputChanged(this, currentInput, null);
227             oldContentProvider.dispose();
228             contentProvider.inputChanged(this, null, currentInput);
229             refresh();
230         }
231     }
232
233     /**
234      * The <code>ContentViewer</code> implementation of this <code>Viewer</code>
235      * method invokes <code>inputChanged</code> on the content provider and then the
236      * <code>inputChanged</code> hook method. This method fails if this viewer does
237      * not have a content provider. Subclassers are advised to override
238      * <code>inputChanged</code> rather than this method, but may extend this method
239      * if required.
240      */

241     public void setInput(Object JavaDoc input) {
242         Assert
243                 .isTrue(getContentProvider() != null,
244                         "ContentViewer must have a content provider when input is set."); //$NON-NLS-1$
245

246         Object JavaDoc oldInput = getInput();
247         contentProvider.inputChanged(this, oldInput, input);
248         this.input = input;
249
250         // call input hook
251
inputChanged(this.input, oldInput);
252     }
253
254     /**
255      * Sets the label provider for this viewer.
256      * <p>
257      * The <code>ContentViewer</code> implementation of this method ensures that the
258      * given label provider is connected to this viewer and the
259      * former label provider is disconnected from this viewer.
260      * Overriding this method is generally not required;
261      * however, if overriding in a subclass,
262      * <code>super.setLabelProvider</code> must be invoked.
263      * </p>
264      *
265      * @param labelProvider the label provider, or <code>null</code> if none
266      */

267     public void setLabelProvider(IBaseLabelProvider labelProvider) {
268         IBaseLabelProvider oldProvider = this.labelProvider;
269         // If it hasn't changed, do nothing.
270
// This also ensures that the provider is not disposed
271
// if set a second time.
272
if (labelProvider == oldProvider) {
273             return;
274         }
275         if (oldProvider != null) {
276             oldProvider.removeListener(this.labelProviderListener);
277         }
278         this.labelProvider = labelProvider;
279         if (labelProvider != null) {
280             labelProvider.addListener(this.labelProviderListener);
281         }
282         refresh();
283
284         // Dispose old provider after refresh, so that items never refer to stale images.
285
if (oldProvider != null) {
286             oldProvider.dispose();
287         }
288     }
289 }
290
Popular Tags