001: /*******************************************************************************
002: * Copyright (c) 2001, 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.ui.views.properties.tabbed;
011:
012: import java.util.ArrayList;
013: import java.util.Collection;
014: import java.util.HashMap;
015: import java.util.Iterator;
016: import java.util.List;
017: import java.util.Map;
018:
019: import org.eclipse.core.runtime.IAdaptable;
020: import org.eclipse.core.runtime.Platform;
021: import org.eclipse.jface.action.IAction;
022: import org.eclipse.jface.viewers.ILabelProviderListener;
023: import org.eclipse.jface.viewers.ISelection;
024: import org.eclipse.jface.viewers.ISelectionChangedListener;
025: import org.eclipse.jface.viewers.IStructuredContentProvider;
026: import org.eclipse.jface.viewers.IStructuredSelection;
027: import org.eclipse.jface.viewers.LabelProvider;
028: import org.eclipse.jface.viewers.LabelProviderChangedEvent;
029: import org.eclipse.jface.viewers.SelectionChangedEvent;
030: import org.eclipse.jface.viewers.StructuredSelection;
031: import org.eclipse.swt.SWT;
032: import org.eclipse.swt.graphics.Image;
033: import org.eclipse.swt.graphics.Point;
034: import org.eclipse.swt.layout.FillLayout;
035: import org.eclipse.swt.layout.FormAttachment;
036: import org.eclipse.swt.layout.FormData;
037: import org.eclipse.swt.layout.FormLayout;
038: import org.eclipse.swt.widgets.Composite;
039: import org.eclipse.swt.widgets.Control;
040: import org.eclipse.ui.IActionBars;
041: import org.eclipse.ui.IEditorPart;
042: import org.eclipse.ui.IPartListener;
043: import org.eclipse.ui.IViewPart;
044: import org.eclipse.ui.IWorkbenchPart;
045: import org.eclipse.ui.IWorkbenchWindow;
046: import org.eclipse.ui.actions.ActionFactory;
047: import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyComposite;
048: import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyRegistry;
049: import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyRegistryFactory;
050: import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyTitle;
051: import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyViewer;
052: import org.eclipse.ui.part.IContributedContentsView;
053: import org.eclipse.ui.part.Page;
054: import org.eclipse.ui.views.properties.IPropertySheetPage;
055: import org.eclipse.ui.views.properties.PropertySheet;
056:
057: /**
058: * A property sheet page that provides a tabbed UI.
059: *
060: * @author Anthony Hunter
061: */
062: public class TabbedPropertySheetPage extends Page implements
063: IPropertySheetPage, ILabelProviderListener {
064:
065: // widgets
066: private TabbedPropertyComposite tabbedPropertyComposite;
067:
068: private TabbedPropertySheetWidgetFactory widgetFactory;
069:
070: private ITabbedPropertySheetPageContributor contributor;
071:
072: private TabbedPropertyRegistry registry;
073:
074: private ITabbedPropertySheetPageContributor selectionContributor = null;
075:
076: /**
077: * The currently active contributor id, which may not match the contributor
078: * id from the workbench part that created this instance.
079: */
080: private String currentContributorId;
081:
082: protected IStructuredContentProvider tabListContentProvider;
083:
084: private ISelection currentSelection;
085:
086: private boolean activePropertySheet;
087:
088: private TabbedPropertyViewer tabbedPropertyViewer;
089:
090: private TabContents currentTab;
091:
092: private Map descriptorToTab;
093:
094: private Map tabToComposite;
095:
096: private List selectionQueue;
097:
098: private boolean selectionQueueLocked;
099:
100: private List tabSelectionListeners;
101:
102: private IWorkbenchWindow cachedWorkbenchWindow;
103:
104: private boolean hasTitleBar;
105:
106: /**
107: * a listener that is interested in part activation events.
108: */
109: private IPartListener partActivationListener = new IPartListener() {
110:
111: public void partActivated(IWorkbenchPart part) {
112: handlePartActivated(part);
113: }
114:
115: public void partBroughtToTop(IWorkbenchPart part) {
116: }
117:
118: public void partClosed(IWorkbenchPart part) {
119: }
120:
121: public void partDeactivated(IWorkbenchPart part) {
122: }
123:
124: public void partOpened(IWorkbenchPart part) {
125: }
126: };
127:
128: private class TabbedPropertySheetPageContributorFromSelection
129: implements ITabbedPropertySheetPageContributor {
130:
131: private String contributorId;
132:
133: /**
134: * Constructor that takes in a contributor id taken from a selection.
135: *
136: * @param contributorId
137: * the contributor id.
138: */
139: public TabbedPropertySheetPageContributorFromSelection(
140: String contributorId) {
141: super ();
142: this .contributorId = contributorId;
143: }
144:
145: /**
146: * @see org.eclipse.ui.views.properties.tabbed.ITabbedPropertySheetPageContributor#getContributorId()
147: */
148: public String getContributorId() {
149: return contributorId;
150: }
151:
152: }
153:
154: /**
155: * Label provider for the ListViewer.
156: */
157: class TabbedPropertySheetPageLabelProvider extends LabelProvider {
158:
159: public String getText(Object element) {
160: if (element instanceof ITabDescriptor) {
161: return ((ITabDescriptor) element).getLabel();
162: }
163: return null;
164: }
165: }
166:
167: /**
168: * SelectionChangedListener for the ListViewer.
169: */
170: class SelectionChangedListener implements ISelectionChangedListener {
171:
172: /**
173: * Shows the tab associated with the selection.
174: */
175: public void selectionChanged(SelectionChangedEvent event) {
176: IStructuredSelection selection = (IStructuredSelection) event
177: .getSelection();
178: TabContents tab = null;
179: ITabDescriptor descriptor = (ITabDescriptor) selection
180: .getFirstElement();
181:
182: if (descriptor == null) {
183: // pretend the tab is empty.
184: hideTab(currentTab);
185: } else {
186: // create tab if necessary
187: // can not cache based on the id - tabs may have the same id,
188: // but different section depending on the selection
189: tab = (TabContents) descriptorToTab.get(descriptor);
190:
191: if (tab != currentTab) {
192: hideTab(currentTab);
193: }
194:
195: Composite tabComposite = (Composite) tabToComposite
196: .get(tab);
197: if (tabComposite == null) {
198: tabComposite = createTabComposite();
199: tab.createControls(tabComposite,
200: TabbedPropertySheetPage.this );
201: // tabAreaComposite.layout(true);
202: tabToComposite.put(tab, tabComposite);
203: }
204: // force widgets to be resized
205: tab.setInput(tabbedPropertyViewer.getWorkbenchPart(),
206: (ISelection) tabbedPropertyViewer.getInput());
207:
208: // store tab selection
209: storeCurrentTabSelection(descriptor.getLabel());
210:
211: if (tab != currentTab) {
212: showTab(tab);
213: }
214:
215: tab.refresh();
216: }
217: tabbedPropertyComposite.getTabComposite().layout(true);
218: currentTab = tab;
219: resizeScrolledComposite();
220:
221: if (descriptor != null) {
222: handleTabSelection(descriptor);
223: }
224: }
225:
226: /**
227: * Shows the given tab.
228: */
229: private void showTab(TabContents target) {
230: if (target != null) {
231: Composite tabComposite = (Composite) tabToComposite
232: .get(target);
233: if (tabComposite != null) {
234: /**
235: * the following method call order is important - do not
236: * change it or the widgets might be drawn incorrectly
237: */
238: tabComposite.moveAbove(null);
239: target.aboutToBeShown();
240: tabComposite.setVisible(true);
241: }
242: }
243: }
244:
245: /**
246: * Hides the given tab.
247: */
248: private void hideTab(TabContents target) {
249: if (target != null) {
250: Composite tabComposite = (Composite) tabToComposite
251: .get(target);
252: if (tabComposite != null) {
253: target.aboutToBeHidden();
254: tabComposite.setVisible(false);
255: }
256: }
257: }
258:
259: }
260:
261: /**
262: * create a new tabbed property sheet page.
263: *
264: * @param tabbedPropertySheetPageContributor
265: * the tabbed property sheet page contributor.
266: */
267: public TabbedPropertySheetPage(
268: ITabbedPropertySheetPageContributor tabbedPropertySheetPageContributor) {
269: contributor = tabbedPropertySheetPageContributor;
270: tabToComposite = new HashMap();
271: selectionQueue = new ArrayList(10);
272: tabSelectionListeners = new ArrayList();
273: initContributor(contributor.getContributorId());
274: }
275:
276: /**
277: * Handle the part activated event.
278: *
279: * @param part
280: * the new activated part.
281: */
282: protected void handlePartActivated(IWorkbenchPart part) {
283: /*
284: * The properties view has been activated and the current page is this
285: * instance of TabbedPropertySheetPage
286: */
287: boolean this Activated = part instanceof PropertySheet
288: && ((PropertySheet) part).getCurrentPage() == this ;
289:
290: /*
291: * When the active part changes and the part does not provide a
292: * selection that affects this property sheet page, the PropertySheet
293: * does not send us a selectionChanged() event. We need to be informed
294: * of these events since we want to send aboutToBeHidden() and
295: * aboutToBeShown() when the property sheet is hidden or shown.
296: */
297: if (!this Activated
298: && !part.equals(contributor)
299: && !part.getSite().getId().equals(
300: contributor.getContributorId())) {
301: /*
302: * Is the part is a IContributedContentsView for the contributor,
303: * for example, outline view.
304: */
305: IContributedContentsView view = (IContributedContentsView) part
306: .getAdapter(IContributedContentsView.class);
307: if (view == null
308: || (view.getContributingPart() != null && !view
309: .getContributingPart().equals(contributor))) {
310: if (activePropertySheet) {
311: if (currentTab != null) {
312: currentTab.aboutToBeHidden();
313: }
314: activePropertySheet = false;
315: }
316: return;
317: }
318: }
319: if (!activePropertySheet && currentTab != null) {
320: currentTab.aboutToBeShown();
321: currentTab.refresh();
322: }
323: activePropertySheet = true;
324: }
325:
326: /**
327: * @see org.eclipse.ui.part.IPage#createControl(org.eclipse.swt.widgets.Composite)
328: */
329: public void createControl(Composite parent) {
330: widgetFactory = new TabbedPropertySheetWidgetFactory();
331: tabbedPropertyComposite = new TabbedPropertyComposite(parent,
332: widgetFactory, hasTitleBar);
333: widgetFactory.paintBordersFor(tabbedPropertyComposite);
334: tabbedPropertyComposite.setLayout(new FormLayout());
335: FormData formData = new FormData();
336: formData.left = new FormAttachment(0, 0);
337: formData.right = new FormAttachment(100, 0);
338: formData.top = new FormAttachment(0, 0);
339: formData.bottom = new FormAttachment(100, 0);
340: tabbedPropertyComposite.setLayoutData(formData);
341:
342: tabbedPropertyViewer = new TabbedPropertyViewer(
343: tabbedPropertyComposite.getList());
344: tabbedPropertyViewer.setContentProvider(tabListContentProvider);
345: tabbedPropertyViewer
346: .setLabelProvider(new TabbedPropertySheetPageLabelProvider());
347: tabbedPropertyViewer
348: .addSelectionChangedListener(new SelectionChangedListener());
349:
350: /**
351: * Add a part activation listener.
352: */
353: cachedWorkbenchWindow = getSite().getWorkbenchWindow();
354: cachedWorkbenchWindow.getPartService().addPartListener(
355: partActivationListener);
356:
357: /**
358: * Add a label provider change listener.
359: */
360: if (hasTitleBar) {
361: registry.getLabelProvider().addListener(this );
362: }
363: }
364:
365: /**
366: * Initialize the contributor with the provided contributor id.
367: *
368: * @param contributorId
369: * the contributor id.
370: */
371: private void initContributor(String contributorId) {
372: descriptorToTab = new HashMap();
373: if (contributor.getContributorId().equals(contributorId)) {
374: /**
375: * default contributor from the workbench part.
376: */
377: registry = TabbedPropertyRegistryFactory.getInstance()
378: .createRegistry(contributor);
379: } else {
380: /**
381: * selection contributor.
382: */
383: selectionContributor = new TabbedPropertySheetPageContributorFromSelection(
384: contributorId);
385: registry = TabbedPropertyRegistryFactory.getInstance()
386: .createRegistry(selectionContributor);
387: }
388: currentContributorId = contributorId;
389: tabListContentProvider = getTabListContentProvider();
390: hasTitleBar = registry.getLabelProvider() != null;
391:
392: if (tabbedPropertyViewer != null) {
393: tabbedPropertyViewer
394: .setContentProvider(tabListContentProvider);
395: }
396:
397: /**
398: * Add a label provider change listener.
399: */
400: if (hasTitleBar) {
401: registry.getLabelProvider().addListener(this );
402: }
403:
404: }
405:
406: /**
407: * Gets the tab list content provider for the contributor.
408: *
409: * @return the tab list content provider for the contributor.
410: */
411: protected IStructuredContentProvider getTabListContentProvider() {
412: return registry.getTabListContentProvider();
413: }
414:
415: /**
416: * Dispose the contributor with the provided contributor id. This happens on
417: * part close as well as when contributiors switch between the workbench
418: * part and contributor from a selection.
419: *
420: * @param contributorId
421: * the contributor id.
422: */
423: private void disposeContributor() {
424: /**
425: * If the current tab is about to be disposed we have to call
426: * aboutToBeHidden
427: */
428: if (currentTab != null) {
429: currentTab.aboutToBeHidden();
430: currentTab = null;
431: }
432:
433: disposeTabs(descriptorToTab.values());
434: descriptorToTab = new HashMap();
435:
436: /**
437: * Remove the label provider change listener.
438: */
439: if (hasTitleBar && registry != null) {
440: registry.getLabelProvider().removeListener(this );
441: }
442:
443: if (selectionContributor != null) {
444: /**
445: * remove the selection contributed registry.
446: */
447: TabbedPropertyRegistryFactory.getInstance()
448: .disposeRegistry(selectionContributor);
449: selectionContributor = null;
450: }
451: }
452:
453: /**
454: * @see org.eclipse.ui.part.IPage#dispose()
455: */
456: public void dispose() {
457:
458: disposeContributor();
459:
460: if (widgetFactory != null) {
461: widgetFactory.dispose();
462: widgetFactory = null;
463: }
464: /**
465: * Remove the part activation listener.
466: */
467: if (cachedWorkbenchWindow != null) {
468: cachedWorkbenchWindow.getPartService().removePartListener(
469: partActivationListener);
470: cachedWorkbenchWindow = null;
471: }
472:
473: if (registry != null) {
474: TabbedPropertyRegistryFactory.getInstance()
475: .disposeRegistry(contributor);
476: registry = null;
477: }
478:
479: contributor = null;
480: currentSelection = null;
481: }
482:
483: /**
484: * @see org.eclipse.ui.part.IPage#getControl()
485: */
486: public Control getControl() {
487: return tabbedPropertyComposite;
488: }
489:
490: /**
491: * @see org.eclipse.ui.part.IPage#setActionBars(org.eclipse.ui.IActionBars)
492: */
493: public void setActionBars(IActionBars actionBars) {
494: // Override the undo and redo global action handlers
495: // to use the contributor action handlers
496: IActionBars partActionBars = null;
497: if (contributor instanceof IEditorPart) {
498: IEditorPart editorPart = (IEditorPart) contributor;
499: partActionBars = editorPart.getEditorSite().getActionBars();
500: } else if (contributor instanceof IViewPart) {
501: IViewPart viewPart = (IViewPart) contributor;
502: partActionBars = viewPart.getViewSite().getActionBars();
503: }
504:
505: if (partActionBars != null) {
506: IAction action = partActionBars
507: .getGlobalActionHandler(ActionFactory.UNDO.getId());
508: if (action != null) {
509: actionBars.setGlobalActionHandler(ActionFactory.UNDO
510: .getId(), action);
511: }
512: action = partActionBars
513: .getGlobalActionHandler(ActionFactory.REDO.getId());
514: if (action != null) {
515: actionBars.setGlobalActionHandler(ActionFactory.REDO
516: .getId(), action);
517: }
518: }
519: }
520:
521: /**
522: * @see org.eclipse.ui.part.IPage#setFocus()
523: */
524: public void setFocus() {
525: getControl().setFocus();
526: }
527:
528: /**
529: * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart,
530: * org.eclipse.jface.viewers.ISelection)
531: */
532: public void selectionChanged(IWorkbenchPart part,
533: ISelection selection) {
534: setInput(part, selection);
535: }
536:
537: /**
538: * Stores the current tab label in the selection queue. Tab labels are used
539: * to carry the tab context from one input object to another. The queue
540: * specifies the selection priority. So if the first tab in the queue is not
541: * available for the input we try the second tab and so on. If none of the
542: * tabs are available we default to the first tab available for the input.
543: */
544: private void storeCurrentTabSelection(String label) {
545: if (!selectionQueueLocked) {
546: selectionQueue.remove(label);
547: selectionQueue.add(0, label);
548: }
549: }
550:
551: private void resizeScrolledComposite() {
552: Point currentTabSize = new Point(0, 0);
553: if (currentTab != null) {
554: Composite sizeReference = (Composite) tabToComposite
555: .get(currentTab);
556: if (sizeReference != null) {
557: currentTabSize = sizeReference.computeSize(SWT.DEFAULT,
558: SWT.DEFAULT);
559: }
560: }
561: tabbedPropertyComposite.getScrolledComposite().setMinSize(
562: currentTabSize.x, currentTabSize.y);
563: }
564:
565: private void disposeTabs(Collection tabs) {
566: for (Iterator iter = tabs.iterator(); iter.hasNext();) {
567: TabContents tab = (TabContents) iter.next();
568: Composite composite = (Composite) tabToComposite
569: .remove(tab);
570: tab.dispose();
571: if (composite != null) {
572: composite.dispose();
573: }
574: }
575: }
576:
577: /**
578: * Returns the last known selected tab for the given input.
579: */
580: private int getLastTabSelection(IWorkbenchPart part,
581: ISelection input) {
582: ITabDescriptor[] descriptors = registry.getTabDescriptors(part,
583: input);
584: if (descriptors.length != 0) {
585: for (Iterator iter = selectionQueue.iterator(); iter
586: .hasNext();) {
587: String text = (String) iter.next();
588: for (int i = 0; i < descriptors.length; i++) {
589: if (text.equals(descriptors[i].getLabel())) {
590: return i;
591: }
592: }
593: }
594: }
595: return 0;
596: }
597:
598: /**
599: * Update the current tabs to represent the given input object. When tabs
600: * apply for both the old and new input they are reused otherwise they are
601: * disposed. If the current visible tab will not be reused (i.e. will be
602: * disposed) we have to send it an aboutToBeHidden() message.
603: */
604: protected void updateTabs(ITabDescriptor[] descriptors) {
605: Map newTabs = new HashMap(descriptors.length * 2);
606: boolean disposingCurrentTab = (currentTab != null);
607: for (int i = 0; i < descriptors.length; i++) {
608: TabContents tab = (TabContents) descriptorToTab
609: .remove(descriptors[i]);
610:
611: if (tab != null && tab.controlsHaveBeenCreated()) {
612: if (tab == currentTab) {
613: disposingCurrentTab = false;
614: }
615: } else {
616: tab = createTab(descriptors[i]);
617: }
618:
619: newTabs.put(descriptors[i], tab);
620: }
621: if (disposingCurrentTab) {
622: /**
623: * If the current tab is about to be disposed we have to call
624: * aboutToBeHidden
625: */
626: currentTab.aboutToBeHidden();
627: currentTab = null;
628: }
629: disposeTabs(descriptorToTab.values());
630: descriptorToTab = newTabs;
631: }
632:
633: /**
634: * Create the tab contents for the provided tab descriptor.
635: *
636: * @param tabDescriptor
637: * the tab descriptor.
638: * @return the tab contents.
639: */
640: protected TabContents createTab(ITabDescriptor tabDescriptor) {
641: return tabDescriptor.createTab();
642: }
643:
644: /**
645: * Helper method for creating property tab composites.
646: *
647: * @return the property tab composite.
648: */
649: private Composite createTabComposite() {
650: Composite result = widgetFactory
651: .createComposite(tabbedPropertyComposite
652: .getTabComposite(), SWT.NO_FOCUS);
653: result.setVisible(false);
654: result.setLayout(new FillLayout());
655: FormData data = new FormData();
656: if (hasTitleBar) {
657: data.top = new FormAttachment(tabbedPropertyComposite
658: .getTitle(), 0);
659: } else {
660: data.top = new FormAttachment(0, 0);
661: }
662: data.bottom = new FormAttachment(100, 0);
663: data.left = new FormAttachment(0, 0);
664: data.right = new FormAttachment(100, 0);
665: result.setLayoutData(data);
666: return result;
667: }
668:
669: private void setInput(IWorkbenchPart part, ISelection selection) {
670: if (selection.equals(currentSelection)) {
671: return;
672: }
673:
674: this .currentSelection = selection;
675:
676: // see if the selection provides a new contributor
677: validateRegistry(selection);
678: ITabDescriptor[] descriptors = registry.getTabDescriptors(part,
679: currentSelection);
680: // If there are no descriptors for the given input we do not need to
681: // touch the tab objects. We might reuse them for the next valid
682: // input.
683: if (descriptors.length > 0) {
684: updateTabs(descriptors);
685: }
686: // update tabs list
687: tabbedPropertyViewer.setInput(part, currentSelection);
688: int lastTabSelectionIndex = getLastTabSelection(part,
689: currentSelection);
690: Object selectedTab = tabbedPropertyViewer
691: .getElementAt(lastTabSelectionIndex);
692: selectionQueueLocked = true;
693: try {
694: if (selectedTab == null) {
695: tabbedPropertyViewer.setSelection(null);
696: } else {
697: tabbedPropertyViewer
698: .setSelection(new StructuredSelection(
699: selectedTab));
700: }
701: } finally {
702: selectionQueueLocked = false;
703: }
704: refreshTitleBar();
705: }
706:
707: /**
708: * Refresh the currently active tab.
709: */
710: public void refresh() {
711: currentTab.refresh();
712: }
713:
714: /**
715: * Get the currently active tab.
716: *
717: * @return the currently active tab.
718: */
719: public TabContents getCurrentTab() {
720: return currentTab;
721: }
722:
723: /**
724: * Handle the tab selected change event.
725: *
726: * @param tabDescriptor
727: * the new selected tab.
728: */
729: private void handleTabSelection(ITabDescriptor tabDescriptor) {
730: if (selectionQueueLocked) {
731: /*
732: * don't send tab selection events for non user changes.
733: */
734: return;
735: }
736: for (Iterator i = tabSelectionListeners.iterator(); i.hasNext();) {
737: ITabSelectionListener listener = (ITabSelectionListener) i
738: .next();
739: listener.tabSelected(tabDescriptor);
740: }
741: }
742:
743: /**
744: * Add a tab selection listener.
745: *
746: * @param listener
747: * a tab selection listener.
748: */
749: public void addTabSelectionListener(ITabSelectionListener listener) {
750: tabSelectionListeners.add(listener);
751: }
752:
753: /**
754: * Remove a tab selection listener.
755: *
756: * @param listener
757: * a tab selection listener.
758: */
759: public void removeTabSelectionListener(
760: ITabSelectionListener listener) {
761: tabSelectionListeners.remove(listener);
762: }
763:
764: /**
765: * Override the tabs with a new set of tabs. The tab list is obtained from
766: * the {@link AbstractOverridableTabListPropertySection} by the
767: * {@link IOverridableTabListContentProvider}.
768: */
769: public void overrideTabs() {
770: if (tabListContentProvider instanceof IOverridableTabListContentProvider) {
771: IOverridableTabListContentProvider overridableTabListContentProvider = (IOverridableTabListContentProvider) tabListContentProvider;
772: overridableTabListContentProvider.overrideTabs();
773: }
774: }
775:
776: /**
777: * Get the widget factory.
778: *
779: * @return the widget factory.
780: */
781: public TabbedPropertySheetWidgetFactory getWidgetFactory() {
782: return widgetFactory;
783: }
784:
785: /**
786: * Update the title bar of the contributor has a label provider.
787: */
788: private void refreshTitleBar() {
789: if (hasTitleBar) {
790: TabbedPropertyTitle title = tabbedPropertyComposite
791: .getTitle();
792: if (currentTab == null) {
793: /**
794: * No tabs are shown so hide the title bar, otherwise you see
795: * "No properties available" and a title bar for the selection.
796: */
797: title.setTitle(null, null);
798: } else {
799: String text = registry.getLabelProvider().getText(
800: currentSelection);
801: Image image = registry.getLabelProvider().getImage(
802: currentSelection);
803: title.setTitle(text, image);
804: }
805: }
806: }
807:
808: /**
809: * @see org.eclipse.jface.viewers.ILabelProviderListener#labelProviderChanged(org.eclipse.jface.viewers.LabelProviderChangedEvent)
810: */
811: public void labelProviderChanged(LabelProviderChangedEvent event) {
812: refreshTitleBar();
813: }
814:
815: /**
816: * Retrieve the contributor from the selection.
817: *
818: * @param object -
819: * the selected element
820: * @return the TabbedPropertySheetPageContributor or null if not applicable
821: */
822: private ITabbedPropertySheetPageContributor getTabbedPropertySheetPageContributor(
823: Object object) {
824: if (object instanceof ITabbedPropertySheetPageContributor) {
825: return (ITabbedPropertySheetPageContributor) object;
826: }
827:
828: if (object instanceof IAdaptable
829: && ((IAdaptable) object)
830: .getAdapter(ITabbedPropertySheetPageContributor.class) != null) {
831: return (ITabbedPropertySheetPageContributor) (((IAdaptable) object)
832: .getAdapter(ITabbedPropertySheetPageContributor.class));
833: }
834:
835: if (Platform.getAdapterManager().hasAdapter(object,
836: ITabbedPropertySheetPageContributor.class.getName())) {
837: return (ITabbedPropertySheetPageContributor) Platform
838: .getAdapterManager().loadAdapter(
839: object,
840: ITabbedPropertySheetPageContributor.class
841: .getName());
842: }
843:
844: return null;
845: }
846:
847: /**
848: * The workbench part creates this instance of the TabbedPropertySheetPage
849: * and implements ITabbedPropertySheetPageContributor which is unique
850: * contributor id. This unique contributor id is used to load a registry
851: * with the extension point This id matches the registry.
852: * <p>
853: * It is possible for elements in a selection to implement
854: * ITabbedPropertySheetPageContributor to provide a different contributor id
855: * and thus a differenent registry.
856: *
857: * @param selection
858: * the current selection in the active workbench part.
859: */
860: private void validateRegistry(ISelection selection) {
861: if (selection == null) {
862: return;
863: }
864:
865: if (!(selection instanceof IStructuredSelection)) {
866: return;
867: }
868:
869: IStructuredSelection structuredSelection = (IStructuredSelection) selection;
870: if (structuredSelection.size() == 0) {
871: return;
872: }
873:
874: ITabbedPropertySheetPageContributor newContributor = getTabbedPropertySheetPageContributor(structuredSelection
875: .getFirstElement());
876:
877: if (newContributor == null) {
878: /**
879: * selection does not implement or adapt ITabbedPropertySheetPageContributor.
880: */
881: newContributor = contributor;
882: }
883:
884: String selectionContributorId = newContributor
885: .getContributorId();
886: if (selectionContributorId.equals(currentContributorId)) {
887: /**
888: * selection has the same contributor id as current, so leave
889: * existing registry.
890: */
891: return;
892: }
893:
894: /**
895: * Selection implements ITabbedPropertySheetPageContributor different
896: * than current contributor id, so make sure all elements implement the
897: * new id. If all contributor id do not match, then fall back to default
898: * contributor from the workbench part.
899: */
900: Iterator i = structuredSelection.iterator();
901: i.next();
902: while (i.hasNext()) {
903: newContributor = getTabbedPropertySheetPageContributor(i
904: .next());
905: if (newContributor == null
906: || !newContributor.getContributorId().equals(
907: selectionContributorId)) {
908: /**
909: * fall back to use the default contributor id from the
910: * workbench part.
911: */
912: if (selectionContributor != null) {
913: disposeContributor();
914: currentContributorId = contributor
915: .getContributorId();
916: initContributor(currentContributorId);
917: }
918: return;
919: }
920: }
921:
922: /**
923: * All the elements in the selection implement a new contributor id, so
924: * use that id.
925: */
926: disposeContributor();
927: currentContributorId = selectionContributorId;
928: initContributor(currentContributorId);
929: overrideActionBars();
930: }
931:
932: /**
933: * Override the action bars for the selection based contributor.
934: */
935: private void overrideActionBars() {
936: if (registry.getActionProvider() != null) {
937: IActionProvider actionProvider = registry
938: .getActionProvider();
939: actionProvider.setActionBars(contributor, getSite()
940: .getActionBars());
941: }
942: }
943:
944: }
|