### Eclipse Workspace Patch 1.0 #P org.eclipse.ui.views.properties.tabbed Index: src/org/eclipse/ui/internal/views/properties/tabbed/view/Tab.java =================================================================== RCS file: src/org/eclipse/ui/internal/views/properties/tabbed/view/Tab.java diff -N src/org/eclipse/ui/internal/views/properties/tabbed/view/Tab.java --- src/org/eclipse/ui/internal/views/properties/tabbed/view/Tab.java 17 Apr 2006 19:03:55 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,240 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2001, 2006 IBM Corporation and others. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * IBM Corporation - initial API and implementation - *******************************************************************************/ -package org.eclipse.ui.internal.views.properties.tabbed.view; - -import org.eclipse.core.runtime.ISafeRunnable; -import org.eclipse.core.runtime.Platform; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.swt.SWT; -import org.eclipse.swt.layout.FillLayout; -import org.eclipse.swt.layout.GridData; -import org.eclipse.swt.layout.GridLayout; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.ui.IWorkbenchPart; -import org.eclipse.ui.views.properties.tabbed.ISection; -import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; - -/** - * A property tab is composed by one or more property sections and is used to - * categorize sections. - * - * @author Anthony Hunter - */ -public class Tab { - - private ISection[] sections; - - private boolean controlsCreated; - - Tab() { - controlsCreated = false; - } - - /** - * Retrieve a numbered index for the section. - * @param section the section. - * @return the section index. - */ - public int getSectionIndex(ISection section) { - for (int i = 0; i < sections.length; i++) { - if (section == sections[i]) { - return i; - } - } - return -1; - } - - /** - * Retrieve the section at a numbered index. - * @param i a numbered index. - * @return the section. - */ - public ISection getSectionAtIndex(int i) { - if (i >= 0 && i < sections.length) { - return sections[i]; - } - return null; - } - - /** - * Retrieve the sections on the tab. - * - * @return the sections on the tab. - */ - public ISection[] getSections() { - return sections; - } - - /** - * Creates page's sections controls. - * - * @param parent - * @param page - */ - public void createControls(Composite parent, - final TabbedPropertySheetPage page) { - Composite pageComposite = page.getWidgetFactory().createComposite( - parent, SWT.NO_FOCUS); - GridLayout layout = new GridLayout(); - layout.marginWidth = 0; - layout.marginHeight = 0; - layout.verticalSpacing = 0; - pageComposite.setLayout(layout); - - for (int i = 0; i < sections.length; i++) { - final ISection section = sections[i]; - final Composite sectionComposite = page.getWidgetFactory() - .createComposite(pageComposite, SWT.NO_FOCUS); - sectionComposite.setLayout(new FillLayout()); - int style = (section.shouldUseExtraSpace()) ? GridData.FILL_BOTH - : GridData.FILL_HORIZONTAL; - GridData data = new GridData(style); - data.heightHint = section.getMinimumHeight(); - sectionComposite.setLayoutData(data); - - ISafeRunnable runnable = new ISafeRunnable() { - - public void run() - throws Exception { - section.createControls(sectionComposite, page); - } - - public void handleException(Throwable exception) { - /* not used */ - } - }; - Platform.run(runnable); - } - controlsCreated = true; - } - - /** - * Dispose of page's sections controls. - */ - public void dispose() { - for (int i = 0; i < sections.length; i++) { - final ISection section = sections[i]; - ISafeRunnable runnable = new ISafeRunnable() { - - public void run() - throws Exception { - section.dispose(); - } - - public void handleException(Throwable exception) { - /* not used */ - } - }; - Platform.run(runnable); - } - } - - /** - * Sends the lifecycle event to the page's sections. - */ - public void aboutToBeShown() { - for (int i = 0; i < sections.length; i++) { - final ISection section = sections[i]; - ISafeRunnable runnable = new ISafeRunnable() { - - public void run() - throws Exception { - section.aboutToBeShown(); - } - - public void handleException(Throwable exception) { - /* not used */ - } - }; - Platform.run(runnable); - } - } - - /** - * Sends the lifecycle event to the page's sections. - */ - public void aboutToBeHidden() { - for (int i = 0; i < sections.length; i++) { - final ISection section = sections[i]; - ISafeRunnable runnable = new ISafeRunnable() { - - public void run() - throws Exception { - section.aboutToBeHidden(); - } - - public void handleException(Throwable exception) { - /* not used */ - } - }; - Platform.run(runnable); - } - } - - /** - * Sets page's sections input objects. - * - * @param part - * @param selection - */ - public void setInput(final IWorkbenchPart part, final ISelection selection) { - for (int i = 0; i < sections.length; i++) { - final ISection section = sections[i]; - ISafeRunnable runnable = new ISafeRunnable() { - - public void run() - throws Exception { - section.setInput(part, selection); - } - - public void handleException(Throwable throwable) { - throwable.printStackTrace(); - } - }; - Platform.run(runnable); - } - } - - void setSections(ISection[] sections) { - this.sections = sections; - } - - /** - * - * @return true if controls have been created. - */ - public boolean controlsHaveBeenCreated() { - return controlsCreated; - } - - /** - * If controls have been created, refresh all sections on the page. - */ - public void refresh() { - if (controlsCreated) { - for (int i = 0; i < sections.length; i++) { - final ISection section = sections[i]; - ISafeRunnable runnable = new ISafeRunnable() { - - public void run() - throws Exception { - section.refresh(); - } - - public void handleException(Throwable throwable) { - throwable.printStackTrace(); - } - }; - Platform.run(runnable); - } - } - } -} Index: src/org/eclipse/ui/internal/views/properties/tabbed/view/TabListContentProvider.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.views.properties.tabbed/src/org/eclipse/ui/internal/views/properties/tabbed/view/TabListContentProvider.java,v retrieving revision 1.1 diff -u -r1.1 TabListContentProvider.java --- src/org/eclipse/ui/internal/views/properties/tabbed/view/TabListContentProvider.java 17 Apr 2006 19:03:55 -0000 1.1 +++ src/org/eclipse/ui/internal/views/properties/tabbed/view/TabListContentProvider.java 31 May 2007 10:32:07 -0000 @@ -14,7 +14,7 @@ import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.Viewer; -import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage; /** @@ -22,19 +22,21 @@ * tabbed property sheet page's list of tabs. * * @author Anthony Hunter + * @version 30 May 2007 */ public class TabListContentProvider implements IStructuredContentProvider { - private TabbedPropertyRegistry registry; + private TabbedPropertySheetPage tabbedPropertyPage; - private IWorkbenchPart currentPart; - /** * Constructor for TabListContentProvider. + * This content provider always returns the "current tabs" of the given + * property page + * #see {@link TabbedPropertySheetPage.#getCurrentTabs()} */ - public TabListContentProvider(TabbedPropertyRegistry registry) { - this.registry = registry; + public TabListContentProvider(TabbedPropertySheetPage tabbedPropertyPage) { + this.tabbedPropertyPage = tabbedPropertyPage; } /** @@ -42,21 +44,19 @@ */ public Object[] getElements(Object inputElement) { Assert.isTrue(inputElement instanceof ISelection); - return registry - .getTabDescriptors(currentPart, (ISelection) inputElement); + return tabbedPropertyPage.getCurrentTabs(); } /** * @see org.eclipse.jface.viewers.IContentProvider#dispose() */ public void dispose() { - /* not used */ + tabbedPropertyPage = null; } /** * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object) */ public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { - this.currentPart = ((TabbedPropertyViewer)viewer).getWorkbenchPart(); } } Index: src/org/eclipse/ui/internal/views/properties/tabbed/view/TabDescriptor.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.views.properties.tabbed/src/org/eclipse/ui/internal/views/properties/tabbed/view/TabDescriptor.java,v retrieving revision 1.1 diff -u -r1.1 TabDescriptor.java --- src/org/eclipse/ui/internal/views/properties/tabbed/view/TabDescriptor.java 17 Apr 2006 19:03:55 -0000 1.1 +++ src/org/eclipse/ui/internal/views/properties/tabbed/view/TabDescriptor.java 31 May 2007 10:32:07 -0000 @@ -10,22 +10,13 @@ *******************************************************************************/ package org.eclipse.ui.internal.views.properties.tabbed.view; -import com.ibm.icu.text.MessageFormat; -import java.util.ArrayList; -import java.util.Iterator; import java.util.List; -import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; import org.eclipse.swt.graphics.Image; -import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewPlugin; -import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewStatusCodes; -import org.eclipse.ui.internal.views.properties.tabbed.l10n.TabbedPropertyMessages; import org.eclipse.ui.plugin.AbstractUIPlugin; -import org.eclipse.ui.views.properties.tabbed.ISection; -import org.eclipse.ui.views.properties.tabbed.ISectionDescriptor; +import org.eclipse.ui.views.properties.tabbed.AbstractTabDescriptor; +import org.eclipse.ui.views.properties.tabbed.ITabDescriptor; import org.eclipse.ui.views.properties.tabbed.ITabItem; /** @@ -33,9 +24,10 @@ * property tabs extensions. * * @author Anthony Hunter + * @version 22 May 2007 */ -public class TabDescriptor - implements Cloneable, ITabItem { +public class TabDescriptor extends AbstractTabDescriptor + implements Cloneable, ITabItem, ITabDescriptor { private static final String ATT_ID = "id"; //$NON-NLS-1$ @@ -49,26 +41,6 @@ private static final String ATT_AFTER_TAB = "afterTab"; //$NON-NLS-1$ - private static final String TOP = "top"; //$NON-NLS-1$ - - private final static String TAB_ERROR = TabbedPropertyMessages.TabDescriptor_Tab_error; - - private String id; - - private String label; - - private Image image; - - private boolean selected; - - private boolean indented; - - private String category; - - private String afterTab; - - private List sectionDescriptors; - /** * Constructor for TabDescriptor. * @@ -76,144 +48,38 @@ * the configuration element for the tab descriptor. */ public TabDescriptor(IConfigurationElement configurationElement) { + super(); + if (configurationElement != null) { - id = configurationElement.getAttribute(ATT_ID); - label = configurationElement.getAttribute(ATT_LABEL); + String id = configurationElement.getAttribute(ATT_ID); + String label = configurationElement.getAttribute(ATT_LABEL); String imageString = configurationElement.getAttribute(ATT_IMAGE); if (imageString != null) { - image = AbstractUIPlugin + Image image = AbstractUIPlugin .imageDescriptorFromPlugin( configurationElement.getDeclaringExtension() .getNamespace(), imageString).createImage(); + if (image != null) { + setImage(image); + } } String indentedString = configurationElement .getAttribute(ATT_INDENTED); - indented = indentedString != null && indentedString.equals("true"); //$NON-NLS-1$ - category = configurationElement.getAttribute(ATT_CATEGORY); - afterTab = configurationElement.getAttribute(ATT_AFTER_TAB); + boolean indented = indentedString != null && indentedString.equals("true"); //$NON-NLS-1$ + setIndented(indented); + String category = configurationElement.getAttribute(ATT_CATEGORY); + String afterTab = configurationElement.getAttribute(ATT_AFTER_TAB); + setAfterTab(afterTab); if (id == null || label == null || category == null) { // the tab id, label and category are mandatory - log error - handleTabError(configurationElement, null); - } - } - if (getAfterTab() == null) { - afterTab = TOP; - } - sectionDescriptors = new ArrayList(5); - selected = false; - } - - /** - * Get the unique identifier for the tab. - * - * @return the unique identifier for the tab. - */ - public String getId() { - return id; - } - - /** - * Get the text label for the tab. - * - * @return the text label for the tab. - */ - public String getLabel() { - return label; - } - - /** - * Get the identifier of the tab after which this tab should be displayed. - * When two or more tabs belong to the same category, they are sorted by the - * after tab values. - * - * @return the identifier of the tab. - */ - protected String getAfterTab() { - return afterTab; - } - - /** - * Get the category this tab belongs to. - * - * @return Get the category this tab belongs to. - */ - protected String getCategory() { - return category; - } - - /** - * Returns whether the given section was added to this tab. The section can - * be appended if its tab attribute matches the tab id. The afterSection - * attribute indicates the order in which the section should be appended. - * - * @param target - * the section descriptor to append. - */ - protected boolean append(ISectionDescriptor target) { - if (!target.getTargetTab().equals(id)) { - return false; - } - - if (insertSectionDescriptor(target)) { - return true; - } - - sectionDescriptors.add(target); - return true; - } - - /** - * Insert the section descriptor into the section descriptor list. - * - * @param target - * the section descriptor to insert. - * @return true if the target descriptor was added to the - * descriptors list. - */ - private boolean insertSectionDescriptor(ISectionDescriptor target) { - if (target.getAfterSection().equals(TOP)) { - sectionDescriptors.add(0, target); - return true; - } - for (int i = 0; i < sectionDescriptors.size(); i++) { - ISectionDescriptor descriptor = (ISectionDescriptor) sectionDescriptors - .get(i); - if (target.getAfterSection().equals(descriptor.getId())) { - sectionDescriptors.add(i + 1, target); - return true; - } else { - if (descriptor.getAfterSection().equals(target.getId())) { - sectionDescriptors.add(i, target); - return true; - } + handleTabError(configurationElement.getContributor().getName(), null); } + + setId(id); + setLabel(label); + setCategory(category); } - return false; - } - - /** - * Instantiate this tab's sections. - */ - public Tab createTab() { - List sections = new ArrayList(sectionDescriptors.size()); - for (Iterator iter = sectionDescriptors.iterator(); iter.hasNext();) { - ISectionDescriptor descriptor = (ISectionDescriptor) iter.next(); - ISection section = descriptor.getSectionClass(); - sections.add(section); - } - Tab tab = new Tab(); - tab.setSections((ISection[]) sections.toArray(new ISection[sections - .size()])); - return tab; - } - - /** - * Get the list of section descriptors for the tab. - * - * @return the list of section descriptors for the tab. - */ - protected List getSectionDescriptors() { - return sectionDescriptors; + } /** @@ -221,182 +87,10 @@ * * @param sectionDescriptors * the list of section descriptors for the tab. - */ - protected void setSectionDescriptors(List sectionDescriptors) { - this.sectionDescriptors = sectionDescriptors; - } - - /** - * @see java.lang.Object#toString() - */ - public String toString() { - return getId(); - } - /** - * Handle the tab error when an issue is found loading from the - * configuration element. - * - * @param configurationElement - * the configuration element - * @param exception - * an optional CoreException - */ - private void handleTabError(IConfigurationElement configurationElement, - CoreException exception) { - String pluginId = configurationElement.getDeclaringExtension() - .getNamespace(); - String message = MessageFormat.format(TAB_ERROR, - new Object[] {pluginId}); - IStatus status = new Status(IStatus.ERROR, pluginId, - TabbedPropertyViewStatusCodes.TAB_ERROR, message, exception); - TabbedPropertyViewPlugin.getPlugin().getLog().log(status); - } - - /** - * @see java.lang.Object#equals(java.lang.Object) - */ - public boolean equals(Object object) { - if (this == object) { - return true; - } - - if (this.getClass() == object.getClass()) { - TabDescriptor descriptor = (TabDescriptor) object; - if (this.getCategory().equals(descriptor.getCategory()) - && this.getId().equals(descriptor.getId()) - && this.getSectionDescriptors().size() == descriptor - .getSectionDescriptors().size()) { - - Iterator i = this.getSectionDescriptors().iterator(); - Iterator j = descriptor.getSectionDescriptors().iterator(); - - // the order is importent here - so as long as the sizes of the - // lists are the same and id of the section at the same - // positions are the same - the lists are the same - while (i.hasNext()) { - ISectionDescriptor source = (ISectionDescriptor) i.next(); - ISectionDescriptor target = (ISectionDescriptor) j.next(); - if (!source.getId().equals(target.getId())) { - return false; - } - } - - return true; - } - - } - - return false; - } - - /** - * @see java.lang.Object#hashCode() - */ - public int hashCode() { - - int hashCode = getCategory().hashCode(); - hashCode ^= getId().hashCode(); - Iterator i = this.getSectionDescriptors().iterator(); - while (i.hasNext()) { - ISectionDescriptor section = (ISectionDescriptor) i.next(); - hashCode ^= section.getId().hashCode(); - } - return hashCode; - } - - /** - * @see java.lang.Object#clone() - */ - public Object clone() { - try { - return super.clone(); - } catch (CloneNotSupportedException exception) { - IStatus status = new Status(IStatus.ERROR, TabbedPropertyViewPlugin - .getPlugin().getBundle().getSymbolicName(), 666, exception - .getMessage(), exception); - TabbedPropertyViewPlugin.getPlugin().getLog().log(status); - } - return null; - } - - /** - * Set the image for the tab. - * - * @param image - * the image for the tab. - */ - protected void setImage(Image image) { - this.image = image; - } - - /** - * Set the indicator to determine if the tab should be displayed as - * indented. - * - * @param indented - * true if the tab should be displayed as - * indented. - */ - protected void setIndented(boolean indented) { - this.indented = indented; - } - - /** - * Set the indicator to determine if the tab should be the selected tab in - * the list. - * - * @param selected - * true if the tab should be the selected tab in - * the list. - */ - protected void setSelected(boolean selected) { - this.selected = selected; - } - - /** - * Set the text label for the tab. - * - * @param label - * the text label for the tab. - */ - protected void setLabel(String label) { - this.label = label; - } - - /** - * Get the image for the tab. - * - * @return the image for the tab. - */ - public Image getImage() { - return image; - } - - /** - * Determine if the tab is selected. - * - * @return true if the tab is selected. - */ - public boolean isSelected() { - return selected; - } - - /** - * Determine if the tab should be displayed as indented. - * - * @return true if the tab should be displayed as indented. - */ - public boolean isIndented() { - return indented; - } - - /** - * Get the text label for the tab. - * - * @return the text label for the tab. + * Made this publicly accessible to {@link TabbedPropertyRegistry} */ - public String getText() { - return label; + public void setSectionDescriptors(List aSectionDescriptors) { + super.setSectionDescriptors(aSectionDescriptors); } } Index: src/org/eclipse/ui/internal/views/properties/tabbed/view/SectionDescriptor.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.views.properties.tabbed/src/org/eclipse/ui/internal/views/properties/tabbed/view/SectionDescriptor.java,v retrieving revision 1.1 diff -u -r1.1 SectionDescriptor.java --- src/org/eclipse/ui/internal/views/properties/tabbed/view/SectionDescriptor.java 17 Apr 2006 19:03:55 -0000 1.1 +++ src/org/eclipse/ui/internal/views/properties/tabbed/view/SectionDescriptor.java 31 May 2007 10:32:07 -0000 @@ -10,7 +10,6 @@ *******************************************************************************/ package org.eclipse.ui.internal.views.properties.tabbed.view; -import com.ibm.icu.text.MessageFormat; import java.util.ArrayList; import java.util.List; @@ -19,24 +18,25 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.jface.viewers.IFilter; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewPlugin; import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewStatusCodes; import org.eclipse.ui.internal.views.properties.tabbed.l10n.TabbedPropertyMessages; +import org.eclipse.ui.views.properties.tabbed.AbstractSectionDescriptor; import org.eclipse.ui.views.properties.tabbed.ISection; -import org.eclipse.ui.views.properties.tabbed.ISectionDescriptor; import org.eclipse.ui.views.properties.tabbed.ITypeMapper; +import com.ibm.icu.text.MessageFormat; + /** * Represents the default implementation of a section descriptor on the tabbed * property sections extensions. This implementation assumes that we are * interested in selected objects in an IStructuredSelection. * * @author Anthony Hunter + * @version 21 May 2007 */ public class SectionDescriptor - implements ISectionDescriptor { + extends AbstractSectionDescriptor { private final static String SECTION_ERROR = TabbedPropertyMessages.SectionDescriptor_Section_error; @@ -56,22 +56,10 @@ private static final String ELEMENT_INPUT = "input"; //$NON-NLS-1$ - private static final String TOP = "top"; //$NON-NLS-1$ - - private String id; - - private String targetTab; - - private String afterSection; - private ArrayList inputTypes; - private TabbedPropertyRegistryClassSectionFilter classFilter; - private IFilter filter; - private int enablesFor = ENABLES_FOR_ANY; - private IConfigurationElement configurationElement; /** @@ -84,19 +72,21 @@ */ protected SectionDescriptor(IConfigurationElement configurationElement, ITypeMapper typeMapper) { + super(); + this.configurationElement = configurationElement; - classFilter = new TabbedPropertyRegistryClassSectionFilter(typeMapper); - id = getConfigurationElement().getAttribute(ATT_ID); - targetTab = getConfigurationElement().getAttribute(ATT_TARGET_TAB); - afterSection = getConfigurationElement() + setTypeMapper(typeMapper); + String id = getConfigurationElement().getAttribute(ATT_ID); + String targetTab = getConfigurationElement().getAttribute(ATT_TARGET_TAB); + String afterSection = getConfigurationElement() .getAttribute(ATT_AFTER_SECTION); if (getConfigurationElement().getAttribute(ATT_SECTION_ENABLES_FOR) != null) { String enablesForStr = getConfigurationElement().getAttribute( ATT_SECTION_ENABLES_FOR); int enablesForTest = Integer.parseInt(enablesForStr); if (enablesForTest > 0) { - enablesFor = enablesForTest; + setEnablesFor(enablesForTest); } } @@ -104,8 +94,15 @@ // the section id and tab are mandatory - log error handleSectionError(null); } - if (getAfterSection() == null) { - afterSection = TOP; + + if (afterSection != null) { + setAfterSection(afterSection); + } + if (id != null) { + setId(id); + } + if (targetTab != null) { + setTargetTab(targetTab); } } @@ -129,13 +126,6 @@ } /** - * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getId() - */ - public String getId() { - return id; - } - - /** * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getFilter() */ public IFilter getFilter() { @@ -153,39 +143,6 @@ } /** - * Retrieves the value for section enablement which is a precise number of - * items selected. For example: enablesFor=" 4" enables the action only when - * 4 items are selected. If not specified, enable for all selections. - * - * @return the value for section enablement. - */ - public int getEnablesFor() { - return enablesFor; - } - - /** - * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getTargetTab() - */ - public String getTargetTab() { - return targetTab; - } - - /** - * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#appliesTo(org.eclipse.ui.IWorkbenchPart, - * org.eclipse.jface.viewers.ISelection) - */ - public boolean appliesTo(IWorkbenchPart part, ISelection selection) { - return classFilter.appliesToSelection(this, selection); - } - - /** - * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getAfterSection() - */ - public String getAfterSection() { - return afterSection; - } - - /** * Creates an instance of a section described by this descriptor * * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getSectionClass() @@ -222,13 +179,6 @@ } /** - * @see java.lang.Object#toString() - */ - public String toString() { - return getId(); - } - - /** * @return Returns the configurationElement. */ private IConfigurationElement getConfigurationElement() { Index: src/org/eclipse/ui/internal/views/properties/tabbed/view/TabbedPropertyRegistry.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.views.properties.tabbed/src/org/eclipse/ui/internal/views/properties/tabbed/view/TabbedPropertyRegistry.java,v retrieving revision 1.1.2.1 diff -u -r1.1.2.1 TabbedPropertyRegistry.java --- src/org/eclipse/ui/internal/views/properties/tabbed/view/TabbedPropertyRegistry.java 6 Jul 2006 17:12:15 -0000 1.1.2.1 +++ src/org/eclipse/ui/internal/views/properties/tabbed/view/TabbedPropertyRegistry.java 31 May 2007 10:32:07 -0000 @@ -10,37 +10,29 @@ *******************************************************************************/ package org.eclipse.ui.internal.views.properties.tabbed.view; -import com.ibm.icu.text.MessageFormat; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.Iterator; import java.util.List; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.IConfigurationElement; -import org.eclipse.core.runtime.IExtensionPoint; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.*; import org.eclipse.jface.viewers.ILabelProvider; import org.eclipse.jface.viewers.ISelection; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewPlugin; import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewStatusCodes; import org.eclipse.ui.internal.views.properties.tabbed.l10n.TabbedPropertyMessages; -import org.eclipse.ui.views.properties.tabbed.IActionProvider; -import org.eclipse.ui.views.properties.tabbed.ISectionDescriptor; -import org.eclipse.ui.views.properties.tabbed.ISectionDescriptorProvider; -import org.eclipse.ui.views.properties.tabbed.ITypeMapper; +import org.eclipse.ui.views.properties.tabbed.*; + +import com.ibm.icu.text.MessageFormat; /** * Provides information about the tabbed property extension points. Each tabbed * property registry is associated with a unique contributor ID. * * @author Anthony Hunter + * @version 22 May 2007 */ -public class TabbedPropertyRegistry { +public class TabbedPropertyRegistry implements ITabDescriptorProvider { private final static String NO_TAB_ERROR = TabbedPropertyMessages.TabbedPropertyRegistry_Non_existing_tab; @@ -69,8 +61,6 @@ private static final String ATT_ACTION_PROVIDER = "actionProvider"; //$NON-NLS-1$ - private static final String TOP = "top"; //$NON-NLS-1$ - protected String contributorId; protected IConfigurationElement contributorConfigurationElement; @@ -218,29 +208,17 @@ } /** - * Returns the index of the given element in the array. - */ - private int getIndex(Object[] array, Object target) { - for (int i = 0; i < array.length; i++) { - if (array[i].equals(target)) { - return i; - } - } - return -1; // should never happen - } - - /** * Returns property tab descriptors for the given contributor id and object * input. The descriptors are sorted using the afterPage attribute. */ - public TabDescriptor[] getTabDescriptors(IWorkbenchPart part, + public ITabDescriptor[] getTabDescriptors(IWorkbenchPart part, ISelection selection) { if (selection == null || selection.isEmpty()) { return EMPTY_DESCRIPTOR_ARRAY; } TabDescriptor[] allDescriptors = getAllTabDescriptors(); - TabDescriptor[] result = filterTabDescriptors(allDescriptors, part, + ITabDescriptor[] result = filterTabDescriptors(allDescriptors, part, selection); return result; } @@ -293,10 +271,7 @@ if (tabDescriptors == null) { List temp = readTabDescriptors(); populateWithSectionDescriptors(temp); - temp = sortTabDescriptorsByCategory(temp); - temp = sortTabDescriptorsByAfterTab(temp); - tabDescriptors = (TabDescriptor[]) temp - .toArray(new TabDescriptor[temp.size()]); + tabDescriptors = (TabDescriptor[]) temp.toArray(new TabDescriptor[temp.size()]); } return tabDescriptors; } @@ -313,7 +288,7 @@ IConfigurationElement[] tabs = extension.getChildren(ELEMENT_TAB); for (int j = 0; j < tabs.length; j++) { IConfigurationElement tab = tabs[j]; - TabDescriptor descriptor = new TabDescriptor(tab); + ITabDescriptor descriptor = new TabDescriptor(tab); result.add(descriptor); } } @@ -342,7 +317,7 @@ protected void appendToTabDescriptor(ISectionDescriptor section, List aTabDescriptors) { for (Iterator i = aTabDescriptors.iterator(); i.hasNext();) { - TabDescriptor tab = (TabDescriptor) i.next(); + AbstractTabDescriptor tab = (AbstractTabDescriptor) i.next(); if (tab.append(section)) { return; } @@ -357,76 +332,6 @@ } /** - * Sorts the tab descriptors in the given list according to category. - */ - protected List sortTabDescriptorsByCategory(List descriptors) { - Collections.sort(descriptors, new Comparator() { - - public int compare(Object arg0, Object arg1) { - TabDescriptor one = (TabDescriptor) arg0; - TabDescriptor two = (TabDescriptor) arg1; - String categoryOne = one.getCategory(); - String categoryTwo = two.getCategory(); - int categoryOnePosition = getIndex(propertyCategories.toArray(), - categoryOne); - int categoryTwoPosition = getIndex(propertyCategories.toArray(), - categoryTwo); - return categoryOnePosition - categoryTwoPosition; - } - }); - return descriptors; - } - - /** - * Sorts the tab descriptors in the given list according to afterTab. - */ - protected List sortTabDescriptorsByAfterTab(List tabs) { - if (tabs.size() == 0 || propertyCategories == null) { - return tabs; - } - List sorted = new ArrayList(); - int categoryIndex = 0; - for (int i = 0; i < propertyCategories.size(); i++) { - List categoryList = new ArrayList(); - String category = (String)propertyCategories.get(i); - int topOfCategory = categoryIndex; - int endOfCategory = categoryIndex; - while (endOfCategory < tabs.size() - && ((TabDescriptor) tabs.get(endOfCategory)).getCategory() - .equals(category)) { - endOfCategory++; - } - for (int j = topOfCategory; j < endOfCategory; j++) { - TabDescriptor tab = (TabDescriptor) tabs.get(j); - if (tab.getAfterTab().equals(TOP)) { - categoryList.add(0, tabs.get(j)); - } else { - categoryList.add(tabs.get(j)); - } - } - Collections.sort(categoryList, new Comparator() { - - public int compare(Object arg0, Object arg1) { - TabDescriptor one = (TabDescriptor) arg0; - TabDescriptor two = (TabDescriptor) arg1; - if (two.getAfterTab().equals(one.getId())) { - return -1; - } else if (one.getAfterTab().equals(two.getId())) { - return 1; - } else { - return 0; - } - } - }); - for (int j = 0; j < categoryList.size(); j++) { - sorted.add(categoryList.get(j)); - } - categoryIndex = endOfCategory; - } - return sorted; - } - - /** * Gets the type mapper for the contributor. * * @return the type mapper for the contributor. @@ -452,8 +357,8 @@ public IActionProvider getActionProvider() { return actionProvider; } - /** + * Sets the section descriptor provider for the contributor. * * @param sectionDescriptorProvider Index: src/org/eclipse/ui/internal/views/properties/tabbed/view/TabbedPropertyRegistryClassSectionFilter.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.views.properties.tabbed/src/org/eclipse/ui/internal/views/properties/tabbed/view/TabbedPropertyRegistryClassSectionFilter.java,v retrieving revision 1.1 diff -u -r1.1 TabbedPropertyRegistryClassSectionFilter.java --- src/org/eclipse/ui/internal/views/properties/tabbed/view/TabbedPropertyRegistryClassSectionFilter.java 17 Apr 2006 19:03:55 -0000 1.1 +++ src/org/eclipse/ui/internal/views/properties/tabbed/view/TabbedPropertyRegistryClassSectionFilter.java 31 May 2007 10:32:08 -0000 @@ -29,6 +29,7 @@ * IStructuredSelection and filtering is based on class. * * @author Anthony Hunter + * @version 15 May 2007 */ public class TabbedPropertyRegistryClassSectionFilter { @@ -37,7 +38,7 @@ /** * constructor. */ - protected TabbedPropertyRegistryClassSectionFilter(ITypeMapper typeMapper) { + public TabbedPropertyRegistryClassSectionFilter(ITypeMapper typeMapper) { super(); this.typeMapper = typeMapper; } @@ -46,7 +47,7 @@ * Verifies if the property section extension represented by sectionElement * applies to the given input. */ - protected boolean appliesToSelection(ISectionDescriptor descriptor, + public boolean appliesToSelection(ISectionDescriptor descriptor, ISelection selection) { if (selection instanceof IStructuredSelection Index: src/org/eclipse/ui/views/properties/tabbed/ITabSelectionListener.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.views.properties.tabbed/src/org/eclipse/ui/views/properties/tabbed/ITabSelectionListener.java,v retrieving revision 1.2 diff -u -r1.2 ITabSelectionListener.java --- src/org/eclipse/ui/views/properties/tabbed/ITabSelectionListener.java 17 Apr 2006 18:56:22 -0000 1.2 +++ src/org/eclipse/ui/views/properties/tabbed/ITabSelectionListener.java 31 May 2007 10:32:08 -0000 @@ -12,11 +12,14 @@ import org.eclipse.ui.internal.views.properties.tabbed.view.TabDescriptor; + /** * A listener interested in tab selection events that occur for the tabbed * property sheet page. * * @author Anthony Hunter + * @version 21 May 2007 + * @deprecated use {@link ITabSelectionListener2} instead */ public interface ITabSelectionListener { Index: src/org/eclipse/ui/views/properties/tabbed/TabbedPropertySheetPage.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.views.properties.tabbed/src/org/eclipse/ui/views/properties/tabbed/TabbedPropertySheetPage.java,v retrieving revision 1.6.2.3 diff -u -r1.6.2.3 TabbedPropertySheetPage.java --- src/org/eclipse/ui/views/properties/tabbed/TabbedPropertySheetPage.java 7 Jul 2006 15:07:16 -0000 1.6.2.3 +++ src/org/eclipse/ui/views/properties/tabbed/TabbedPropertySheetPage.java 31 May 2007 10:32:08 -0000 @@ -10,25 +10,12 @@ *******************************************************************************/ package org.eclipse.ui.views.properties.tabbed; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; import org.eclipse.core.runtime.IAdaptable; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.action.IAction; -import org.eclipse.jface.viewers.ILabelProviderListener; -import org.eclipse.jface.viewers.ISelection; -import org.eclipse.jface.viewers.ISelectionChangedListener; -import org.eclipse.jface.viewers.IStructuredContentProvider; -import org.eclipse.jface.viewers.IStructuredSelection; -import org.eclipse.jface.viewers.LabelProvider; -import org.eclipse.jface.viewers.LabelProviderChangedEvent; -import org.eclipse.jface.viewers.SelectionChangedEvent; -import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.*; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; @@ -40,21 +27,9 @@ import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; -import org.eclipse.ui.IActionBars; -import org.eclipse.ui.IEditorPart; -import org.eclipse.ui.IPartListener; -import org.eclipse.ui.IViewPart; -import org.eclipse.ui.IWorkbenchPart; -import org.eclipse.ui.IWorkbenchWindow; +import org.eclipse.ui.*; import org.eclipse.ui.actions.ActionFactory; -import org.eclipse.ui.internal.views.properties.tabbed.view.Tab; -import org.eclipse.ui.internal.views.properties.tabbed.view.TabDescriptor; -import org.eclipse.ui.internal.views.properties.tabbed.view.TabListContentProvider; -import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyComposite; -import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyRegistry; -import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyRegistryFactory; -import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyTitle; -import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyViewer; +import org.eclipse.ui.internal.views.properties.tabbed.view.*; import org.eclipse.ui.part.IContributedContentsView; import org.eclipse.ui.part.Page; import org.eclipse.ui.views.properties.IPropertySheetPage; @@ -64,6 +39,7 @@ * A property sheet page that provides a tabbed UI. * * @author Anthony Hunter + * @version 31 May 2007 */ public class TabbedPropertySheetPage extends Page @@ -94,7 +70,9 @@ private TabbedPropertyViewer tabbedPropertyViewer; - private Tab currentTab; + private TabContents currentTab; + + private ITabDescriptor[] currentTabs; private Map descriptorToTab; @@ -105,11 +83,14 @@ private boolean selectionQueueLocked; private List tabSelectionListeners; + private List tabSelectionListeners2; private IWorkbenchWindow cachedWorkbenchWindow; private boolean hasTitleBar; + private TabDescriptorProviderManager tabDescriptorManager; + /** * a listener that is interested in part activation events. */ @@ -132,6 +113,8 @@ } }; + + private class TabbedPropertySheetPageContributorFromSelection implements ITabbedPropertySheetPageContributor { @@ -165,8 +148,8 @@ extends LabelProvider { public String getText(Object element) { - if (element instanceof TabDescriptor) { - return ((TabDescriptor) element).getLabel(); + if (element instanceof AbstractTabDescriptor) { + return ((ITabDescriptor) element).getLabel(); } return null; } @@ -184,8 +167,8 @@ public void selectionChanged(SelectionChangedEvent event) { IStructuredSelection selection = (IStructuredSelection) event .getSelection(); - Tab tab = null; - TabDescriptor descriptor = (TabDescriptor) selection + TabContents tab = null; + ITabDescriptor descriptor = (ITabDescriptor) selection .getFirstElement(); if (descriptor == null) { @@ -195,7 +178,7 @@ // create tab if necessary // can not cache based on the id - tabs may have the same id, // but different section depending on the selection - tab = (Tab) descriptorToTab.get(descriptor); + tab = (TabContents) descriptorToTab.get(descriptor); if (tab != currentTab) { hideTab(currentTab); @@ -234,7 +217,7 @@ /** * Shows the given tab. */ - private void showTab(Tab target) { + private void showTab(TabContents target) { if (target != null) { Composite tabComposite = (Composite) tabToComposite.get(target); if (tabComposite != null) { @@ -252,7 +235,7 @@ /** * Hides the given tab. */ - private void hideTab(Tab target) { + private void hideTab(TabContents target) { if (target != null) { Composite tabComposite = (Composite) tabToComposite.get(target); if (tabComposite != null) { @@ -275,7 +258,8 @@ contributor = tabbedPropertySheetPageContributor; tabToComposite = new HashMap(); selectionQueue = new ArrayList(10); - tabSelectionListeners = new ArrayList(); + tabSelectionListeners2 = new ArrayList(); + tabDescriptorManager = new TabDescriptorProviderManager(); initContributor(contributor.getContributorId()); } @@ -382,6 +366,8 @@ */ private void initContributor(String contributorId) { descriptorToTab = new HashMap(); + TabbedPropertyRegistry oldRegistry = registry; + if (contributor.getContributorId().equals(contributorId)) { /** * default contributor from the workbench part. @@ -397,6 +383,11 @@ registry = TabbedPropertyRegistryFactory.getInstance() .createRegistry(selectionContributor); } + if (oldRegistry != null && !oldRegistry.equals(registry)) { + tabDescriptorManager.removeTabDescriptorProvider(oldRegistry); + } + tabDescriptorManager.insertTabDescriptorProvider(0, registry); + currentContributorId = contributorId; tabListContentProvider = getTabListContentProvider(); hasTitleBar = registry.getLabelProvider() != null; @@ -420,7 +411,7 @@ * @return the tab list content provider for the contributor. */ protected IStructuredContentProvider getTabListContentProvider() { - return new TabListContentProvider(registry); + return new TabListContentProvider(this); } /** @@ -543,7 +534,7 @@ } /** - * Stores the current tab label in the selection queue. Tab labels are used + * Stores the current tab label in the selection queue. TabContents labels are used * to carry the tab context from one input object to another. The queue * specifies the selection priority. So if the first tab in the queue is not * available for the input we try the second tab and so on. If none of the @@ -579,7 +570,7 @@ private void disposeTabs(Collection tabs) { for (Iterator iter = tabs.iterator(); iter.hasNext();) { - Tab tab = (Tab) iter.next(); + TabContents tab = (TabContents) iter.next(); Composite composite = (Composite) tabToComposite.remove(tab); tab.dispose(); if (composite != null) { @@ -589,10 +580,10 @@ } /** - * Returns the last known selected tab for the given input. + * Returns the last known selected tab for the current input */ - private int getLastTabSelection(IWorkbenchPart part, ISelection input) { - TabDescriptor[] descriptors = registry.getTabDescriptors(part, input); + private int getLastTabSelection() { + ITabDescriptor[] descriptors = currentTabs; if (descriptors.length != 0) { for (Iterator iter = selectionQueue.iterator(); iter.hasNext();) { String text = (String) iter.next(); @@ -612,18 +603,18 @@ * disposed. If the current visible tab will not be reused (i.e. will be * disposed) we have to send it an aboutToBeHidden() message. */ - protected void updateTabs(TabDescriptor[] descriptors) { + protected void updateTabs(ITabDescriptor[] descriptors) { Map newTabs = new HashMap(descriptors.length * 2); boolean disposingCurrentTab = (currentTab != null); for (int i = 0; i < descriptors.length; i++) { - Tab tab = (Tab) descriptorToTab.remove(descriptors[i]); + TabContents tab = (TabContents) descriptorToTab.remove(descriptors[i]); if (tab != null && tab.controlsHaveBeenCreated()) { if (tab == currentTab) { disposingCurrentTab = false; } } else { - tab = (descriptors[i]).createTab(); + tab = createTab(descriptors[i]); } newTabs.put(descriptors[i], tab); @@ -641,6 +632,15 @@ } /** + * Creates a new {@link TabContents} for the given tabDescriptor + * @param aDescriptor the descriptor to create the new TabContents for + * @return the new TabContents + */ + protected TabContents createTab(ITabDescriptor tabDescriptor) { + return tabDescriptor.createTab(); + } + + /** * Helper method for creating property tab composites. */ private Composite createTabComposite() { @@ -670,17 +670,19 @@ // see if the selection provides a new contributor validateRegistry(selection); - TabDescriptor[] descriptors = registry.getTabDescriptors(part, - currentSelection); + ITabDescriptor[] descriptors = getTabDescriptorsForSelection(part, currentSelection); // If there are no descriptors for the given input we do not need to // touch the tab objects. We might reuse them for the next valid // input. if (descriptors.length > 0) { updateTabs(descriptors); } + // update the content provider, which must return exactly the above descriptors + currentTabs = descriptors; + // update tabs list tabbedPropertyViewer.setInput(part, currentSelection); - int lastTabSelectionIndex = getLastTabSelection(part, currentSelection); + int lastTabSelectionIndex = getLastTabSelection(); Object selectedTab = tabbedPropertyViewer .getElementAt(lastTabSelectionIndex); selectionQueueLocked = true; @@ -698,6 +700,19 @@ } /** + * Returns the {@link ITabDescriptor} applicable to the given part and selection. + * These descriptors will be used and shown in the property sheet. + * @param part + * @param currentSelection + * @return The tab descriptors for the given selection + */ + protected ITabDescriptor[] getTabDescriptorsForSelection(IWorkbenchPart part, ISelection currentSelection) { + ITabDescriptor[] descriptors = tabDescriptorManager.getTabDescriptors(part, + currentSelection); + return descriptors; + } + + /** * Refresh the currently active tab. */ public void refresh() { @@ -709,25 +724,39 @@ * * @return the currently active tab. */ - public Tab getCurrentTab() { + public TabContents getCurrentTab() { return currentTab; } /** + * @return Returns the descriptors for the currently used tabs + */ + public ITabDescriptor[] getCurrentTabs() { + return currentTabs; + } + + /** * Handle the tab selected change event. * * @param tabDescriptor * the new selected tab. */ - private void handleTabSelection(TabDescriptor tabDescriptor) { + private void handleTabSelection(ITabDescriptor tabDescriptor) { if (selectionQueueLocked) { /* * don't send tab selection events for non user changes. */ return; } - for (Iterator i = tabSelectionListeners.iterator(); i.hasNext();) { - ITabSelectionListener listener = (ITabSelectionListener) i.next(); + if (tabSelectionListeners != null && tabDescriptor instanceof TabDescriptor) { + for (Iterator i = tabSelectionListeners.iterator(); i.hasNext();) { + ITabSelectionListener listener = (ITabSelectionListener) i.next(); + listener.tabSelected((TabDescriptor) tabDescriptor); + } + } + + for (Iterator i = tabSelectionListeners2.iterator(); i.hasNext();) { + ITabSelectionListener2 listener = (ITabSelectionListener2) i.next(); listener.tabSelected(tabDescriptor); } } @@ -737,8 +766,12 @@ * * @param listener * a tab selection listener. + * @deprecated use {@link #addTabSelectionListener(ITabSelectionListener2)} instead */ public void addTabSelectionListener(ITabSelectionListener listener) { + if (tabSelectionListeners == null) { + tabSelectionListeners = new ArrayList(); + } tabSelectionListeners.add(listener); } @@ -747,9 +780,33 @@ * * @param listener * a tab selection listener. + * @deprecated use {@link #removeTabSelectionListener(ITabSelectionListener2)} */ public void removeTabSelectionListener(ITabSelectionListener listener) { tabSelectionListeners.remove(listener); + if (tabSelectionListeners.isEmpty()) { + tabSelectionListeners = null; + } + } + + /** + * Add a tab selection listener. + * + * @param listener + * a tab selection listener. + */ + public void addTabSelectionListener(ITabSelectionListener2 listener) { + tabSelectionListeners2.add(listener); + } + + /** + * Remove a tab selection listener. + * + * @param listener + * a tab selection listener. + */ + public void removeTabSelectionListener(ITabSelectionListener2 listener) { + tabSelectionListeners2.remove(listener); } /** Index: src/org/eclipse/ui/views/properties/tabbed/TabContents.java =================================================================== RCS file: src/org/eclipse/ui/views/properties/tabbed/TabContents.java diff -N src/org/eclipse/ui/views/properties/tabbed/TabContents.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/views/properties/tabbed/TabContents.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,239 @@ +/******************************************************************************* + * Copyright (c) 2001, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.views.properties.tabbed; + +import org.eclipse.core.runtime.ISafeRunnable; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.swt.SWT; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.IWorkbenchPart; + +/** + * A property tab is composed by one or more property sections and is used to + * categorize sections. + * + * @author Anthony Hunter + * @version 14 May 2007 + */ +public class TabContents { + + private ISection[] sections; + + private boolean controlsCreated; + + public TabContents() { + controlsCreated = false; + } + + /** + * Retrieve a numbered index for the section. + * @param section the section. + * @return the section index. + */ + public int getSectionIndex(ISection section) { + for (int i = 0; i < sections.length; i++) { + if (section == sections[i]) { + return i; + } + } + return -1; + } + + /** + * Retrieve the section at a numbered index. + * @param i a numbered index. + * @return the section. + */ + public ISection getSectionAtIndex(int i) { + if (i >= 0 && i < sections.length) { + return sections[i]; + } + return null; + } + + /** + * Retrieve the sections on the tab. + * + * @return the sections on the tab. + */ + public ISection[] getSections() { + return sections; + } + + /** + * Creates page's sections controls. + * + * @param parent + * @param page + */ + public void createControls(Composite parent, + final TabbedPropertySheetPage page) { + Composite pageComposite = page.getWidgetFactory().createComposite( + parent, SWT.NO_FOCUS); + GridLayout layout = new GridLayout(); + layout.marginWidth = 0; + layout.marginHeight = 0; + layout.verticalSpacing = 0; + pageComposite.setLayout(layout); + + for (int i = 0; i < sections.length; i++) { + final ISection section = sections[i]; + final Composite sectionComposite = page.getWidgetFactory() + .createComposite(pageComposite, SWT.NO_FOCUS); + sectionComposite.setLayout(new FillLayout()); + int style = (section.shouldUseExtraSpace()) ? GridData.FILL_BOTH + : GridData.FILL_HORIZONTAL; + GridData data = new GridData(style); + data.heightHint = section.getMinimumHeight(); + sectionComposite.setLayoutData(data); + + ISafeRunnable runnable = new ISafeRunnable() { + + public void run() + throws Exception { + section.createControls(sectionComposite, page); + } + + public void handleException(Throwable exception) { + /* not used */ + } + }; + Platform.run(runnable); + } + controlsCreated = true; + } + + /** + * Dispose of page's sections controls. + */ + public void dispose() { + for (int i = 0; i < sections.length; i++) { + final ISection section = sections[i]; + ISafeRunnable runnable = new ISafeRunnable() { + + public void run() + throws Exception { + section.dispose(); + } + + public void handleException(Throwable exception) { + /* not used */ + } + }; + Platform.run(runnable); + } + } + + /** + * Sends the lifecycle event to the page's sections. + */ + public void aboutToBeShown() { + for (int i = 0; i < sections.length; i++) { + final ISection section = sections[i]; + ISafeRunnable runnable = new ISafeRunnable() { + + public void run() + throws Exception { + section.aboutToBeShown(); + } + + public void handleException(Throwable exception) { + /* not used */ + } + }; + Platform.run(runnable); + } + } + + /** + * Sends the lifecycle event to the page's sections. + */ + public void aboutToBeHidden() { + for (int i = 0; i < sections.length; i++) { + final ISection section = sections[i]; + ISafeRunnable runnable = new ISafeRunnable() { + + public void run() + throws Exception { + section.aboutToBeHidden(); + } + + public void handleException(Throwable exception) { + /* not used */ + } + }; + Platform.run(runnable); + } + } + + /** + * Sets page's sections input objects. + * + * @param part + * @param selection + */ + public void setInput(final IWorkbenchPart part, final ISelection selection) { + for (int i = 0; i < sections.length; i++) { + final ISection section = sections[i]; + ISafeRunnable runnable = new ISafeRunnable() { + + public void run() + throws Exception { + section.setInput(part, selection); + } + + public void handleException(Throwable throwable) { + throwable.printStackTrace(); + } + }; + Platform.run(runnable); + } + } + + public void setSections(ISection[] sections) { + this.sections = sections; + } + + /** + * + * @return true if controls have been created. + */ + public boolean controlsHaveBeenCreated() { + return controlsCreated; + } + + /** + * If controls have been created, refresh all sections on the page. + */ + public void refresh() { + if (controlsCreated) { + for (int i = 0; i < sections.length; i++) { + final ISection section = sections[i]; + ISafeRunnable runnable = new ISafeRunnable() { + + public void run() + throws Exception { + section.refresh(); + } + + public void handleException(Throwable throwable) { + throwable.printStackTrace(); + } + }; + Platform.run(runnable); + } + } + } +} Index: src/org/eclipse/ui/views/properties/tabbed/AbstractSectionDescriptor.java =================================================================== RCS file: src/org/eclipse/ui/views/properties/tabbed/AbstractSectionDescriptor.java diff -N src/org/eclipse/ui/views/properties/tabbed/AbstractSectionDescriptor.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/views/properties/tabbed/AbstractSectionDescriptor.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,207 @@ +/******************************************************************************* + * Copyright (c) 2001, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.views.properties.tabbed; + +import java.util.Collections; +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.jface.viewers.IFilter; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewPlugin; +import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewStatusCodes; +import org.eclipse.ui.internal.views.properties.tabbed.l10n.TabbedPropertyMessages; +import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyRegistryClassSectionFilter; + +import com.ibm.icu.text.MessageFormat; + +/** + * Represents the default implementation of a section descriptor on the tabbed + * property sections extensions. This implementation assumes that we are + * interested in selected objects in an IStructuredSelection. + * + * The id and targetTab properties are mandatory and must not be null. + * + * @author Anthony Hunter + * @version 31 May 2007 + */ +public abstract class AbstractSectionDescriptor + implements ISectionDescriptor { + + private final static String SECTION_ERROR = TabbedPropertyMessages.SectionDescriptor_Section_error; + + private static final String TOP = "top"; //$NON-NLS-1$ + + private String id; + + private String targetTab; + + private String afterSection; + + private TabbedPropertyRegistryClassSectionFilter classFilter; + + private IFilter filter; + + private int enablesFor = ENABLES_FOR_ANY; + + /** + * Constructor for the section descriptor. + * + * @param id + * The id of this section descriptor (must not be null). + * @param targetTab + * The tab that this section applies to (must not be null). + * @param typeMapper + * The type mapper. + */ + protected AbstractSectionDescriptor(String id, String targetTab, ITypeMapper typeMapper) { + this(); + classFilter = new TabbedPropertyRegistryClassSectionFilter(typeMapper); + this.id = id; + this.targetTab = targetTab; + + if (id == null || targetTab == null) { + // the section id and tab are mandatory - log error + handleSectionError(null); + } + } + + /** + * Creates a new section descriptor. It is the resposibility of the subclass to ensure + * that at least a valid id and targetTab are set afterwards. + * @see #setId(String) + * @see #setTargetTab(String) + */ + protected AbstractSectionDescriptor() { + afterSection = TOP; + } + + /** + * Handle the section error when an issue is found loading from the + * configuration element. + * + * @param exception + * an optional CoreException + */ + private void handleSectionError(CoreException exception) { + String pluginId = TabbedPropertyViewPlugin.getPlugin().getBundle().getSymbolicName(); + String message = MessageFormat.format(SECTION_ERROR, + new Object[] {pluginId}); + IStatus status = new Status(IStatus.ERROR, pluginId, + TabbedPropertyViewStatusCodes.SECTION_ERROR, message, exception); + TabbedPropertyViewPlugin.getPlugin().getLog().log(status); + } + + /** + * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getId() + */ + public String getId() { + return id; + } + + /** + * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getFilter() + */ + public IFilter getFilter() { + return filter; + } + + /** + * @param aEnablesFor The enablesFor to set. + */ + public void setEnablesFor(int enablesFor) { + this.enablesFor = enablesFor; + } + + /** + * Retrieves the value for section enablement which is a precise number of + * items selected. For example: enablesFor=" 4" enables the action only when + * 4 items are selected. If not specified, enable for all selections. + * + * @return the value for section enablement. + */ + public int getEnablesFor() { + return enablesFor; + } + + /** + * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getTargetTab() + */ + public String getTargetTab() { + return targetTab; + } + + /** + * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#appliesTo(org.eclipse.ui.IWorkbenchPart, + * org.eclipse.jface.viewers.ISelection) + */ + public boolean appliesTo(IWorkbenchPart part, ISelection selection) { + return classFilter.appliesToSelection(this, selection); + } + + /** + * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getAfterSection() + */ + public String getAfterSection() { + return afterSection; + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + return getId(); + } + + /** + * @param id The id to set (must not be null). + */ + protected void setId(String id) { + if (id == null) { + throw new IllegalArgumentException("id must not be null"); //$NON-NLS-1$ + } + + this.id = id; + } + + /** + * @param targetTab The targetTab to set (must not be null). + */ + protected void setTargetTab(String targetTab) { + if (targetTab == null) { + throw new IllegalArgumentException("targetTab must not be null"); //$NON-NLS-1$ + } + this.targetTab = targetTab; + } + + protected void setTypeMapper(ITypeMapper typeMapper) { + classFilter = new TabbedPropertyRegistryClassSectionFilter(typeMapper); + } + + /** + * @param aAfterSection The afterSection to set. + */ + protected void setAfterSection(String afterSection) { + this.afterSection = afterSection; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getInputTypes() + * Returns an empty list by default. Actually only applicable to subclass SectionDescriptor + * but already released in ISectionDescriptor + */ + public List getInputTypes() { + return Collections.EMPTY_LIST; + } +} Index: src/org/eclipse/ui/views/properties/tabbed/ITabSelectionListener2.java =================================================================== RCS file: src/org/eclipse/ui/views/properties/tabbed/ITabSelectionListener2.java diff -N src/org/eclipse/ui/views/properties/tabbed/ITabSelectionListener2.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/views/properties/tabbed/ITabSelectionListener2.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,31 @@ +/******************************************************************************* + * Copyright (c) 2001, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.views.properties.tabbed; + + + +/** + * A listener interested in tab selection events that occur for the tabbed + * property sheet page. + * + * @author Anthony Hunter + * @version 21 May 2007 + */ +public interface ITabSelectionListener2 { + + /** + * Notifies this listener that the selected tab has changed. + * + * @param tabDescriptor + * the selected tab descriptor. + */ + public void tabSelected(ITabDescriptor tabDescriptor); +} Index: src/org/eclipse/ui/views/properties/tabbed/AbstractTabDescriptor.java =================================================================== RCS file: src/org/eclipse/ui/views/properties/tabbed/AbstractTabDescriptor.java diff -N src/org/eclipse/ui/views/properties/tabbed/AbstractTabDescriptor.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/views/properties/tabbed/AbstractTabDescriptor.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,415 @@ +/******************************************************************************* + * Copyright (c) 2001, 2006 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + *******************************************************************************/ +package org.eclipse.ui.views.properties.tabbed; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewPlugin; +import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewStatusCodes; +import org.eclipse.ui.internal.views.properties.tabbed.l10n.TabbedPropertyMessages; + +import com.ibm.icu.text.MessageFormat; + +/** + * Realizes the base implementation of a tab descriptor on the tabbed + * property tabs extensions. + * + * Clients should subclass this class instead of implementing ITabDescriptor directly. + * + * The id, label, category and section descriptors properties are mandatory and must not be null. + * + * @author Anthony Hunter + * @version 31 May 2007 + */ +public abstract class AbstractTabDescriptor + implements Cloneable, ITabItem, ITabDescriptor { + + public static final String TOP = "top"; //$NON-NLS-1$ + + private final static String TAB_ERROR = TabbedPropertyMessages.TabDescriptor_Tab_error; + + private String id; + + private String label; + + private Image image; + + private boolean selected; + + private boolean indented; + + private String category; + + private String afterTab; + + private List sectionDescriptors; + + /** + * Constructor for AbstractTabDescriptor. + * @param id + * The id of this tab (must not be null) + * @param label + * The label for this tab (must not be null) + * @param category + * The category this tab belongs to (must not be null) + */ + protected AbstractTabDescriptor(String id, String label, String category) { + this(); + + this.id = id; + this.label = label; + this.category = category; + if (id == null || label == null || category == null) { + // the tab id, label and category are mandatory - log error + String pluginId = TabbedPropertyViewPlugin.getPlugin().getBundle().getSymbolicName(); + handleTabError(pluginId, null); + } + } + + /** + * Creates a new AbstractTabDescriptor. + * It is the resposibility of the subclass to ensure + * that at least a valid id, label, category a section descriptors are set afterwards. + * @see #setId(String) + * @see #setCategory(String) + * @see #setSectionDescriptors(List) + */ + protected AbstractTabDescriptor() { + afterTab = TOP; + sectionDescriptors = new ArrayList(5); + selected = false; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.internal.views.properties.tabbed.view.ITabDescriptor#getId() + */ + public String getId() { + return id; + } + + /** + * @param aId The id to set (must not be null). + */ + protected void setId(String id) { + if (id == null) { + throw new IllegalArgumentException("id must not be null"); //$NON-NLS-1$ + } + + this.id = id; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.internal.views.properties.tabbed.view.ITabDescriptor#getLabel() + */ + public String getLabel() { + return label; + } + + /** + * Get the identifier of the tab after which this tab should be displayed. + * When two or more tabs belong to the same category, they are sorted by the + * after tab values. + * + * @return the identifier of the tab. + */ + public String getAfterTab() { + return afterTab; + } + + /** + * Get the category this tab belongs to. + * + * @return Get the category this tab belongs to. + */ + public String getCategory() { + return category; + } + + /** + * Returns whether the given section was added to this tab. The section can + * be appended if its tab attribute matches the tab id. The afterSection + * attribute indicates the order in which the section should be appended. + * + * @param target + * the section descriptor to append. + */ + public boolean append(ISectionDescriptor target) { + if (!target.getTargetTab().equals(id)) { + return false; + } + + if (insertSectionDescriptor(target)) { + return true; + } + + sectionDescriptors.add(target); + return true; + } + + /** + * Insert the section descriptor into the section descriptor list. + * + * @param target + * the section descriptor to insert. + * @return true if the target descriptor was added to the + * descriptors list. + */ + private boolean insertSectionDescriptor(ISectionDescriptor target) { + if (target.getAfterSection().equals(TOP)) { + sectionDescriptors.add(0, target); + return true; + } + for (int i = 0; i < sectionDescriptors.size(); i++) { + ISectionDescriptor descriptor = (ISectionDescriptor) sectionDescriptors + .get(i); + if (target.getAfterSection().equals(descriptor.getId())) { + sectionDescriptors.add(i + 1, target); + return true; + } else { + if (descriptor.getAfterSection().equals(target.getId())) { + sectionDescriptors.add(i, target); + return true; + } + } + } + return false; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.internal.views.properties.tabbed.view.ITabDescriptor#createTab() + */ + public TabContents createTab() { + List sections = new ArrayList(sectionDescriptors.size()); + for (Iterator iter = sectionDescriptors.iterator(); iter.hasNext();) { + ISectionDescriptor descriptor = (ISectionDescriptor) iter.next(); + ISection section = descriptor.getSectionClass(); + sections.add(section); + } + TabContents tab = new TabContents(); + tab.setSections((ISection[]) sections.toArray(new ISection[sections + .size()])); + return tab; + } + + /** + * Get the list of section descriptors for the tab. + * + * @return the list of section descriptors for the tab. + */ + public List getSectionDescriptors() { + return sectionDescriptors; + } + + /** + * Set the list of section descriptors for the tab. + * + * @param sectionDescriptors + * the list of section descriptors for the tab. + */ + protected void setSectionDescriptors(List sectionDescriptors) { + this.sectionDescriptors = sectionDescriptors; + } + + /** + * @see java.lang.Object#toString() + */ + public String toString() { + return getId(); + } + + /** + * Handle the tab error when an issue is found loading from the + * configuration element. + * + * @param configurationElement + * the configuration element + * @param exception + * an optional CoreException + */ + protected void handleTabError(String pluginId, CoreException exception) { + String message = MessageFormat.format(TAB_ERROR, + new Object[] {pluginId}); + IStatus status = new Status(IStatus.ERROR, pluginId, + TabbedPropertyViewStatusCodes.TAB_ERROR, message, exception); + TabbedPropertyViewPlugin.getPlugin().getLog().log(status); + } + + /** + * @see java.lang.Object#equals(java.lang.Object) + */ + public boolean equals(Object object) { + if (this == object) { + return true; + } + + if (this.getClass() == object.getClass()) { + AbstractTabDescriptor descriptor = (AbstractTabDescriptor) object; + if (this.getCategory().equals(descriptor.getCategory()) + && this.getId().equals(descriptor.getId()) + && this.getSectionDescriptors().size() == descriptor + .getSectionDescriptors().size()) { + + Iterator i = this.getSectionDescriptors().iterator(); + Iterator j = descriptor.getSectionDescriptors().iterator(); + + // the order is importent here - so as long as the sizes of the + // lists are the same and id of the section at the same + // positions are the same - the lists are the same + while (i.hasNext()) { + ISectionDescriptor source = (ISectionDescriptor) i.next(); + ISectionDescriptor target = (ISectionDescriptor) j.next(); + if (!source.getId().equals(target.getId())) { + return false; + } + } + + return true; + } + + } + + return false; + } + + /** + * @see java.lang.Object#hashCode() + */ + public int hashCode() { + + int hashCode = getCategory().hashCode(); + hashCode ^= getId().hashCode(); + Iterator i = this.getSectionDescriptors().iterator(); + while (i.hasNext()) { + ISectionDescriptor section = (ISectionDescriptor) i.next(); + hashCode ^= section.getId().hashCode(); + } + return hashCode; + } + + /** + * @see java.lang.Object#clone() + */ + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException exception) { + IStatus status = new Status(IStatus.ERROR, TabbedPropertyViewPlugin + .getPlugin().getBundle().getSymbolicName(), 666, exception + .getMessage(), exception); + TabbedPropertyViewPlugin.getPlugin().getLog().log(status); + } + return null; + } + + /** + * @param afterTab The id of another tab that should appear before this tab + */ + protected void setAfterTab(String afterTab) { + if (afterTab == null) { + this.afterTab = TOP; + } else { + this.afterTab = afterTab; + } + } + + /** + * @param category The category this tab belongs to (must not be null). + */ + protected void setCategory(String category) { + if (category == null) { + throw new IllegalArgumentException("category must not be null"); //$NON-NLS-1$ + } + + this.category = category; + } + + /** + * Set the image for the tab. + * + * @param image + * the image for the tab. + */ + protected void setImage(Image image) { + this.image = image; + } + + /** + * Set the indicator to determine if the tab should be displayed as + * indented. + * + * @param indented + * true if the tab should be displayed as + * indented. + */ + protected void setIndented(boolean indented) { + this.indented = indented; + } + + /** + * Set the indicator to determine if the tab should be the selected tab in + * the list. + * + * @param selected + * true if the tab should be the selected tab in + * the list. + */ + protected void setSelected(boolean selected) { + this.selected = selected; + } + + /** + * Set the text label for the tab (must not be null). + * + * @param label + * the text label for the tab. + */ + protected void setLabel(String label) { + if (label == null) { + throw new IllegalArgumentException("label must not be null"); //$NON-NLS-1$ + } + + this.label = label; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.internal.views.properties.tabbed.view.ITabDescriptor#getImage() + */ + public Image getImage() { + return image; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.internal.views.properties.tabbed.view.ITabDescriptor#isSelected() + */ + public boolean isSelected() { + return selected; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.internal.views.properties.tabbed.view.ITabDescriptor#isIndented() + */ + public boolean isIndented() { + return indented; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.internal.views.properties.tabbed.view.ITabDescriptor#getText() + */ + public String getText() { + return label; + } +} Index: src/org/eclipse/ui/views/properties/tabbed/ITabDescriptorProvider.java =================================================================== RCS file: src/org/eclipse/ui/views/properties/tabbed/ITabDescriptorProvider.java diff -N src/org/eclipse/ui/views/properties/tabbed/ITabDescriptorProvider.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/views/properties/tabbed/ITabDescriptorProvider.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ + +package org.eclipse.ui.views.properties.tabbed; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.ui.IWorkbenchPart; + + +/** + * This interface may be implemented clients who wish to dynamically provide + * ITabDescriptors instead of registering them statically with the extension + * point org.eclipse.ui.views.properties.tabbed.propertyTabs. + * The tabbed properties view queries the current selection for instances of + * this interface, both directly and through the {@link IAdaptable} mechanism. + * + * @since 3.4 + * @version 31 May 2007 + */ +public interface ITabDescriptorProvider { + /** + * Returns the descriptors for the tabs to be shown for the given selection. + * Note that "this" may actually be part of or derived from the selection. + * @return the {@link ITabDescriptor} to be shown in the tabbed properties view + * TODO: really pass part and selection? "this" may actually be part of the selection... + */ + public ITabDescriptor[] getTabDescriptors(IWorkbenchPart currentPart, ISelection currentSelection); +} Index: src/org/eclipse/ui/views/properties/tabbed/ITabDescriptor.java =================================================================== RCS file: src/org/eclipse/ui/views/properties/tabbed/ITabDescriptor.java diff -N src/org/eclipse/ui/views/properties/tabbed/ITabDescriptor.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/views/properties/tabbed/ITabDescriptor.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ + +package org.eclipse.ui.views.properties.tabbed; + +import java.util.List; + +import org.eclipse.swt.graphics.Image; + +/** + *

