Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/eclipse/jface/viewers/ContentViewer.java


1   /*******************************************************************************
2    * Copyright (c) 2000, 2003 IBM Corporation and others.
3    * All rights reserved. This program and the accompanying materials 
4    * are made available under the terms of the Common Public License v1.0
5    * which accompanies this distribution, and is available at
6    * http://www.eclipse.org/legal/cpl-v10.html
7    * 
8    * Contributors:
9    *     IBM Corporation - initial API and implementation
10   *******************************************************************************/
11  package org.eclipse.jface.viewers;
12  
13  import org.eclipse.jface.util.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 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   * Creates a content viewer with no input, no content provider, and a
79   * default label provider.
80   */
81  protected ContentViewer() {
82  }
83  /**
84   * Returns the content provider used by this viewer, 
85   * or <code>null</code> if this view does not yet have a content
86   * provider.
87   * <p>
88   * The <code>ContentViewer</code> implementation of this method returns the content
89   * provider recorded is an internal state variable. 
90   * Overriding this method is generally not required; 
91   * however, if overriding in a subclass, 
92   * <code>super.getContentProvider</code> must be invoked.
93   * </p>
94   *
95   * @return the content provider, or <code>null</code> if none
96   */
97  public IContentProvider getContentProvider() {
98    return contentProvider;
99  }
100 /**
101  * The <code>ContentViewer</code> implementation of this <code>IInputProvider</code> 
102  * method returns the current input of this viewer, or <code>null</code>
103  * if none. The viewer's input provides the "model" for the viewer's
104  * content.
105  */
106 public Object getInput() {
107   return input;
108 }
109 /**
110  * Returns the label provider used by this viewer.
111  * <p>
112  * The <code>ContentViewer</code> implementation of this method returns the label
113  * provider recorded in an internal state variable; if none has been
114  * set (with <code>setLabelProvider</code>) a <code>SimpleLabelProvider</code>
115  * will be created, remembered, and returned.
116  * Overriding this method is generally not required; 
117  * however, if overriding in a subclass,
118  * <code>super.getLabelProvider</code> must be invoked.
119  * </p>
120  *
121  * @return a label provider
122  */
123 public IBaseLabelProvider getLabelProvider() {
124   if (labelProvider == null)
125     labelProvider = new LabelProvider();
126   return labelProvider;
127 }
128 /**
129  * Handles a dispose event on this viewer's control.
130  * <p>
131  * The <code>ContentViewer</code> implementation of this method disposes of this
132  * viewer's label provider and content provider (if it has one).
133  * Subclasses should override this method to perform any additional
134  * cleanup of resources; however, overriding methods must invoke
135  * <code>super.handleDispose</code>.
136  * </p>
137  *
138  * @param event a dispose event
139  */
140 protected void handleDispose(DisposeEvent event) {
141   if (contentProvider != null) {
142     contentProvider.inputChanged(this, getInput(), null);
143     contentProvider.dispose();
144     contentProvider = null;
145   }
146   if (labelProvider != null) {
147     labelProvider.removeListener(labelProviderListener);
148     labelProvider.dispose();
149     labelProvider = null;
150   }
151 }
152 /**
153  * Handles a label provider changed event.
154  * <p>
155  * The <code>ContentViewer</code> implementation of this method calls <code>labelProviderChanged()</code>
156  * to cause a complete refresh of the viewer.
157  * Subclasses may reimplement or extend.
158  * </p>
159  */
160 protected void handleLabelProviderChanged(LabelProviderChangedEvent event) {
161   labelProviderChanged();
162 }
163 /**
164  * Adds event listener hooks to the given control.
165  * <p>
166  * All subclasses must call this method when their control is
167  * first established.
168  * </p> 
169  * <p>
170  * The <code>ContentViewer</code> implementation of this method hooks 
171  * dispose events for the given control.
172  * Subclasses may override if they need to add other control hooks;
173  * however, <code>super.hookControl</code> must be invoked.
174  * </p>
175  *
176  * @param control the control
177  */
178 protected void hookControl(Control control) {
179   control.addDisposeListener(new DisposeListener() {
180     public void widgetDisposed(DisposeEvent event) {
181       handleDispose(event);
182     }
183   });
184 }
185 /**
186  * Notifies that the label provider has changed.
187  * <p>
188  * The <code>ContentViewer</code> implementation of this method calls <code>refresh()</code>.
189  * Subclasses may reimplement or extend.
190  * </p>
191  */
192 protected void labelProviderChanged() {
193   refresh();
194 }
195 /**
196  * Sets the content provider used by this viewer.
197  * <p>
198  * The <code>ContentViewer</code> implementation of this method records the 
199  * content provider in an internal state variable.
200  * Overriding this method is generally not required; 
201  * however, if overriding in a subclass,
202  * <code>super.setContentProvider</code> must be invoked.
203  * </p>
204  *
205  * @param contentProvider the content provider
206  * @see #getContentProvider
207  */
208 public void setContentProvider(IContentProvider contentProvider) {
209   Assert.isNotNull(contentProvider);
210   IContentProvider oldContentProvider = this.contentProvider;
211   this.contentProvider = contentProvider;
212   if (oldContentProvider != null) {
213     Object currentInput = getInput();
214     oldContentProvider.inputChanged(this, currentInput, null);
215     oldContentProvider.dispose();
216     contentProvider.inputChanged(this, null, currentInput);
217     refresh();
218   }
219 }
220 /**
221  * The <code>ContentViewer</code> implementation of this <code>Viewer</code>
222  * method invokes <code>inputChanged</code> on the content provider and then the
223  * <code>inputChanged</code> hook method. This method fails if this viewer does
224  * not have a content provider. Subclassers are advised to override 
225  * <code>inputChanged</code> rather than this method, but may extend this method
226  * if required.
227  */
228 public void setInput(Object input) {
229   Assert.isTrue(
230     getContentProvider() != null, 
231     "ContentViewer must have a content provider when input is set."); //$NON-NLS-1$
232 
233   Object oldInput = getInput();
234   contentProvider.inputChanged(this, oldInput, input);
235   this.input = input;
236 
237   // call input hook
238   inputChanged(this.input, oldInput);
239 }
240 /**
241  * Sets the label provider for this viewer.
242  * <p>
243  * The <code>ContentViewer</code> implementation of this method ensures that the
244  * given label provider is connected to this viewer and the
245  * former label provider is disconnected from this viewer.
246  * Overriding this method is generally not required; 
247  * however, if overriding in a subclass,
248  * <code>super.setLabelProvider</code> must be invoked.
249  * </p>
250  *
251  * @param labelProvider the label provider, or <code>null</code> if none
252  */
253 public void setLabelProvider(IBaseLabelProvider labelProvider) {
254   IBaseLabelProvider oldProvider = this.labelProvider;
255   // If it hasn't changed, do nothing.
256   // This also ensures that the provider is not disposed
257   // if set a second time.
258   if (labelProvider == oldProvider) {
259     return;
260   }
261   if (oldProvider != null) {
262     oldProvider.removeListener(this.labelProviderListener);
263   }
264   this.labelProvider = labelProvider;
265   if (labelProvider != null) {
266     labelProvider.addListener(this.labelProviderListener);
267   }
268   refresh();
269 
270   // Dispose old provider after refresh, so that items never refer to stale images.
271   if (oldProvider != null) {
272     oldProvider.dispose();
273   }
274 }
275 }