001: /*******************************************************************************
002: * Copyright (c) 2000, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.internal.ui.views.dependencies;
011:
012: import org.eclipse.core.resources.IResource;
013: import org.eclipse.jface.action.Action;
014: import org.eclipse.jface.action.IMenuListener;
015: import org.eclipse.jface.action.IMenuManager;
016: import org.eclipse.jface.action.IStatusLineManager;
017: import org.eclipse.jface.action.IToolBarManager;
018: import org.eclipse.jface.action.MenuManager;
019: import org.eclipse.jface.action.Separator;
020: import org.eclipse.jface.dialogs.IDialogSettings;
021: import org.eclipse.jface.util.IPropertyChangeListener;
022: import org.eclipse.jface.util.PropertyChangeEvent;
023: import org.eclipse.jface.viewers.DoubleClickEvent;
024: import org.eclipse.jface.viewers.IContentProvider;
025: import org.eclipse.jface.viewers.IDoubleClickListener;
026: import org.eclipse.jface.viewers.IStructuredSelection;
027: import org.eclipse.jface.viewers.LabelProvider;
028: import org.eclipse.jface.viewers.StructuredViewer;
029: import org.eclipse.jface.viewers.Viewer;
030: import org.eclipse.jface.viewers.ViewerFilter;
031: import org.eclipse.jface.window.Window;
032: import org.eclipse.osgi.service.resolver.BaseDescription;
033: import org.eclipse.osgi.service.resolver.BundleDescription;
034: import org.eclipse.osgi.service.resolver.BundleSpecification;
035: import org.eclipse.osgi.service.resolver.ExportPackageDescription;
036: import org.eclipse.osgi.service.resolver.ImportPackageSpecification;
037: import org.eclipse.osgi.util.NLS;
038: import org.eclipse.pde.core.plugin.IPluginBase;
039: import org.eclipse.pde.core.plugin.IPluginImport;
040: import org.eclipse.pde.core.plugin.IPluginModelBase;
041: import org.eclipse.pde.core.plugin.IPluginObject;
042: import org.eclipse.pde.core.plugin.ISharedPluginModel;
043: import org.eclipse.pde.core.plugin.PluginRegistry;
044: import org.eclipse.pde.internal.ui.IPreferenceConstants;
045: import org.eclipse.pde.internal.ui.PDEPlugin;
046: import org.eclipse.pde.internal.ui.PDEUIMessages;
047: import org.eclipse.pde.internal.ui.editor.plugin.ManifestEditor;
048: import org.eclipse.pde.internal.ui.refactoring.RenamePluginAction;
049: import org.eclipse.pde.internal.ui.search.dependencies.DependencyExtentAction;
050: import org.eclipse.pde.internal.ui.search.dependencies.UnusedDependenciesAction;
051: import org.eclipse.pde.internal.ui.wizards.PluginSelectionDialog;
052: import org.eclipse.swt.widgets.Composite;
053: import org.eclipse.swt.widgets.Control;
054: import org.eclipse.swt.widgets.Menu;
055: import org.eclipse.ui.IActionBars;
056: import org.eclipse.ui.IWorkbenchActionConstants;
057: import org.eclipse.ui.part.Page;
058:
059: public abstract class DependenciesViewPage extends Page {
060: class FocusOnSelectionAction extends Action {
061: public void run() {
062: handleFocusOn(getSelectedObject());
063: }
064:
065: public void update(Object object) {
066: setEnabled(object != null);
067: String name = ((LabelProvider) fViewer.getLabelProvider())
068: .getText(object);
069: setText(NLS
070: .bind(
071: PDEUIMessages.DependenciesViewPage_focusOnSelection,
072: name));
073: }
074: }
075:
076: private Action fFocusOnAction;
077:
078: private FocusOnSelectionAction fFocusOnSelectionAction;
079:
080: private Action fOpenAction;
081:
082: protected RenamePluginAction fRefactorAction;
083:
084: private IPropertyChangeListener fPropertyListener;
085:
086: private DependenciesView fView;
087:
088: protected StructuredViewer fViewer;
089:
090: protected IContentProvider fContentProvider;
091:
092: private Action fHideFragmentFilterAction;
093:
094: protected Action fHideOptionalFilterAction;
095:
096: private FragmentFilter fHideFragmentFilter = new FragmentFilter();
097:
098: private static final String HIDE_FRAGMENTS = "hideFrags"; //$NON-NLS-1$
099:
100: private static final String HIDE_OPTIONAL = "hideOptional"; //$NON-NLS-1$
101:
102: class FragmentFilter extends ViewerFilter {
103:
104: public boolean select(Viewer v, Object parent, Object element) {
105: BundleDescription desc = null;
106: if (element instanceof BundleSpecification) {
107: BaseDescription supplier = ((BundleSpecification) element)
108: .getSupplier();
109: if (supplier instanceof BundleDescription)
110: desc = (BundleDescription) supplier;
111: } else if (element instanceof BundleDescription) {
112: desc = (BundleDescription) element;
113: } else if (element instanceof ImportPackageSpecification) {
114: BaseDescription export = ((ImportPackageSpecification) element)
115: .getSupplier();
116: desc = ((ExportPackageDescription) export)
117: .getExporter();
118: }
119: if (desc != null) {
120: return desc.getHost() == null;
121: }
122: return true;
123: }
124: }
125:
126: /**
127: *
128: */
129: public DependenciesViewPage(DependenciesView view,
130: IContentProvider contentProvider) {
131: this .fView = view;
132: this .fContentProvider = contentProvider;
133: fPropertyListener = new IPropertyChangeListener() {
134: public void propertyChange(PropertyChangeEvent event) {
135: String property = event.getProperty();
136: if (property
137: .equals(IPreferenceConstants.PROP_SHOW_OBJECTS)) {
138: fViewer.refresh();
139: }
140: }
141: };
142: }
143:
144: /*
145: * (non-Javadoc)
146: *
147: * @see org.eclipse.ui.part.IPage#createControl(org.eclipse.swt.widgets.Composite)
148: */
149: public void createControl(Composite parent) {
150: fViewer = createViewer(parent);
151: fViewer.setComparator(DependenciesViewComparator
152: .getViewerComparator());
153: PDEPlugin.getDefault().getPreferenceStore()
154: .addPropertyChangeListener(fPropertyListener);
155: getSite().setSelectionProvider(fViewer);
156: }
157:
158: protected abstract StructuredViewer createViewer(Composite parent);
159:
160: public void dispose() {
161: PDEPlugin.getDefault().getPreferenceStore()
162: .removePropertyChangeListener(fPropertyListener);
163: super .dispose();
164: }
165:
166: private void fillContextMenu(IMenuManager manager) {
167: IStructuredSelection selection = (IStructuredSelection) fViewer
168: .getSelection();
169:
170: if (selection.size() == 1) {
171: manager.add(fOpenAction);
172: manager.add(new Separator());
173: }
174: fFocusOnSelectionAction.update(getSelectedObject());
175: if (fFocusOnSelectionAction.isEnabled())
176: manager.add(fFocusOnSelectionAction);
177: manager.add(fFocusOnAction);
178: Object selectionElement = selection.getFirstElement();
179:
180: manager.add(new Separator());
181: // only show Find Dependency Extent when in Callees view
182: if (selection.size() == 1 && !fView.isShowingCallers()) {
183: String id = null;
184: if (selectionElement instanceof BundleSpecification) {
185: id = ((BundleSpecification) selectionElement).getName();
186: } else if (selectionElement instanceof BundleDescription) {
187: id = ((BundleDescription) selectionElement)
188: .getSymbolicName();
189: }
190: // don't include find dependency extent for unresolved imports or bundles
191: if (id != null && PluginRegistry.findModel(id) != null) {
192: Object input = fViewer.getInput();
193: if (input instanceof IPluginBase)
194: input = ((IPluginBase) input).getModel();
195: if (input instanceof IPluginModelBase) {
196: IPluginModelBase base = (IPluginModelBase) input;
197: IResource res = (base == null) ? null : base
198: .getUnderlyingResource();
199: if (res != null)
200: manager.add(new DependencyExtentAction(res
201: .getProject(), id));
202: }
203: }
204: }
205: // Unused Dependencies Action, only for worskpace plug-ins
206: ISharedPluginModel model = null;
207: if (selectionElement instanceof BundleSpecification) {
208: model = PluginRegistry
209: .findModel(((BundleSpecification) selectionElement)
210: .getName());
211: } else if (selectionElement instanceof BundleDescription) {
212: model = PluginRegistry
213: .findModel((BundleDescription) selectionElement);
214: } else if (selectionElement instanceof IPluginBase) {
215: // root
216: model = ((IPluginBase) selectionElement).getModel();
217: }
218: if (model != null && model.getUnderlyingResource() != null) {
219: manager.add(new UnusedDependenciesAction(
220: (IPluginModelBase) model, true));
221: }
222: if (enableRename(selection)) {
223: manager.add(new Separator());
224: manager.add(fRefactorAction);
225: }
226:
227: manager.add(new Separator());
228: manager.add(new Separator(
229: IWorkbenchActionConstants.MB_ADDITIONS));
230: }
231:
232: /*
233: * (non-Javadoc)
234: *
235: * @see org.eclipse.ui.part.IPage#getControl()
236: */
237: public Control getControl() {
238: return fViewer.getControl();
239: }
240:
241: private Object getSelectedObject() {
242: IStructuredSelection selection = getSelection();
243: if (selection.isEmpty() || selection.size() != 1)
244: return null;
245: return selection.getFirstElement();
246: }
247:
248: protected IStructuredSelection getSelection() {
249: return (IStructuredSelection) fViewer.getSelection();
250: }
251:
252: protected void setSelection(IStructuredSelection selection) {
253: if (selection != null && !selection.isEmpty())
254: fViewer.setSelection(selection, true);
255: }
256:
257: /**
258: * @return Returns the view.
259: */
260: public DependenciesView getView() {
261: return fView;
262: }
263:
264: private void handleDoubleClick() {
265: Object obj = getSelectedObject();
266: BundleDescription desc = null;
267: if (obj instanceof BundleSpecification) {
268: desc = (BundleDescription) ((BundleSpecification) obj)
269: .getSupplier();
270: } else if (obj instanceof BundleDescription) {
271: desc = (BundleDescription) obj;
272:
273: } else if (obj instanceof IPluginBase) {
274: // root object
275: desc = ((IPluginModelBase) ((IPluginBase) obj).getModel())
276: .getBundleDescription();
277: } else if (obj instanceof ImportPackageSpecification) {
278: BaseDescription export = ((ImportPackageSpecification) obj)
279: .getSupplier();
280: desc = ((ExportPackageDescription) export).getExporter();
281: }
282: if (desc != null)
283: ManifestEditor.openPluginEditor(desc.getSymbolicName());
284: }
285:
286: private void handleFocusOn() {
287: PluginSelectionDialog dialog = new PluginSelectionDialog(
288: fViewer.getControl().getShell(), true, false);
289: dialog.create();
290: if (dialog.open() == Window.OK) {
291: handleFocusOn(dialog.getFirstResult());
292: }
293: }
294:
295: private void handleFocusOn(Object newFocus) {
296: if (newFocus instanceof IPluginModelBase) {
297: fView.openTo(newFocus);
298: }
299: if (newFocus instanceof IPluginBase) {
300: fView.openTo(((IPluginBase) newFocus).getModel());
301: }
302: if (newFocus instanceof IPluginImport) {
303: IPluginImport pluginImport = ((IPluginImport) newFocus);
304: String id = pluginImport.getId();
305: IPluginModelBase model = PluginRegistry.findModel(id);
306: if (model != null) {
307: fView.openTo(model);
308: } else {
309: fView.openTo(null);
310: }
311: }
312: BundleDescription desc = null;
313: if (newFocus instanceof BundleSpecification) {
314: desc = (BundleDescription) ((BundleSpecification) newFocus)
315: .getSupplier();
316: if (desc == null)
317: fView.openTo(null);
318: }
319: if (newFocus instanceof BundleDescription) {
320: desc = (BundleDescription) newFocus;
321: }
322: if (desc != null)
323: fView.openTo(PluginRegistry.findModel(desc
324: .getSymbolicName()));
325: }
326:
327: private void hookContextMenu() {
328: MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
329: menuMgr.setRemoveAllWhenShown(true);
330: menuMgr.addMenuListener(new IMenuListener() {
331: public void menuAboutToShow(IMenuManager manager) {
332: DependenciesViewPage.this .fillContextMenu(manager);
333: }
334: });
335: Menu menu = menuMgr.createContextMenu(fViewer.getControl());
336: fViewer.getControl().setMenu(menu);
337:
338: getSite().registerContextMenu(fView.getSite().getId(), menuMgr,
339: fViewer);
340: }
341:
342: private void hookDoubleClickAction() {
343: fViewer.addDoubleClickListener(new IDoubleClickListener() {
344: public void doubleClick(DoubleClickEvent event) {
345: handleDoubleClick();
346: }
347: });
348: }
349:
350: private void makeActions() {
351: fOpenAction = new Action() {
352: public void run() {
353: handleDoubleClick();
354: }
355: };
356: fOpenAction.setText(PDEUIMessages.DependenciesView_open);
357:
358: fFocusOnSelectionAction = new FocusOnSelectionAction();
359:
360: fFocusOnAction = new Action() {
361: public void run() {
362: handleFocusOn();
363: }
364: };
365: fFocusOnAction
366: .setText(PDEUIMessages.DependenciesViewPage_focusOn);
367:
368: fRefactorAction = new RenamePluginAction();
369:
370: fHideFragmentFilterAction = new Action() {
371: public void run() {
372: boolean checked = fHideFragmentFilterAction.isChecked();
373: if (checked)
374: fViewer.removeFilter(fHideFragmentFilter);
375: else
376: fViewer.addFilter(fHideFragmentFilter);
377: getSettings().put(HIDE_FRAGMENTS, !checked);
378: }
379: };
380: fHideFragmentFilterAction
381: .setText(PDEUIMessages.DependenciesViewPage_showFragments);
382:
383: fHideOptionalFilterAction = new Action() {
384: public void run() {
385: boolean checked = isChecked();
386: handleShowOptional(isChecked(), true);
387: getSettings().put(HIDE_OPTIONAL, !checked);
388: }
389: };
390: fHideOptionalFilterAction
391: .setText(PDEUIMessages.DependenciesViewPage_showOptional);
392: }
393:
394: protected abstract void handleShowOptional(boolean checked,
395: boolean refreshIfNecessary);
396:
397: protected abstract boolean isShowingOptional();
398:
399: /*
400: * (non-Javadoc)
401: *
402: * @see org.eclipse.ui.part.Page#makeContributions(org.eclipse.jface.action.IMenuManager,
403: * org.eclipse.jface.action.IToolBarManager,
404: * org.eclipse.jface.action.IStatusLineManager)
405: */
406: public void makeContributions(IMenuManager menuManager,
407: IToolBarManager toolBarManager,
408: IStatusLineManager statusLineManager) {
409: super .makeContributions(menuManager, toolBarManager,
410: statusLineManager);
411: makeActions();
412: hookContextMenu();
413: hookDoubleClickAction();
414: contributeToActionBars(getSite().getActionBars());
415: }
416:
417: /*
418: * (non-Javadoc)
419: *
420: * @see org.eclipse.ui.part.IPage#setFocus()
421: */
422: public void setFocus() {
423: if (fViewer != null) {
424: Control c = fViewer.getControl();
425: if (!c.isFocusControl()) {
426: c.setFocus();
427: }
428: }
429: }
430:
431: public void setInput(Object object) {
432: if (object != fViewer.getInput())
433: fViewer.setInput(object);
434: }
435:
436: // returns true if Rename Action is valid.
437: protected boolean enableRename(IStructuredSelection selection) {
438: if (selection.size() == 1) {
439: Object selectionElement = selection.getFirstElement();
440: IPluginModelBase base = null;
441: if (selectionElement instanceof IPluginImport) {
442: String id = ((IPluginImport) selectionElement).getId();
443: base = PluginRegistry.findModel(id);
444: } else if (selectionElement instanceof IPluginObject) {
445: base = (IPluginModelBase) ((IPluginObject) selectionElement)
446: .getModel();
447: } else if (selectionElement instanceof BundleSpecification) {
448: BundleDescription desc = (BundleDescription) ((BundleSpecification) selectionElement)
449: .getSupplier();
450: if (desc != null)
451: base = PluginRegistry.findModel(desc);
452: } else if (selectionElement instanceof BundleDescription) {
453: base = PluginRegistry
454: .findModel((BundleDescription) selectionElement);
455: }
456: if (base != null && base.getUnderlyingResource() != null) {
457: fRefactorAction.setPlugin(base);
458: return true;
459: }
460: }
461: return false;
462: }
463:
464: public void setActive(boolean active) {
465: if (active) {
466: // update filter actions before updating filters because the filters depend on the state of the filter actions
467: // update filter actions - both filter actions are specific to each Page instance
468: if (fView.isShowingCallers()) {
469: // deactive show optional on Callers view.
470: fHideOptionalFilterAction.setChecked(true);
471: fHideOptionalFilterAction.setEnabled(false);
472: } else {
473: fHideOptionalFilterAction.setEnabled(true);
474: fHideOptionalFilterAction.setChecked(!getSettings()
475: .getBoolean(HIDE_OPTIONAL));
476: }
477: fHideFragmentFilterAction.setChecked(!getSettings()
478: .getBoolean(HIDE_FRAGMENTS));
479:
480: // update viewer's fragment filter
481: boolean showFragments = fHideFragmentFilterAction
482: .isChecked();
483: boolean containsFragments = true;
484: ViewerFilter[] filters = fViewer.getFilters();
485: for (int i = 0; i < filters.length; i++) {
486: if (filters[i].equals(fHideFragmentFilter)) {
487: containsFragments = false;
488: break;
489: }
490: }
491: if (showFragments != containsFragments)
492: if (showFragments)
493: fViewer.removeFilter(fHideFragmentFilter);
494: else
495: fViewer.addFilter(fHideFragmentFilter);
496:
497: // update viewer's optional filtering
498: if (fHideOptionalFilterAction.isChecked() != isShowingOptional())
499: handleShowOptional(fHideOptionalFilterAction
500: .isChecked(), false);
501: }
502:
503: if (fContentProvider instanceof DependenciesViewPageContentProvider) {
504: if (active) {
505: // when a page is activated, we need to have the content provider listen for changes and refresh the view to get current data
506: ((DependenciesViewPageContentProvider) fContentProvider)
507: .attachModelListener();
508: fViewer.refresh();
509: } else
510: // when page is deactivated, we need to remove model listener from content manager. Otherwise model changes will be sent to all
511: // DependenciesViewPageContentProvider (including inactive ones). This will cause problems with the content provider's logic!!
512: ((DependenciesViewPageContentProvider) fContentProvider)
513: .removeModelListener();
514: }
515: }
516:
517: private void contributeToActionBars(IActionBars actionBars) {
518: contributeToDropDownMenu(actionBars.getMenuManager());
519: }
520:
521: private void contributeToDropDownMenu(IMenuManager manager) {
522: manager.add(fHideFragmentFilterAction);
523: manager.add(fHideOptionalFilterAction);
524: IDialogSettings settings = getSettings();
525: boolean hideFragments = settings.getBoolean(HIDE_FRAGMENTS);
526: boolean hideOptional = settings.getBoolean(HIDE_OPTIONAL);
527: fHideFragmentFilterAction.setChecked(!hideFragments);
528: fHideOptionalFilterAction.setChecked(!hideOptional);
529: // The filtering will be executed in the setActive function when the viewer is displayed
530: }
531:
532: private IDialogSettings getSettings() {
533: IDialogSettings master = PDEPlugin.getDefault()
534: .getDialogSettings();
535: IDialogSettings section = master.getSection("dependenciesView"); //$NON-NLS-1$
536: if (section == null) {
537: section = master.addNewSection("dependenciesView"); //$NON-NLS-1$
538: }
539: return section;
540: }
541:
542: }
|