+ * Not intended to be implemented by clients. Clients should subclass + * AbstractTabDescriptor instead. + *

+ * @since 3.4 + * @version 21 May 2007 + * @see AbstractTabDescriptor + */ +public interface ITabDescriptor { + + /** + * Get the unique identifier for the tab. + * + * @return the unique identifier for the tab. + */ + public String getId(); + + /** + * Get the text label for the tab. + * + * @return the text label for the tab. + */ + public String getLabel(); + + /** + * Instantiate this tab's sections. + */ + public TabContents createTab(); + + /** + * Get the image for the tab. + * + * @return the image for the tab. + */ + public Image getImage(); + + /** + * Determine if the tab is selected. + * + * @return true if the tab is selected. + */ + public boolean isSelected(); + + /** + * Determine if the tab should be displayed as indented. + * + * @return true if the tab should be displayed as indented. + */ + public boolean isIndented(); + + /** + * Get the text label for the tab. + * TODO: why getText() and getLabel()? + * + * @return the text label for the tab. + */ + public String getText(); + + /** + * Get the list of section descriptors for the tab. + * + * @return the list of section descriptors for the tab. + * TODO: probably arrayify this + */ + public List getSectionDescriptors(); + + /** + * Get the category this tab belongs to. + * + * @return Get the category this tab belongs to. + */ + public String getCategory(); +} Index: src/org/eclipse/ui/internal/views/properties/tabbed/view/TabDescriptorProviderManager.java =================================================================== RCS file: src/org/eclipse/ui/internal/views/properties/tabbed/view/TabDescriptorProviderManager.java diff -N src/org/eclipse/ui/internal/views/properties/tabbed/view/TabDescriptorProviderManager.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ src/org/eclipse/ui/internal/views/properties/tabbed/view/TabDescriptorProviderManager.java 1 Jan 1970 00:00:00 -0000 @@ -0,0 +1,269 @@ +/******************************************************************************* + * Copyright (c) 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + ******************************************************************************/ + +package org.eclipse.ui.internal.views.properties.tabbed.view; + +import java.util.*; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.Platform; +import org.eclipse.jface.viewers.ISelection; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.ui.IWorkbenchPart; +import org.eclipse.ui.views.properties.tabbed.AbstractTabDescriptor; +import org.eclipse.ui.views.properties.tabbed.ITabDescriptor; +import org.eclipse.ui.views.properties.tabbed.ITabDescriptorProvider; + + +/** + * Manages {@link ITabDescriptorProvider}s and ensures the correct tab sort order + * + * @since 3.4 + * @version 31 May 2007 + */ +public class TabDescriptorProviderManager { + + private List descriptorProviders = new ArrayList(); + + /** + * Creates a new TabDescriptorProviderManager + */ + public TabDescriptorProviderManager() { + } + + /** + * Inserts a new {@link ITabDescriptorProvider} at the given index + * @param index the position where the descriptor should be added + * @param provider the provider to add + */ + public void insertTabDescriptorProvider(int index, ITabDescriptorProvider provider) { + descriptorProviders.add(index, provider); + } + + /** + * Adds a new {@link ITabDescriptorProvider} to the end of the list + * @param provider the provider to add + */ + public void addTabDescriptorProvider(ITabDescriptorProvider provider) { + descriptorProviders.add(provider); + } + + /** + * Removes the given provider from the list. + * @return Returns true if the provider was previously present in the list + */ + public boolean removeTabDescriptorProvider(ITabDescriptorProvider provider) { + return descriptorProviders.remove(provider); + } + + /** + * @return Returns all the providers + */ + public ITabDescriptorProvider[] getDescriptorProviders() { + return (ITabDescriptorProvider[]) descriptorProviders.toArray(new ITabDescriptorProvider[descriptorProviders.size()]); + } + + /** + * Returns the {@link ITabDescriptor}s applicable to the IWorkbenchPart and the + * given ISelection. Asks all {@link ITabDescriptorProvider}s as well as + * {@link TabbedPropertyRegistry} and returns their descriptors in the correct sort order + * @param currentPart + * @param currentSelection + * @return all applicable {@link ITabDescriptor}s + */ + public ITabDescriptor[] getTabDescriptors(IWorkbenchPart currentPart, ISelection currentSelection) { + Set descriptorSet = new HashSet(); + + // first those from the selection + for (Iterator iter = getProvidersFromSelection(currentPart, currentSelection).iterator(); iter.hasNext();) { + ITabDescriptorProvider provider = (ITabDescriptorProvider) iter.next(); + addReplaceDescriptors(descriptorSet, provider.getTabDescriptors(currentPart, currentSelection)); + } + + // then the explicitly registered ones (including the registry) + for (Iterator iter = descriptorProviders.iterator(); iter.hasNext();) { + ITabDescriptorProvider provider = (ITabDescriptorProvider) iter.next(); + addReplaceDescriptors(descriptorSet, provider.getTabDescriptors(currentPart, currentSelection)); + } + + String[] categories = getAllCategories(descriptorSet); + List sortedDescriptors = new ArrayList(descriptorSet); + sortedDescriptors = sortTabDescriptorsByCategory(categories, sortedDescriptors); + sortedDescriptors = sortTabDescriptorsByAfterTab(categories, sortedDescriptors); + + return (ITabDescriptor[]) sortedDescriptors.toArray(new ITabDescriptor[sortedDescriptors.size()]); + } + + /** + * @param aCurrentPart + * @param aCurrentSelection + * @return Returns a list of all available {@link ITabDescriptorProvider}s for the given selection + * @see #getProviderFor(Object) + */ + private List getProvidersFromSelection(IWorkbenchPart currentPart, ISelection currentSelection) { + if (currentSelection instanceof IStructuredSelection) { + IStructuredSelection ssel = (IStructuredSelection) currentSelection; + List result = new ArrayList(); + for (Iterator iter = ssel.iterator(); iter.hasNext();) { + Object element = iter.next(); + ITabDescriptorProvider provider = getProviderFor(element); + if (provider != null) { + result.add(provider); + } + } + + return result; + } + + return Collections.EMPTY_LIST; + } + + /** + * Returns an {@link ITabDescriptorProvider} for the given element if available. + * Returns the element itself if it is an ITabDescriptorProvider or uses the {@link IAdaptable} + * mechanism. + * @param element the element to query an ITabDescriptorProvider for + */ + protected ITabDescriptorProvider getProviderFor(Object element) { + if (element instanceof ITabDescriptorProvider) { + return (ITabDescriptorProvider) element; + } + + ITabDescriptorProvider provider = null; + + if (element instanceof IAdaptable) { + IAdaptable adaptable = (IAdaptable) element; + provider = (ITabDescriptorProvider) adaptable.getAdapter(ITabDescriptorProvider.class); + if (provider != null) { + return provider; + } + + if (Platform.getAdapterManager().hasAdapter(adaptable, ITabDescriptorProvider.class.getName())) { + provider = (ITabDescriptorProvider) Platform.getAdapterManager().loadAdapter(adaptable, ITabDescriptorProvider.class.getName()); + } + } + + return provider; + } + + /** + * @param descriptors a set of {@link ITabDescriptor}s + * @return Returns all categories referenced by the given set of ITabDescriptors + */ + private String[] getAllCategories(Set descriptors) { + Set allCategories = new HashSet(); + + for (Iterator iter = descriptors.iterator(); iter.hasNext();) { + ITabDescriptor descriptor = (ITabDescriptor) iter.next(); + String category = descriptor.getCategory(); + allCategories.add(category); + } + + return (String[]) allCategories.toArray(new String[allCategories.size()]); + } + + /** + * Adds the given descriptors to the set of {@link ITabDescriptor}s. If an equal + * descriptor is already in the set, it is replaced. + * @param descriptorSet the Set + * @param descriptors the descriptors to add to the set + */ + protected void addReplaceDescriptors(Set descriptorSet, ITabDescriptor[] descriptors) { + if (descriptors != null) { + for (int i = 0; i < descriptors.length; i++) { + descriptorSet.remove(descriptors[i]); // last one takes precedence + descriptorSet.add(descriptors[i]); + } + } + } + + /** + * Sorts the tab descriptors in the given list according to category. + * @param categories + */ + protected List sortTabDescriptorsByCategory(final String[] categories, List descriptors) { + Collections.sort(descriptors, new Comparator() { + + public int compare(Object arg0, Object arg1) { + AbstractTabDescriptor one = (AbstractTabDescriptor) arg0; + AbstractTabDescriptor two = (AbstractTabDescriptor) arg1; + String categoryOne = one.getCategory(); + String categoryTwo = two.getCategory(); + int categoryOnePosition = getIndex(categories, categoryOne); + int categoryTwoPosition = getIndex(categories, categoryTwo); + return categoryOnePosition - categoryTwoPosition; + } + }); + return descriptors; + } + + /** + * Sorts the tab descriptors in the given list according to afterTab. + * @param categories + */ + protected List sortTabDescriptorsByAfterTab(String[] categories, List tabs) { + if (tabs.size() == 0 || categories == null) { + return tabs; + } + List sorted = new ArrayList(); + int categoryIndex = 0; + for (int i = 0; i < categories.length; i++) { + List categoryList = new ArrayList(); + String category = categories[i]; + int topOfCategory = categoryIndex; + int endOfCategory = categoryIndex; + while (endOfCategory < tabs.size() + && ((AbstractTabDescriptor) tabs.get(endOfCategory)).getCategory() + .equals(category)) { + endOfCategory++; + } + for (int j = topOfCategory; j < endOfCategory; j++) { + AbstractTabDescriptor tab = (AbstractTabDescriptor) tabs.get(j); + if (tab.getAfterTab().equals(AbstractTabDescriptor.TOP)) { + categoryList.add(0, tabs.get(j)); + } else { + categoryList.add(tabs.get(j)); + } + } + Collections.sort(categoryList, new Comparator() { + + public int compare(Object arg0, Object arg1) { + AbstractTabDescriptor one = (AbstractTabDescriptor) arg0; + AbstractTabDescriptor two = (AbstractTabDescriptor) arg1; + if (two.getAfterTab().equals(one.getId())) { + return -1; + } else if (one.getAfterTab().equals(two.getId())) { + return 1; + } else { + return 0; + } + } + }); + for (int j = 0; j < categoryList.size(); j++) { + sorted.add(categoryList.get(j)); + } + categoryIndex = endOfCategory; + } + return sorted; + } + + /** + * Returns the index of the given element in the array. + */ + private int getIndex(Object[] array, Object target) { + for (int i = 0; i < array.length; i++) { + if (array[i].equals(target)) { + return i; + } + } + return -1; // should never happen + } +} #P org.eclipse.ui.tests.views.properties.tabbed Index: src/org/eclipse/ui/tests/views/properties/tabbed/TabbedPropertySheetPageTest.java =================================================================== RCS file: /cvsroot/eclipse/org.eclipse.ui.tests.views.properties.tabbed/src/org/eclipse/ui/tests/views/properties/tabbed/TabbedPropertySheetPageTest.java,v retrieving revision 1.3 diff -u -r1.3 TabbedPropertySheetPageTest.java --- src/org/eclipse/ui/tests/views/properties/tabbed/TabbedPropertySheetPageTest.java 22 Feb 2007 02:42:53 -0000 1.3 +++ src/org/eclipse/ui/tests/views/properties/tabbed/TabbedPropertySheetPageTest.java 31 May 2007 10:32:10 -0000 @@ -22,7 +22,6 @@ import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; -import org.eclipse.ui.internal.views.properties.tabbed.view.Tab; import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyComposite; import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyList; import org.eclipse.ui.tests.views.properties.tabbed.sections.InformationTwoSection; @@ -31,6 +30,7 @@ import org.eclipse.ui.tests.views.properties.tabbed.views.TestsView; import org.eclipse.ui.tests.views.properties.tabbed.views.TestsViewContentProvider; import org.eclipse.ui.views.properties.tabbed.ISection; +import org.eclipse.ui.views.properties.tabbed.TabContents; public class TabbedPropertySheetPageTest extends TestCase { @@ -202,7 +202,7 @@ * First tab is Information */ assertEquals(tabbedPropertyList.getElementAt(0).toString(), "Name");//$NON-NLS-1$ - Tab tab = testsView.getTabbedPropertySheetPage().getCurrentTab(); + TabContents tab = testsView.getTabbedPropertySheetPage().getCurrentTab(); /** * the tab has two sections. */ @@ -258,7 +258,7 @@ * viewer. */ public void test_noPropertiesAvailable() { - Tab tab = testsView.getTabbedPropertySheetPage().getCurrentTab(); + TabContents tab = testsView.getTabbedPropertySheetPage().getCurrentTab(); assertNull(tab); TabbedPropertyList tabbedPropertyList = getTabbedPropertyList(); assertNull(tabbedPropertyList.getElementAt(0));