1 /*******************************************************************************
2  * Copyright (c) 2003, 2015 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  * IBM Corporation - initial API and implementation
13  * Patrik Suzzi <psuzzi@gmail.com> - Bug 501590
14  *******************************************************************************/
15 package org.eclipse.ui.navigator;
16 
17 import java.util.Set;
18 
19 import org.eclipse.jface.viewers.IContentProvider;
20 import org.eclipse.jface.viewers.ILabelProvider;
21 import org.eclipse.jface.viewers.IStructuredContentProvider;
22 import org.eclipse.jface.viewers.ITreeContentProvider;
23 import org.eclipse.jface.viewers.ViewerSorter;
24 import org.eclipse.ui.IMemento;
25 import org.eclipse.ui.ISaveablesSource;
26 
27 /**
28  *
29  * Manages content extensions for extensible viewers and provides reusable
30  * services for filters, sorting, the activation of content extensions, and DND.
31  * The service can locate the appropriate providers (for contents or labels) for
32  * an element and provide a ready-to-go {@link ITreeContentProvider} and
33  * {@link ILabelProvider} for viewers that wish to take advantage of the
34  * <b>org.eclipse.ui.navigator.navigatorContent</b> extensions defined for a
35  * particular <i>viewerId</i>.
36  *
37  * <p>
38  * Clients can get the instance of this associated with the
39  * {@link CommonNavigator} using
40  * {@link CommonNavigator#getNavigatorContentService()}.
41  * </p>
42  *
43  * <p>
44  * Clients may contribute logical extensions using
45  * <b>org.eclipse.ui.navigator.navigatorContent</b>. Each extension has three
46  * states which determine whether the extension is used by the content service:
47  * </p>
48  * <ul>
49  * <li><i>visible</i>: If a content extension id matches a
50  * <b>viewerContentBinding</b> for the <i>viewerId</i> of this content service,
51  * then the extension is <i>visible</i>. Visible extensions may only be
52  * configured through <b>viewerContentBinding</b>s.</li>
53  *
54  * <li><i>active</i>: The active state may be set to a default using the
55  * <i>activeByDefault</i> attribute of <b>navigatorContent</b>. Users may toggle
56  * the <i>active</i> state through the "Filters and Customization" dialog.
57  * Clients may also configure the active extensions using
58  * {@link INavigatorActivationService#activateExtensions(String[], boolean)} or
59  * {@link INavigatorActivationService#deactivateExtensions(String[], boolean)}
60  * from the {@link #getActivationService() Activation Service}</li>
61  *
62  * <li><i>enabled</i>: An extension is <i>enabled</i> for an element if the
63  * extension contributed that element or if the element is described in the
64  * <i>triggerPoints</i> element of the <b>navigatorContent</b> extension. The
65  * findXXX() methods search for <i>enabled</i> extensions.</li>
66  * </ul>
67  * <p>
68  * A new instance of the content service should be created for each viewer.
69  * Clients should use {@link #createCommonContentProvider()} and
70  * {@link #createCommonLabelProvider()} for the viewer. Each content service
71  * tracks the viewer it is attached to. Clients may create the content service
72  * with a viewer using
73  * ({@link NavigatorContentServiceFactory#createContentService(String)}).
74  * Alternatively, when the content provider is created and set on a viewer,
75  * {@link IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, Object, Object)}
76  * will be called and the content provider will update the viewer used by its
77  * backing content service. Therefore, only each content service has exactly one
78  * content provider and one label provider.
79  * </p>
80  * <p>
81  * Extensions may also coordinate their behavior through a
82  * {@link IExtensionStateModel state model}. The state model holds properties
83  * and supports property change listeners. Actions can toggle the setting of
84  * properties and the corresponding content/label providers will respond to
85  * property change event. Each <b>navigatorContent</b> extension has its own
86  * contained state model keyed off of the content extension id.
87  * </p>
88  * <p>
89  * Clients may respond when content extensions are loaded by attaching a
90  * {@link INavigatorContentServiceListener} to the content service.
91  * </p>
92  * <p>
93  * Some extensions may provide content or label providers which implement
94  * {@link IMemento}. Clients must call {@link #restoreState(IMemento)} and
95  * {@link #saveState(IMemento)} at the appropriate times for these extensions to
96  * prepare themselves with the memento.
97  * </p>
98  *
99  * @since 3.2
100  * @noimplement This interface is not intended to be implemented by clients.
101  * @noextend This interface is not intended to be extended by clients.
102  *
103  */
104 public interface INavigatorContentService {
105 
106 	/**
107 	 * Create a Content Provider which will use an enhanced delegation model to
108 	 * locate extension content providers using this content service for each
109 	 * element in the tree.
110 	 *
111 	 * <p>
112 	 * The content provider returned will populate the root of the viewer in one
113 	 * of two ways.
114 	 * <p>
115 	 * In the first approach, the content provider will seek out content
116 	 * extensions which are bound using a <b>viewerContentBinding</b>. If any
117 	 * of the found <b>viewerContentBindings</b> declare the <i>isRoot</i>
118 	 * attribute on as true, then that set of extensions will be consulted for
119 	 * the root elements of the tree. The input of the viewer will be supplied
120 	 * to each of their {@link IStructuredContentProvider#getElements(Object)}
121 	 * methods and aggregate the results for the root of the viewer.
122 	 * </p>
123 	 * <p>
124 	 * In the second approach, if no <b>viewerContentBindings</b> declare
125 	 * <i>isRoot</i> as true, then all matching extensions are consulted based
126 	 * on their <b>triggerPoints</b> expression in the <b>navigatorContent</b>
127 	 * extension. Any matching extensions are then consulted via their
128 	 * {@link IStructuredContentProvider#getElements(Object)} methods and the
129 	 * results are aggregated into the root.
130 	 * </p>
131 	 * <p>
132 	 * After the root is populated, the children of each root element are
133 	 * determined by consulting the source extension and all extension which
134 	 * describe the element in their <b>triggerPoints</b> expression.
135 	 * </p>
136 	 * <p>
137 	 * If clients wish to use a viewer other than the CommonViewer, then they
138 	 * are responsible for creating the content provider, and setting it on
139 	 * their viewer.
140 	 * </p>
141 	 *
142 	 * @return An enhanced content provider that will use this content service
143 	 *         to drive the viewer.
144 	 */
createCommonContentProvider()145 	ITreeContentProvider createCommonContentProvider();
146 
147 	/**
148 	 * Create a Label Provider which will use an enhanced delegation model to
149 	 * locate extension label providers using this content service for each
150 	 * element in the tree.
151 	 *
152 	 * <p>
153 	 * The label of each element is determined by consulting the source of the
154 	 * element. If the source chooses to return null, then other extensions
155 	 * which declare the element in their <b>triggerPoints</b> extension are
156 	 * consulted. The first non-null value is used (including the empty label).
157 	 * </p>
158 	 *
159 	 * <p>
160 	 * If clients wish to use a viewer other than the CommonViewer, then they
161 	 * are responsible for creating the label provider, and setting it on their
162 	 * viewer.
163 	 * </p>
164 	 *
165 	 * @return An enhanced label provider that will use this content service to
166 	 *         drive labels in the viewer.
167 	 */
createCommonLabelProvider()168 	ILabelProvider createCommonLabelProvider();
169 
170 	/**
171 	 *
172 	 * @return The description provider for this content service.
173 	 */
createCommonDescriptionProvider()174 	IDescriptionProvider createCommonDescriptionProvider();
175 
176 	/**
177 	 * The state model stores properties associated with the extension. Each
178 	 * content extension has its own contained state model. Components of the
179 	 * extension (content provider, label provider, action providers, etc) may
180 	 * attach themselves as listeners to the model ({@link IExtensionStateModel#addPropertyChangeListener(org.eclipse.jface.util.IPropertyChangeListener)})
181 	 * and respond to changes to the values of the properties.
182 	 *
183 	 * @param anExtensionId
184 	 *            The extension id defined by a <b>navigatorContent</b>
185 	 *            extension.
186 	 * @return The state model for the given extension id.
187 	 */
findStateModel(String anExtensionId)188 	IExtensionStateModel findStateModel(String anExtensionId);
189 
190 	/**
191 	 * The viewer id is used to locate matching <b>viewerContentBindings</b>.
192 	 * In general, this would be the id of the view defined by a
193 	 * <b>org.eclipse.ui.views</b> extension. However, there is no formal
194 	 * requirement that this is the case.
195 	 *
196 	 * @return The viewerId used to create this content service.
197 	 */
getViewerId()198 	String getViewerId();
199 
200 	/**
201 	 * The viewer descriptor provides some basic information about the abstract
202 	 * viewer that uses this content service.
203 	 *
204 	 * @return The viewer descriptor for this content service.
205 	 * @see INavigatorViewerDescriptor
206 	 */
getViewerDescriptor()207 	INavigatorViewerDescriptor getViewerDescriptor();
208 
209 	/**
210 	 * See <a href="INavigatorContentService.html#active">above</a> for the
211 	 * definition of <i>active</i>.
212 	 *
213 	 * @param anExtensionId
214 	 *            The unqiue identifier from a content extension.
215 	 * @return True if and only if the given extension id is <i>active</i> for
216 	 *         this content service.
217 	 * @see INavigatorContentService For more information on what <i>active</i>
218 	 *      means.
219 	 *
220 	 */
isActive(String anExtensionId)221 	boolean isActive(String anExtensionId);
222 
223 	/**
224 	 * See <a href="INavigatorContentService.html#visible">above</a> for the
225 	 * definition of <i>visible</i>.
226 	 *
227 	 * @param anExtensionId
228 	 *            The unqiue identifier from a content extension.
229 	 * @return True if and only if the given extension id is <i>visible</i> to
230 	 *         this content service.
231 	 * @see INavigatorContentService For more information on what <i>visible</i>
232 	 *      means.
233 	 */
isVisible(String anExtensionId)234 	boolean isVisible(String anExtensionId);
235 
236 	/**
237 	 * Return the set of <i>visible</i> extension ids for this content service,
238 	 * which includes those that are bound through <b>viewerContentBinding</b>s
239 	 * and those that are bound through
240 	 * {@link #bindExtensions(String[], boolean)}.
241 	 *
242 	 * @return The set of <i>visible</i> extension ids for this content service
243 	 */
getVisibleExtensionIds()244 	String[] getVisibleExtensionIds();
245 
246 	/**
247 	 * Return the set of <i>visible</i> content descriptors for this content
248 	 * service, which includes those that are bound through
249 	 * <b>viewerContentBinding</b>s and those that are bound through
250 	 * {@link #bindExtensions(String[], boolean)}.
251 	 *
252 	 * @return The set of <i>visible</i> content descriptors for this content
253 	 *         service
254 	 */
getVisibleExtensions()255 	INavigatorContentDescriptor[] getVisibleExtensions();
256 
257 	/**
258 	 * Bind the set of given extensions to this content service. Programmatic
259 	 * bindings allow clients to make extensions <i>visible</i> to an instance
260 	 * of the content service by appending to the bindings declared through
261 	 * <b>org.eclipse.ui.navigator.viewer</b>. Programmatic bindings are not
262 	 * persisted and are not remembered or propagated to other instances of the
263 	 * INavigatorContentService in the same session. Programmatic bindings
264 	 * cannot be undone for a given instance of the INavigatorContentService and
265 	 * do not override declarative bindings.
266 	 * <p>
267 	 * Once a content extension has been bound to the INavigatorContentService,
268 	 * clients may use
269 	 * {@link INavigatorActivationService#activateExtensions(String[], boolean) }
270 	 * or
271 	 * {@link  INavigatorActivationService#deactivateExtensions(String[], boolean) }
272 	 * to control the <i>activation</i> state of the extension. See
273 	 * {@link INavigatorContentService} for more information on the difference
274 	 * between <i>visible</i> and <i>active</i>.
275 	 * </p>
276 	 *
277 	 * @param extensionIds
278 	 *            The list of extensions to make visible.
279 	 * @param isRoot
280 	 *            whether the context provider should be a root content provider
281 	 * @return A list of all INavigatorContentDescriptors that correspond to the
282 	 *         given extensionIds.
283 	 */
bindExtensions(String[] extensionIds, boolean isRoot)284 	INavigatorContentDescriptor[] bindExtensions(String[] extensionIds,
285 			boolean isRoot);
286 
287 	/**
288 	 * Restore the state associated with the memento.
289 	 *
290 	 * @param aMemento
291 	 *            The memento for extensions to use when restoring previous
292 	 *            settings.
293 	 */
restoreState(IMemento aMemento)294 	void restoreState(IMemento aMemento);
295 
296 	/**
297 	 * Persist any session-to-session state with the memento.
298 	 *
299 	 * @param aMemento
300 	 *            The memento for extensions to use when persisting previous
301 	 *            settings.
302 	 */
saveState(IMemento aMemento)303 	void saveState(IMemento aMemento);
304 
305 	/**
306 	 * Add a listener to be notified whenever an extension is loaded.
307 	 *
308 	 * @param aListener
309 	 *            A listener to be attached.
310 	 */
addListener(INavigatorContentServiceListener aListener)311 	void addListener(INavigatorContentServiceListener aListener);
312 
313 	/**
314 	 * Remove a listener (by identity) from the set of listeners.
315 	 *
316 	 * @param aListener
317 	 *            A listener to be detached.
318 	 */
removeListener(INavigatorContentServiceListener aListener)319 	void removeListener(INavigatorContentServiceListener aListener);
320 
321 	/**
322 	 * The root content providers are recalculated by this method. The attached
323 	 * viewer is also refreshed as a result of this method.
324 	 *
325 	 */
update()326 	void update();
327 
328 	/**
329 	 * Release any acquired resources and instantiated content extensions.
330 	 *
331 	 */
dispose()332 	void dispose();
333 
334 	/**
335 	 * Search for extensions that declare the given element in their
336 	 * <b>triggerPoints</b> expression or that indicate they should be bound as
337 	 * a root extension.
338 	 *
339 	 * @param anElement
340 	 *            The element to use in the query
341 	 * @return The set of {@link INavigatorContentExtension}s that are
342 	 *         <i>visible</i> and <i>active</i> for this content service and
343 	 *         either declared through a
344 	 *         <b>org.eclipse.ui.navigator.viewer/viewerContentBinding</b> to
345 	 *         be a root element or have a <b>triggerPoints</b> expression that
346 	 *         is <i>enabled</i> for the given element.
347 	 */
findRootContentExtensions(Object anElement)348 	Set findRootContentExtensions(Object anElement);
349 
350 	/**
351 	 * Search for extensions that declare the given element in their
352 	 * <b>triggerPoints</b> expression.
353 	 *
354 	 * @param anElement
355 	 *            The element to use in the query
356 	 * @return The set of {@link INavigatorContentExtension}s that are
357 	 *         <i>visible</i> and <i>active</i> for this content service and
358 	 *         have a <b>triggerPoints</b> expression that is <i>enabled</i>
359 	 *         for the given element.
360 	 */
findContentExtensionsByTriggerPoint(Object anElement)361 	Set findContentExtensionsByTriggerPoint(Object anElement);
362 
363 	/**
364 	 * Search for extensions that declare the given element in their
365 	 * <b>possibleChildren</b> expression.
366 	 *
367 	 * @param anElement
368 	 *            The element to use in the query
369 	 * @return The set of {@link INavigatorContentExtension}s that are
370 	 *         <i>visible</i> and <i>active</i> for this content service and
371 	 *         have a <b>possibleChildren</b> expression that is <i>enabled</i>
372 	 *         for the given element.
373 	 */
findContentExtensionsWithPossibleChild(Object anElement)374 	Set findContentExtensionsWithPossibleChild(Object anElement);
375 
376 	/**
377 	 * The filter service can provide the available filters for the viewer, and
378 	 * manage which filters are <i>active</i>.
379 	 *
380 	 * @return An {@link INavigatorFilterService} that can provide information
381 	 *         to a viewer about what filters are <i>visible</i> and <i>active</i>.
382 	 */
getFilterService()383 	INavigatorFilterService getFilterService();
384 
385 	/**
386 	 * The sorter service provides the appropriate sorter based on the current
387 	 * items being sorted. By default, the CommonViewer uses
388 	 * {@link CommonViewerSorter} which delegates to this service. Clients do
389 	 * not need to provide their own {@link ViewerSorter} unless they wish to
390 	 * override this functionality.
391 	 *
392 	 * @return An {@link INavigatorSorterService} that can provide
393 	 *         {@link ViewerSorter} based on the context of the parent.
394 	 */
getSorterService()395 	INavigatorSorterService getSorterService();
396 
397 	/**
398 	 * The pipeline service calculates the appropriate viewer modification or
399 	 * refresh that should be applied for viewers that wish to take advantage of
400 	 * the model pipelining that some extensions use to massage or reshape
401 	 * contents in the viewer. Clients that use the {@link CommonViewer} do not
402 	 * need to be concerned with this service as the refreshes are automatically
403 	 * computed using this service.
404 	 *
405 	 *
406 	 * @return The {@link INavigatorPipelineService} which can determine the
407 	 *         correct updates to apply to a viewer.
408 	 */
getPipelineService()409 	INavigatorPipelineService getPipelineService();
410 
411 	/**
412 	 * The DND Service provides instances of {@link CommonDragAdapterAssistant}
413 	 * and {@link CommonDropAdapterAssistant} for this content service.
414 	 *
415 	 * @return The {@link INavigatorDnDService} which can add additional
416 	 *         TransferTypes for the DragAdapter and setup the data correctly
417 	 *         for those extended Transfer Types.
418 	 */
getDnDService()419 	INavigatorDnDService getDnDService();
420 
421 	/**
422 	 * The activation service is used to toggle whether certain extensions have
423 	 * the opportunity to contribute content and/or actions.
424 	 *
425 	 * @return The {@link INavigatorActivationService} for this content service.
426 	 */
getActivationService()427 	INavigatorActivationService getActivationService();
428 
429 	/**
430 	 * The saveable service helps implementing {@link ISaveablesSource}.
431 	 *
432 	 * @return the {@link INavigatorSaveablesService} for this content service.
433 	 */
getSaveablesService()434 	INavigatorSaveablesService getSaveablesService();
435 
436 	/**
437 	 * Return the content extension for the given id.
438 	 *
439 	 * @param anExtensionId The id used to define the <b>org.eclipse.ui.navigator.navigatorContent/navigatorContent</b> extension.
440 	 * @return An instance of the content extension for the given extension id. May return <b>null</b> if the id is invalid.
441 	 */
getContentExtensionById(String anExtensionId)442 	public INavigatorContentExtension getContentExtensionById(String anExtensionId);
443 
444 	/**
445 	 * Return the content extension for the given id.
446 	 *
447 	 * @param anExtensionId The id used to define the <b>org.eclipse.ui.navigator.navigatorContent/navigatorContent</b> extension.
448 	 * @return An instance of the content extension for the given extension id. May return <b>null</b> if the id is invalid.
449 	 * @since 3.3
450 	 */
getContentDescriptorById(String anExtensionId)451 	public INavigatorContentDescriptor getContentDescriptorById(String anExtensionId);
452 
453 
454 
455 }
456