View | Details | Raw Unified | Return to bug 131855 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/ui/internal/views/properties/tabbed/view/Tab.java (-240 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2001, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.ui.internal.views.properties.tabbed.view;
12
13
import org.eclipse.core.runtime.ISafeRunnable;
14
import org.eclipse.core.runtime.Platform;
15
import org.eclipse.jface.viewers.ISelection;
16
import org.eclipse.swt.SWT;
17
import org.eclipse.swt.layout.FillLayout;
18
import org.eclipse.swt.layout.GridData;
19
import org.eclipse.swt.layout.GridLayout;
20
import org.eclipse.swt.widgets.Composite;
21
import org.eclipse.ui.IWorkbenchPart;
22
import org.eclipse.ui.views.properties.tabbed.ISection;
23
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
24
25
/**
26
 * A property tab is composed by one or more property sections and is used to
27
 * categorize sections.
28
 * 
29
 * @author Anthony Hunter
30
 */
31
public class Tab {
32
33
    private ISection[] sections;
34
35
    private boolean controlsCreated;
36
37
    Tab() {
38
        controlsCreated = false;
39
    }
40
41
    /**
42
     * Retrieve a numbered index for the section.
43
     * @param section the section.
44
     * @return the section index.
45
     */
46
    public int getSectionIndex(ISection section) {
47
        for (int i = 0; i < sections.length; i++) {
48
			if (section == sections[i]) {
49
				return i;
50
			}
51
		}
52
        return -1;
53
    }
54
55
    /**
56
     * Retrieve the section at a numbered index.
57
     * @param i a numbered index.
58
     * @return the section.
59
     */
60
    public ISection getSectionAtIndex(int i) {
61
        if (i >= 0 && i < sections.length) {
62
			return sections[i];
63
		}
64
        return null;
65
    }
66
67
    /**
68
     * Retrieve the sections on the tab.
69
     * 
70
     * @return the sections on the tab.
71
     */
72
    public ISection[] getSections() {
73
        return sections;
74
    }
75
76
    /**
77
     * Creates page's sections controls.
78
     * 
79
     * @param parent
80
     * @param page
81
     */
82
    public void createControls(Composite parent,
83
            final TabbedPropertySheetPage page) {
84
        Composite pageComposite = page.getWidgetFactory().createComposite(
85
            parent, SWT.NO_FOCUS);
86
        GridLayout layout = new GridLayout();
87
        layout.marginWidth = 0;
88
        layout.marginHeight = 0;
89
        layout.verticalSpacing = 0;
90
        pageComposite.setLayout(layout);
91
92
        for (int i = 0; i < sections.length; i++) {
93
            final ISection section = sections[i];
94
            final Composite sectionComposite = page.getWidgetFactory()
95
                .createComposite(pageComposite, SWT.NO_FOCUS);
96
            sectionComposite.setLayout(new FillLayout());
97
            int style = (section.shouldUseExtraSpace()) ? GridData.FILL_BOTH
98
                : GridData.FILL_HORIZONTAL;
99
            GridData data = new GridData(style);
100
            data.heightHint = section.getMinimumHeight();
101
            sectionComposite.setLayoutData(data);
102
103
            ISafeRunnable runnable = new ISafeRunnable() {
104
105
                public void run()
106
                    throws Exception {
107
                    section.createControls(sectionComposite, page);
108
                }
109
110
                public void handleException(Throwable exception) {
111
                    /* not used */
112
                }
113
            };
114
            Platform.run(runnable);
115
        }
116
        controlsCreated = true;
117
    }
118
119
    /**
120
     * Dispose of page's sections controls.
121
     */
122
    public void dispose() {
123
        for (int i = 0; i < sections.length; i++) {
124
            final ISection section = sections[i];
125
            ISafeRunnable runnable = new ISafeRunnable() {
126
127
                public void run()
128
                    throws Exception {
129
                    section.dispose();
130
                }
131
132
                public void handleException(Throwable exception) {
133
                    /* not used */
134
                }
135
            };
136
            Platform.run(runnable);
137
        }
138
    }
139
140
    /**
141
     * Sends the lifecycle event to the page's sections.
142
     */
143
    public void aboutToBeShown() {
144
        for (int i = 0; i < sections.length; i++) {
145
            final ISection section = sections[i];
146
            ISafeRunnable runnable = new ISafeRunnable() {
147
148
                public void run()
149
                    throws Exception {
150
                    section.aboutToBeShown();
151
                }
152
153
                public void handleException(Throwable exception) {
154
                    /* not used */
155
                }
156
            };
157
            Platform.run(runnable);
158
        }
159
    }
160
161
    /**
162
     * Sends the lifecycle event to the page's sections.
163
     */
164
    public void aboutToBeHidden() {
165
        for (int i = 0; i < sections.length; i++) {
166
            final ISection section = sections[i];
167
            ISafeRunnable runnable = new ISafeRunnable() {
168
169
                public void run()
170
                    throws Exception {
171
                    section.aboutToBeHidden();
172
                }
173
174
                public void handleException(Throwable exception) {
175
                    /* not used */
176
                }
177
            };
178
            Platform.run(runnable);
179
        }
180
    }
181
182
    /**
183
     * Sets page's sections input objects.
184
     * 
185
     * @param part
186
     * @param selection
187
     */
188
    public void setInput(final IWorkbenchPart part, final ISelection selection) {
189
        for (int i = 0; i < sections.length; i++) {
190
            final ISection section = sections[i];
191
            ISafeRunnable runnable = new ISafeRunnable() {
192
193
                public void run()
194
                    throws Exception {
195
                    section.setInput(part, selection);
196
                }
197
198
                public void handleException(Throwable throwable) {
199
                    throwable.printStackTrace();
200
                }
201
            };
202
            Platform.run(runnable);
203
        }
204
    }
205
206
    void setSections(ISection[] sections) {
207
        this.sections = sections;
208
    }
209
210
    /**
211
     * 
212
     * @return <code>true</code> if controls have been created.
213
     */
214
    public boolean controlsHaveBeenCreated() {
215
        return controlsCreated;
216
    }
217
218
    /**
219
     * If controls have been created, refresh all sections on the page.
220
     */
221
    public void refresh() {
222
        if (controlsCreated) {
223
            for (int i = 0; i < sections.length; i++) {
224
                final ISection section = sections[i];
225
                ISafeRunnable runnable = new ISafeRunnable() {
226
227
                    public void run()
228
                        throws Exception {
229
                        section.refresh();
230
                    }
231
232
                    public void handleException(Throwable throwable) {
233
                        throwable.printStackTrace();
234
                    }
235
                };
236
                Platform.run(runnable);
237
            }
238
        }
239
    }
240
}
(-)src/org/eclipse/ui/internal/views/properties/tabbed/view/TabListContentProvider.java (-10 / +10 lines)
Lines 14-20 Link Here
14
import org.eclipse.jface.viewers.ISelection;
14
import org.eclipse.jface.viewers.ISelection;
15
import org.eclipse.jface.viewers.IStructuredContentProvider;
15
import org.eclipse.jface.viewers.IStructuredContentProvider;
16
import org.eclipse.jface.viewers.Viewer;
16
import org.eclipse.jface.viewers.Viewer;
17
import org.eclipse.ui.IWorkbenchPart;
17
import org.eclipse.ui.views.properties.tabbed.TabbedPropertySheetPage;
18
18
19
19
20
/**
20
/**
Lines 22-40 Link Here
22
 * tabbed property sheet page's list of tabs.
22
 * tabbed property sheet page's list of tabs.
23
 * 
23
 * 
24
 * @author Anthony Hunter
24
 * @author Anthony Hunter
25
 * @version 30 May 2007
25
 */
26
 */
26
public class TabListContentProvider
27
public class TabListContentProvider
27
	implements IStructuredContentProvider {
28
	implements IStructuredContentProvider {
28
	
29
	
29
	private TabbedPropertyRegistry registry;
30
	private TabbedPropertySheetPage tabbedPropertyPage;
30
31
31
	private IWorkbenchPart currentPart;
32
	
33
	/**
32
	/**
34
	 * Constructor for TabListContentProvider.
33
	 * Constructor for TabListContentProvider.
34
	 * This content provider always returns the "current tabs" of the given
35
	 * property page
36
	 * #see {@link TabbedPropertySheetPage.#getCurrentTabs()} 
35
	 */
37
	 */
36
	public TabListContentProvider(TabbedPropertyRegistry registry) {
38
	public TabListContentProvider(TabbedPropertySheetPage tabbedPropertyPage) {
37
		this.registry = registry;
39
		this.tabbedPropertyPage = tabbedPropertyPage;
38
	}
40
	}
39
	
41
	
40
	/**
42
	/**
Lines 42-62 Link Here
42
	 */
44
	 */
43
	public Object[] getElements(Object inputElement) {
45
	public Object[] getElements(Object inputElement) {
44
		Assert.isTrue(inputElement instanceof ISelection);
46
		Assert.isTrue(inputElement instanceof ISelection);
45
			return registry
47
			return tabbedPropertyPage.getCurrentTabs();
46
			.getTabDescriptors(currentPart, (ISelection) inputElement);
47
	}
48
	}
48
49
49
	/**
50
	/**
50
	 * @see org.eclipse.jface.viewers.IContentProvider#dispose()
51
	 * @see org.eclipse.jface.viewers.IContentProvider#dispose()
51
	 */
52
	 */
52
	public void dispose() {
53
	public void dispose() {
53
		/* not used */
54
		tabbedPropertyPage = null;
54
	}
55
	}
55
56
56
	/**
57
	/**
57
	 * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
58
	 * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
58
	 */
59
	 */
59
	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
60
	public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
60
		this.currentPart = ((TabbedPropertyViewer)viewer).getWorkbenchPart();
61
	}
61
	}
62
}
62
}
(-)src/org/eclipse/ui/internal/views/properties/tabbed/view/TabDescriptor.java (-333 / +27 lines)
Lines 10-31 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.ui.internal.views.properties.tabbed.view;
11
package org.eclipse.ui.internal.views.properties.tabbed.view;
12
12
13
import com.ibm.icu.text.MessageFormat;
14
import java.util.ArrayList;
15
import java.util.Iterator;
16
import java.util.List;
13
import java.util.List;
17
14
18
import org.eclipse.core.runtime.CoreException;
19
import org.eclipse.core.runtime.IConfigurationElement;
15
import org.eclipse.core.runtime.IConfigurationElement;
20
import org.eclipse.core.runtime.IStatus;
21
import org.eclipse.core.runtime.Status;
22
import org.eclipse.swt.graphics.Image;
16
import org.eclipse.swt.graphics.Image;
23
import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewPlugin;
24
import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewStatusCodes;
25
import org.eclipse.ui.internal.views.properties.tabbed.l10n.TabbedPropertyMessages;
26
import org.eclipse.ui.plugin.AbstractUIPlugin;
17
import org.eclipse.ui.plugin.AbstractUIPlugin;
27
import org.eclipse.ui.views.properties.tabbed.ISection;
18
import org.eclipse.ui.views.properties.tabbed.AbstractTabDescriptor;
28
import org.eclipse.ui.views.properties.tabbed.ISectionDescriptor;
19
import org.eclipse.ui.views.properties.tabbed.ITabDescriptor;
29
import org.eclipse.ui.views.properties.tabbed.ITabItem;
20
import org.eclipse.ui.views.properties.tabbed.ITabItem;
30
21
31
/**
22
/**
Lines 33-41 Link Here
33
 * property tabs extensions.
24
 * property tabs extensions.
34
 * 
25
 * 
35
 * @author Anthony Hunter
26
 * @author Anthony Hunter
27
 * @version 22 May 2007
36
 */
28
 */
37
public class TabDescriptor
29
public class TabDescriptor extends AbstractTabDescriptor
38
	implements Cloneable, ITabItem {
30
	implements Cloneable, ITabItem, ITabDescriptor {
39
31
40
	private static final String ATT_ID = "id"; //$NON-NLS-1$
32
	private static final String ATT_ID = "id"; //$NON-NLS-1$
41
33
Lines 49-74 Link Here
49
41
50
	private static final String ATT_AFTER_TAB = "afterTab"; //$NON-NLS-1$
42
	private static final String ATT_AFTER_TAB = "afterTab"; //$NON-NLS-1$
51
43
52
	private static final String TOP = "top"; //$NON-NLS-1$
53
54
	private final static String TAB_ERROR = TabbedPropertyMessages.TabDescriptor_Tab_error;
55
56
	private String id;
57
58
	private String label;
59
60
	private Image image;
61
62
	private boolean selected;
63
64
	private boolean indented;
65
66
	private String category;
67
68
	private String afterTab;
69
70
	private List sectionDescriptors;
71
72
	/**
44
	/**
73
	 * Constructor for TabDescriptor.
45
	 * Constructor for TabDescriptor.
74
	 * 
46
	 * 
Lines 76-219 Link Here
76
	 *            the configuration element for the tab descriptor.
48
	 *            the configuration element for the tab descriptor.
77
	 */
49
	 */
78
	public TabDescriptor(IConfigurationElement configurationElement) {
50
	public TabDescriptor(IConfigurationElement configurationElement) {
51
		super();
52
		
79
		if (configurationElement != null) {
53
		if (configurationElement != null) {
80
			id = configurationElement.getAttribute(ATT_ID);
54
			String id = configurationElement.getAttribute(ATT_ID);
81
			label = configurationElement.getAttribute(ATT_LABEL);
55
			String label = configurationElement.getAttribute(ATT_LABEL);
82
			String imageString = configurationElement.getAttribute(ATT_IMAGE);
56
			String imageString = configurationElement.getAttribute(ATT_IMAGE);
83
			if (imageString != null) {
57
			if (imageString != null) {
84
				image = AbstractUIPlugin
58
				Image image = AbstractUIPlugin
85
					.imageDescriptorFromPlugin(
59
					.imageDescriptorFromPlugin(
86
						configurationElement.getDeclaringExtension()
60
						configurationElement.getDeclaringExtension()
87
							.getNamespace(), imageString).createImage();
61
							.getNamespace(), imageString).createImage();
62
				if (image != null) {
63
					setImage(image);
64
				}
88
			}
65
			}
89
			String indentedString = configurationElement
66
			String indentedString = configurationElement
90
				.getAttribute(ATT_INDENTED);
67
				.getAttribute(ATT_INDENTED);
91
			indented = indentedString != null && indentedString.equals("true"); //$NON-NLS-1$
68
			boolean indented = indentedString != null && indentedString.equals("true"); //$NON-NLS-1$
92
			category = configurationElement.getAttribute(ATT_CATEGORY);
69
			setIndented(indented);
93
			afterTab = configurationElement.getAttribute(ATT_AFTER_TAB);
70
			String category = configurationElement.getAttribute(ATT_CATEGORY);
71
			String afterTab = configurationElement.getAttribute(ATT_AFTER_TAB);
72
			setAfterTab(afterTab);
94
			if (id == null || label == null || category == null) {
73
			if (id == null || label == null || category == null) {
95
				// the tab id, label and category are mandatory - log error
74
				// the tab id, label and category are mandatory - log error
96
				handleTabError(configurationElement, null);
75
				handleTabError(configurationElement.getContributor().getName(), null);
97
			}
98
		}
99
		if (getAfterTab() == null) {
100
			afterTab = TOP;
101
		}
102
		sectionDescriptors = new ArrayList(5);
103
		selected = false;
104
	}
105
106
	/**
107
	 * Get the unique identifier for the tab.
108
	 * 
109
	 * @return the unique identifier for the tab.
110
	 */
111
	public String getId() {
112
		return id;
113
	}
114
115
	/**
116
	 * Get the text label for the tab.
117
	 * 
118
	 * @return the text label for the tab.
119
	 */
120
	public String getLabel() {
121
		return label;
122
	}
123
124
	/**
125
	 * Get the identifier of the tab after which this tab should be displayed.
126
	 * When two or more tabs belong to the same category, they are sorted by the
127
	 * after tab values.
128
	 * 
129
	 * @return the identifier of the tab.
130
	 */
131
	protected String getAfterTab() {
132
		return afterTab;
133
	}
134
135
	/**
136
	 * Get the category this tab belongs to.
137
	 * 
138
	 * @return Get the category this tab belongs to.
139
	 */
140
	protected String getCategory() {
141
		return category;
142
	}
143
144
	/**
145
	 * Returns whether the given section was added to this tab. The section can
146
	 * be appended if its tab attribute matches the tab id. The afterSection
147
	 * attribute indicates the order in which the section should be appended.
148
	 * 
149
	 * @param target
150
	 *            the section descriptor to append.
151
	 */
152
	protected boolean append(ISectionDescriptor target) {
153
		if (!target.getTargetTab().equals(id)) {
154
			return false;
155
		}
156
157
		if (insertSectionDescriptor(target)) {
158
			return true;
159
		}
160
161
		sectionDescriptors.add(target);
162
		return true;
163
	}
164
165
	/**
166
	 * Insert the section descriptor into the section descriptor list.
167
	 * 
168
	 * @param target
169
	 *            the section descriptor to insert.
170
	 * @return <code>true</code> if the target descriptor was added to the
171
	 *         descriptors list.
172
	 */
173
	private boolean insertSectionDescriptor(ISectionDescriptor target) {
174
		if (target.getAfterSection().equals(TOP)) {
175
			sectionDescriptors.add(0, target);
176
			return true;
177
		}
178
		for (int i = 0; i < sectionDescriptors.size(); i++) {
179
			ISectionDescriptor descriptor = (ISectionDescriptor) sectionDescriptors
180
				.get(i);
181
			if (target.getAfterSection().equals(descriptor.getId())) {
182
				sectionDescriptors.add(i + 1, target);
183
				return true;
184
			} else {
185
				if (descriptor.getAfterSection().equals(target.getId())) {
186
					sectionDescriptors.add(i, target);
187
					return true;
188
				}
189
			}
76
			}
77
			
78
			setId(id);
79
			setLabel(label);
80
			setCategory(category);
190
		}
81
		}
191
		return false;
82
		
192
	}
193
194
	/**
195
	 * Instantiate this tab's sections.
196
	 */
197
	public Tab createTab() {
198
		List sections = new ArrayList(sectionDescriptors.size());
199
		for (Iterator iter = sectionDescriptors.iterator(); iter.hasNext();) {
200
			ISectionDescriptor descriptor = (ISectionDescriptor) iter.next();
201
			ISection section = descriptor.getSectionClass();
202
			sections.add(section);
203
		}
204
		Tab tab = new Tab();
205
		tab.setSections((ISection[]) sections.toArray(new ISection[sections
206
			.size()]));
207
		return tab;
208
	}
209
210
	/**
211
	 * Get the list of section descriptors for the tab.
212
	 * 
213
	 * @return the list of section descriptors for the tab.
214
	 */
215
	protected List getSectionDescriptors() {
216
		return sectionDescriptors;
217
	}
83
	}
218
84
219
	/**
85
	/**
Lines 221-402 Link Here
221
	 * 
87
	 * 
222
	 * @param sectionDescriptors
88
	 * @param sectionDescriptors
223
	 *            the list of section descriptors for the tab.
89
	 *            the list of section descriptors for the tab.
224
	 */
225
	protected void setSectionDescriptors(List sectionDescriptors) {
226
		this.sectionDescriptors = sectionDescriptors;
227
	}
228
229
	/**
230
	 * @see java.lang.Object#toString()
231
	 */
232
	public String toString() {
233
		return getId();
234
	}
235
90
236
	/**
91
	 * Made this publicly accessible to {@link TabbedPropertyRegistry}  
237
	 * Handle the tab error when an issue is found loading from the
238
	 * configuration element.
239
	 * 
240
	 * @param configurationElement
241
	 *            the configuration element
242
	 * @param exception
243
	 *            an optional CoreException
244
	 */
245
	private void handleTabError(IConfigurationElement configurationElement,
246
			CoreException exception) {
247
		String pluginId = configurationElement.getDeclaringExtension()
248
			.getNamespace();
249
		String message = MessageFormat.format(TAB_ERROR,
250
			new Object[] {pluginId});
251
		IStatus status = new Status(IStatus.ERROR, pluginId,
252
			TabbedPropertyViewStatusCodes.TAB_ERROR, message, exception);
253
		TabbedPropertyViewPlugin.getPlugin().getLog().log(status);
254
	}
255
256
	/**
257
	 * @see java.lang.Object#equals(java.lang.Object)
258
	 */
259
	public boolean equals(Object object) {
260
		if (this == object) {
261
			return true;
262
		}
263
264
		if (this.getClass() == object.getClass()) {
265
			TabDescriptor descriptor = (TabDescriptor) object;
266
			if (this.getCategory().equals(descriptor.getCategory())
267
				&& this.getId().equals(descriptor.getId())
268
				&& this.getSectionDescriptors().size() == descriptor
269
					.getSectionDescriptors().size()) {
270
271
				Iterator i = this.getSectionDescriptors().iterator();
272
				Iterator j = descriptor.getSectionDescriptors().iterator();
273
274
				// the order is importent here - so as long as the sizes of the
275
				// lists are the same and id of the section at the same
276
				// positions are the same - the lists are the same
277
				while (i.hasNext()) {
278
					ISectionDescriptor source = (ISectionDescriptor) i.next();
279
					ISectionDescriptor target = (ISectionDescriptor) j.next();
280
					if (!source.getId().equals(target.getId())) {
281
						return false;
282
					}
283
				}
284
285
				return true;
286
			}
287
288
		}
289
290
		return false;
291
	}
292
293
	/**
294
	 * @see java.lang.Object#hashCode()
295
	 */
296
	public int hashCode() {
297
298
		int hashCode = getCategory().hashCode();
299
		hashCode ^= getId().hashCode();
300
		Iterator i = this.getSectionDescriptors().iterator();
301
		while (i.hasNext()) {
302
			ISectionDescriptor section = (ISectionDescriptor) i.next();
303
			hashCode ^= section.getId().hashCode();
304
		}
305
		return hashCode;
306
	}
307
308
	/**
309
	 * @see java.lang.Object#clone()
310
	 */
311
	public Object clone() {
312
		try {
313
			return super.clone();
314
		} catch (CloneNotSupportedException exception) {
315
			IStatus status = new Status(IStatus.ERROR, TabbedPropertyViewPlugin
316
				.getPlugin().getBundle().getSymbolicName(), 666, exception
317
				.getMessage(), exception);
318
			TabbedPropertyViewPlugin.getPlugin().getLog().log(status);
319
		}
320
		return null;
321
	}
322
323
	/**
324
	 * Set the image for the tab.
325
	 * 
326
	 * @param image
327
	 *            the image for the tab.
328
	 */
329
	protected void setImage(Image image) {
330
		this.image = image;
331
	}
332
333
	/**
334
	 * Set the indicator to determine if the tab should be displayed as
335
	 * indented.
336
	 * 
337
	 * @param indented
338
	 *            <code>true</code> if the tab should be displayed as
339
	 *            indented.
340
	 */
341
	protected void setIndented(boolean indented) {
342
		this.indented = indented;
343
	}
344
345
	/**
346
	 * Set the indicator to determine if the tab should be the selected tab in
347
	 * the list.
348
	 * 
349
	 * @param selected
350
	 *            <code>true</code> if the tab should be the selected tab in
351
	 *            the list.
352
	 */
353
	protected void setSelected(boolean selected) {
354
		this.selected = selected;
355
	}
356
357
	/**
358
	 * Set the text label for the tab.
359
	 * 
360
	 * @param label
361
	 *            the text label for the tab.
362
	 */
363
	protected void setLabel(String label) {
364
		this.label = label;
365
	}
366
367
	/**
368
	 * Get the image for the tab.
369
	 * 
370
	 * @return the image for the tab.
371
	 */
372
	public Image getImage() {
373
		return image;
374
	}
375
376
	/**
377
	 * Determine if the tab is selected.
378
	 * 
379
	 * @return <code>true</code> if the tab is selected.
380
	 */
381
	public boolean isSelected() {
382
		return selected;
383
	}
384
385
	/**
386
	 * Determine if the tab should be displayed as indented.
387
	 * 
388
	 * @return <code>true</code> if the tab should be displayed as indented.
389
	 */
390
	public boolean isIndented() {
391
		return indented;
392
	}
393
394
	/**
395
	 * Get the text label for the tab.
396
	 * 
397
	 * @return the text label for the tab.
398
	 */
92
	 */
399
	public String getText() {
93
	public void setSectionDescriptors(List aSectionDescriptors) {
400
		return label;
94
		super.setSectionDescriptors(aSectionDescriptors);
401
	}
95
	}
402
}
96
}
(-)src/org/eclipse/ui/internal/views/properties/tabbed/view/SectionDescriptor.java (-71 / +21 lines)
Lines 10-16 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.ui.internal.views.properties.tabbed.view;
11
package org.eclipse.ui.internal.views.properties.tabbed.view;
12
12
13
import com.ibm.icu.text.MessageFormat;
14
import java.util.ArrayList;
13
import java.util.ArrayList;
15
import java.util.List;
14
import java.util.List;
16
15
Lines 19-42 Link Here
19
import org.eclipse.core.runtime.IStatus;
18
import org.eclipse.core.runtime.IStatus;
20
import org.eclipse.core.runtime.Status;
19
import org.eclipse.core.runtime.Status;
21
import org.eclipse.jface.viewers.IFilter;
20
import org.eclipse.jface.viewers.IFilter;
22
import org.eclipse.jface.viewers.ISelection;
23
import org.eclipse.ui.IWorkbenchPart;
24
import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewPlugin;
21
import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewPlugin;
25
import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewStatusCodes;
22
import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewStatusCodes;
26
import org.eclipse.ui.internal.views.properties.tabbed.l10n.TabbedPropertyMessages;
23
import org.eclipse.ui.internal.views.properties.tabbed.l10n.TabbedPropertyMessages;
24
import org.eclipse.ui.views.properties.tabbed.AbstractSectionDescriptor;
27
import org.eclipse.ui.views.properties.tabbed.ISection;
25
import org.eclipse.ui.views.properties.tabbed.ISection;
28
import org.eclipse.ui.views.properties.tabbed.ISectionDescriptor;
29
import org.eclipse.ui.views.properties.tabbed.ITypeMapper;
26
import org.eclipse.ui.views.properties.tabbed.ITypeMapper;
30
27
28
import com.ibm.icu.text.MessageFormat;
29
31
/**
30
/**
32
 * Represents the default implementation of a section descriptor on the tabbed
31
 * Represents the default implementation of a section descriptor on the tabbed
33
 * property sections extensions. This implementation assumes that we are
32
 * property sections extensions. This implementation assumes that we are
34
 * interested in selected objects in an IStructuredSelection.
33
 * interested in selected objects in an IStructuredSelection.
35
 * 
34
 * 
36
 * @author Anthony Hunter
35
 * @author Anthony Hunter
36
 * @version 21 May 2007
37
 */
37
 */
38
public class SectionDescriptor
38
public class SectionDescriptor
39
	implements ISectionDescriptor {
39
	extends AbstractSectionDescriptor {
40
40
41
	private final static String SECTION_ERROR = TabbedPropertyMessages.SectionDescriptor_Section_error;
41
	private final static String SECTION_ERROR = TabbedPropertyMessages.SectionDescriptor_Section_error;
42
42
Lines 56-77 Link Here
56
56
57
	private static final String ELEMENT_INPUT = "input"; //$NON-NLS-1$
57
	private static final String ELEMENT_INPUT = "input"; //$NON-NLS-1$
58
58
59
	private static final String TOP = "top"; //$NON-NLS-1$
60
61
	private String id;
62
63
	private String targetTab;
64
65
	private String afterSection;
66
67
	private ArrayList inputTypes;
59
	private ArrayList inputTypes;
68
60
69
	private TabbedPropertyRegistryClassSectionFilter classFilter;
70
71
	private IFilter filter;
61
	private IFilter filter;
72
62
73
	private int enablesFor = ENABLES_FOR_ANY;
74
75
	private IConfigurationElement configurationElement;
63
	private IConfigurationElement configurationElement;
76
64
77
	/**
65
	/**
Lines 84-102 Link Here
84
	 */
72
	 */
85
	protected SectionDescriptor(IConfigurationElement configurationElement,
73
	protected SectionDescriptor(IConfigurationElement configurationElement,
86
			ITypeMapper typeMapper) {
74
			ITypeMapper typeMapper) {
75
		super();
76
		
87
		this.configurationElement = configurationElement;
77
		this.configurationElement = configurationElement;
88
78
89
		classFilter = new TabbedPropertyRegistryClassSectionFilter(typeMapper);
79
		setTypeMapper(typeMapper);
90
		id = getConfigurationElement().getAttribute(ATT_ID);
80
		String id = getConfigurationElement().getAttribute(ATT_ID);
91
		targetTab = getConfigurationElement().getAttribute(ATT_TARGET_TAB);
81
		String targetTab = getConfigurationElement().getAttribute(ATT_TARGET_TAB);
92
		afterSection = getConfigurationElement()
82
		String afterSection = getConfigurationElement()
93
			.getAttribute(ATT_AFTER_SECTION);
83
			.getAttribute(ATT_AFTER_SECTION);
94
		if (getConfigurationElement().getAttribute(ATT_SECTION_ENABLES_FOR) != null) {
84
		if (getConfigurationElement().getAttribute(ATT_SECTION_ENABLES_FOR) != null) {
95
			String enablesForStr = getConfigurationElement().getAttribute(
85
			String enablesForStr = getConfigurationElement().getAttribute(
96
				ATT_SECTION_ENABLES_FOR);
86
				ATT_SECTION_ENABLES_FOR);
97
			int enablesForTest = Integer.parseInt(enablesForStr);
87
			int enablesForTest = Integer.parseInt(enablesForStr);
98
			if (enablesForTest > 0) {
88
			if (enablesForTest > 0) {
99
				enablesFor = enablesForTest;
89
				setEnablesFor(enablesForTest);
100
			}
90
			}
101
		}
91
		}
102
92
Lines 104-111 Link Here
104
			// the section id and tab are mandatory - log error
94
			// the section id and tab are mandatory - log error
105
			handleSectionError(null);
95
			handleSectionError(null);
106
		}
96
		}
107
		if (getAfterSection() == null) {
97
		
108
			afterSection = TOP;
98
		if (afterSection != null) {
99
			setAfterSection(afterSection);
100
		}
101
		if (id != null) {
102
			setId(id);
103
		}
104
		if (targetTab != null) {
105
			setTargetTab(targetTab);
109
		}
106
		}
110
	}
107
	}
111
108
Lines 129-141 Link Here
129
	}
126
	}
130
127
131
	/**
128
	/**
132
	 * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getId()
133
	 */
134
	public String getId() {
135
		return id;
136
	}
137
138
	/**
139
	 * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getFilter()
129
	 * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getFilter()
140
	 */
130
	 */
141
	public IFilter getFilter() {
131
	public IFilter getFilter() {
Lines 153-191 Link Here
153
	}
143
	}
154
144
155
	/**
145
	/**
156
	 * Retrieves the value for section enablement which is a precise number of
157
	 * items selected. For example: enablesFor=" 4" enables the action only when
158
	 * 4 items are selected. If not specified, enable for all selections.
159
	 * 
160
	 * @return the value for section enablement.
161
	 */
162
	public int getEnablesFor() {
163
		return enablesFor;
164
	}
165
166
	/**
167
	 * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getTargetTab()
168
	 */
169
	public String getTargetTab() {
170
		return targetTab;
171
	}
172
173
	/**
174
	 * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#appliesTo(org.eclipse.ui.IWorkbenchPart,
175
	 *      org.eclipse.jface.viewers.ISelection)
176
	 */
177
	public boolean appliesTo(IWorkbenchPart part, ISelection selection) {
178
		return classFilter.appliesToSelection(this, selection);
179
	}
180
181
	/**
182
	 * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getAfterSection()
183
	 */
184
	public String getAfterSection() {
185
		return afterSection;
186
	}
187
188
	/**
189
	 * Creates an instance of a section described by this descriptor
146
	 * Creates an instance of a section described by this descriptor
190
	 * 
147
	 * 
191
	 * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getSectionClass()
148
	 * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getSectionClass()
Lines 222-234 Link Here
222
	}
179
	}
223
180
224
	/**
181
	/**
225
	 * @see java.lang.Object#toString()
226
	 */
227
	public String toString() {
228
		return getId();
229
	}
230
231
	/**
232
	 * @return Returns the configurationElement.
182
	 * @return Returns the configurationElement.
233
	 */
183
	 */
234
	private IConfigurationElement getConfigurationElement() {
184
	private IConfigurationElement getConfigurationElement() {
(-)src/org/eclipse/ui/internal/views/properties/tabbed/view/TabbedPropertyRegistry.java (-107 / +12 lines)
Lines 10-46 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.ui.internal.views.properties.tabbed.view;
11
package org.eclipse.ui.internal.views.properties.tabbed.view;
12
12
13
import com.ibm.icu.text.MessageFormat;
14
import java.util.ArrayList;
13
import java.util.ArrayList;
15
import java.util.Collections;
16
import java.util.Comparator;
17
import java.util.Iterator;
14
import java.util.Iterator;
18
import java.util.List;
15
import java.util.List;
19
16
20
import org.eclipse.core.runtime.CoreException;
17
import org.eclipse.core.runtime.*;
21
import org.eclipse.core.runtime.IConfigurationElement;
22
import org.eclipse.core.runtime.IExtensionPoint;
23
import org.eclipse.core.runtime.IStatus;
24
import org.eclipse.core.runtime.Platform;
25
import org.eclipse.core.runtime.Status;
26
import org.eclipse.jface.viewers.ILabelProvider;
18
import org.eclipse.jface.viewers.ILabelProvider;
27
import org.eclipse.jface.viewers.ISelection;
19
import org.eclipse.jface.viewers.ISelection;
28
import org.eclipse.ui.IWorkbenchPart;
20
import org.eclipse.ui.IWorkbenchPart;
29
import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewPlugin;
21
import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewPlugin;
30
import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewStatusCodes;
22
import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewStatusCodes;
31
import org.eclipse.ui.internal.views.properties.tabbed.l10n.TabbedPropertyMessages;
23
import org.eclipse.ui.internal.views.properties.tabbed.l10n.TabbedPropertyMessages;
32
import org.eclipse.ui.views.properties.tabbed.IActionProvider;
24
import org.eclipse.ui.views.properties.tabbed.*;
33
import org.eclipse.ui.views.properties.tabbed.ISectionDescriptor;
25
34
import org.eclipse.ui.views.properties.tabbed.ISectionDescriptorProvider;
26
import com.ibm.icu.text.MessageFormat;
35
import org.eclipse.ui.views.properties.tabbed.ITypeMapper;
36
27
37
/**
28
/**
38
 * Provides information about the tabbed property extension points. Each tabbed
29
 * Provides information about the tabbed property extension points. Each tabbed
39
 * property registry is associated with a unique contributor ID.
30
 * property registry is associated with a unique contributor ID.
40
 * 
31
 * 
41
 * @author Anthony Hunter
32
 * @author Anthony Hunter
33
 * @version 22 May 2007
42
 */
34
 */
43
public class TabbedPropertyRegistry {
35
public class TabbedPropertyRegistry implements ITabDescriptorProvider {
44
36
45
	private final static String NO_TAB_ERROR = TabbedPropertyMessages.TabbedPropertyRegistry_Non_existing_tab;
37
	private final static String NO_TAB_ERROR = TabbedPropertyMessages.TabbedPropertyRegistry_Non_existing_tab;
46
38
Lines 69-76 Link Here
69
61
70
    private static final String ATT_ACTION_PROVIDER = "actionProvider"; //$NON-NLS-1$
62
    private static final String ATT_ACTION_PROVIDER = "actionProvider"; //$NON-NLS-1$
71
63
72
	private static final String TOP = "top"; //$NON-NLS-1$
73
74
	protected String contributorId;
64
	protected String contributorId;
75
65
76
	protected IConfigurationElement contributorConfigurationElement;
66
	protected IConfigurationElement contributorConfigurationElement;
Lines 218-246 Link Here
218
	}
208
	}
219
209
220
	/**
210
	/**
221
	 * Returns the index of the given element in the array.
222
	 */
223
	private int getIndex(Object[] array, Object target) {
224
		for (int i = 0; i < array.length; i++) {
225
			if (array[i].equals(target)) {
226
				return i;
227
			}
228
		}
229
		return -1; // should never happen
230
	}
231
232
	/**
233
	 * Returns property tab descriptors for the given contributor id and object
211
	 * Returns property tab descriptors for the given contributor id and object
234
	 * input. The descriptors are sorted using the afterPage attribute.
212
	 * input. The descriptors are sorted using the afterPage attribute.
235
	 */
213
	 */
236
	public TabDescriptor[] getTabDescriptors(IWorkbenchPart part,
214
	public ITabDescriptor[] getTabDescriptors(IWorkbenchPart part,
237
			ISelection selection) {
215
			ISelection selection) {
238
		if (selection == null || selection.isEmpty()) {
216
		if (selection == null || selection.isEmpty()) {
239
			return EMPTY_DESCRIPTOR_ARRAY;
217
			return EMPTY_DESCRIPTOR_ARRAY;
240
		}
218
		}
241
219
242
		TabDescriptor[] allDescriptors = getAllTabDescriptors();
220
		TabDescriptor[] allDescriptors = getAllTabDescriptors();
243
		TabDescriptor[] result = filterTabDescriptors(allDescriptors, part,
221
		ITabDescriptor[] result = filterTabDescriptors(allDescriptors, part,
244
			selection);
222
			selection);
245
		return result;
223
		return result;
246
	}
224
	}
Lines 293-302 Link Here
293
		if (tabDescriptors == null) {
271
		if (tabDescriptors == null) {
294
			List temp = readTabDescriptors();
272
			List temp = readTabDescriptors();
295
			populateWithSectionDescriptors(temp);
273
			populateWithSectionDescriptors(temp);
296
			temp = sortTabDescriptorsByCategory(temp);
274
			tabDescriptors = (TabDescriptor[]) temp.toArray(new TabDescriptor[temp.size()]);
297
			temp = sortTabDescriptorsByAfterTab(temp);
298
			tabDescriptors = (TabDescriptor[]) temp
299
				.toArray(new TabDescriptor[temp.size()]);
300
		}
275
		}
301
		return tabDescriptors;
276
		return tabDescriptors;
302
	}
277
	}
Lines 313-319 Link Here
313
			IConfigurationElement[] tabs = extension.getChildren(ELEMENT_TAB);
288
			IConfigurationElement[] tabs = extension.getChildren(ELEMENT_TAB);
314
			for (int j = 0; j < tabs.length; j++) {
289
			for (int j = 0; j < tabs.length; j++) {
315
				IConfigurationElement tab = tabs[j];
290
				IConfigurationElement tab = tabs[j];
316
				TabDescriptor descriptor = new TabDescriptor(tab);
291
				ITabDescriptor descriptor = new TabDescriptor(tab);
317
				result.add(descriptor);
292
				result.add(descriptor);
318
			}
293
			}
319
		}
294
		}
Lines 342-348 Link Here
342
	protected void appendToTabDescriptor(ISectionDescriptor section,
317
	protected void appendToTabDescriptor(ISectionDescriptor section,
343
			List aTabDescriptors) {
318
			List aTabDescriptors) {
344
		for (Iterator i = aTabDescriptors.iterator(); i.hasNext();) {
319
		for (Iterator i = aTabDescriptors.iterator(); i.hasNext();) {
345
			TabDescriptor tab = (TabDescriptor) i.next();
320
			AbstractTabDescriptor tab = (AbstractTabDescriptor) i.next();
346
			if (tab.append(section)) {
321
			if (tab.append(section)) {
347
				return;
322
				return;
348
			}
323
			}
Lines 357-432 Link Here
357
	}
332
	}
358
333
359
	/**
334
	/**
360
	 * Sorts the tab descriptors in the given list according to category.
361
	 */
362
	protected List sortTabDescriptorsByCategory(List descriptors) {
363
		Collections.sort(descriptors, new Comparator() {
364
365
			public int compare(Object arg0, Object arg1) {
366
				TabDescriptor one = (TabDescriptor) arg0;
367
				TabDescriptor two = (TabDescriptor) arg1;
368
				String categoryOne = one.getCategory();
369
				String categoryTwo = two.getCategory();
370
				int categoryOnePosition = getIndex(propertyCategories.toArray(),
371
					categoryOne);
372
				int categoryTwoPosition = getIndex(propertyCategories.toArray(),
373
					categoryTwo);
374
				return categoryOnePosition - categoryTwoPosition;
375
			}
376
		});
377
		return descriptors;
378
	}
379
380
	/**
381
	 * Sorts the tab descriptors in the given list according to afterTab.
382
	 */
383
	protected List sortTabDescriptorsByAfterTab(List tabs) {
384
		if (tabs.size() == 0 || propertyCategories == null) {
385
			return tabs;
386
		}
387
		List sorted = new ArrayList();
388
		int categoryIndex = 0;
389
		for (int i = 0; i < propertyCategories.size(); i++) {
390
			List categoryList = new ArrayList();
391
			String category = (String)propertyCategories.get(i);
392
			int topOfCategory = categoryIndex;
393
			int endOfCategory = categoryIndex;
394
			while (endOfCategory < tabs.size()
395
				&& ((TabDescriptor) tabs.get(endOfCategory)).getCategory()
396
					.equals(category)) {
397
				endOfCategory++;
398
			}
399
			for (int j = topOfCategory; j < endOfCategory; j++) {
400
				TabDescriptor tab = (TabDescriptor) tabs.get(j);
401
				if (tab.getAfterTab().equals(TOP)) {
402
					categoryList.add(0, tabs.get(j));
403
				} else {
404
					categoryList.add(tabs.get(j));
405
				}
406
			}
407
			Collections.sort(categoryList, new Comparator() {
408
409
				public int compare(Object arg0, Object arg1) {
410
					TabDescriptor one = (TabDescriptor) arg0;
411
					TabDescriptor two = (TabDescriptor) arg1;
412
					if (two.getAfterTab().equals(one.getId())) {
413
						return -1;
414
					} else if (one.getAfterTab().equals(two.getId())) {
415
						return 1;
416
					} else {
417
						return 0;
418
					}
419
				}
420
			});
421
			for (int j = 0; j < categoryList.size(); j++) {
422
				sorted.add(categoryList.get(j));
423
			}
424
			categoryIndex = endOfCategory;
425
		}
426
		return sorted;
427
	}
428
429
	/**
430
	 * Gets the type mapper for the contributor.
335
	 * Gets the type mapper for the contributor.
431
	 * 
336
	 * 
432
	 * @return the type mapper for the contributor.
337
	 * @return the type mapper for the contributor.
Lines 452-459 Link Here
452
    public IActionProvider getActionProvider() {
357
    public IActionProvider getActionProvider() {
453
        return actionProvider;
358
        return actionProvider;
454
    }
359
    }
455
456
	/**
360
	/**
361
457
	 * Sets the section descriptor provider for the contributor.
362
	 * Sets the section descriptor provider for the contributor.
458
	 * 
363
	 * 
459
	 * @param sectionDescriptorProvider
364
	 * @param sectionDescriptorProvider
(-)src/org/eclipse/ui/internal/views/properties/tabbed/view/TabbedPropertyRegistryClassSectionFilter.java (-2 / +3 lines)
Lines 29-34 Link Here
29
 * IStructuredSelection and filtering is based on class.
29
 * IStructuredSelection and filtering is based on class.
30
 * 
30
 * 
31
 * @author Anthony Hunter
31
 * @author Anthony Hunter
32
 * @version 15 May 2007
32
 */
33
 */
33
public class TabbedPropertyRegistryClassSectionFilter {
34
public class TabbedPropertyRegistryClassSectionFilter {
34
35
Lines 37-43 Link Here
37
	/**
38
	/**
38
	 * constructor.
39
	 * constructor.
39
	 */
40
	 */
40
	protected TabbedPropertyRegistryClassSectionFilter(ITypeMapper typeMapper) {
41
	public TabbedPropertyRegistryClassSectionFilter(ITypeMapper typeMapper) {
41
		super();
42
		super();
42
		this.typeMapper = typeMapper;
43
		this.typeMapper = typeMapper;
43
	}
44
	}
Lines 46-52 Link Here
46
	 * Verifies if the property section extension represented by sectionElement
47
	 * Verifies if the property section extension represented by sectionElement
47
	 * applies to the given input.
48
	 * applies to the given input.
48
	 */
49
	 */
49
	protected boolean appliesToSelection(ISectionDescriptor descriptor,
50
	public boolean appliesToSelection(ISectionDescriptor descriptor,
50
			ISelection selection) {
51
			ISelection selection) {
51
52
52
		if (selection instanceof IStructuredSelection
53
		if (selection instanceof IStructuredSelection
(-)src/org/eclipse/ui/views/properties/tabbed/ITabSelectionListener.java (+3 lines)
Lines 12-22 Link Here
12
12
13
import org.eclipse.ui.internal.views.properties.tabbed.view.TabDescriptor;
13
import org.eclipse.ui.internal.views.properties.tabbed.view.TabDescriptor;
14
14
15
15
/**
16
/**
16
 * A listener interested in tab selection events that occur for the tabbed
17
 * A listener interested in tab selection events that occur for the tabbed
17
 * property sheet page.
18
 * property sheet page.
18
 * 
19
 * 
19
 * @author Anthony Hunter 
20
 * @author Anthony Hunter 
21
 * @version 21 May 2007
22
 * @deprecated use {@link ITabSelectionListener2} instead
20
 */
23
 */
21
public interface ITabSelectionListener {
24
public interface ITabSelectionListener {
22
25
(-)src/org/eclipse/ui/views/properties/tabbed/TabbedPropertySheetPage.java (-54 / +111 lines)
Lines 10-34 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.ui.views.properties.tabbed;
11
package org.eclipse.ui.views.properties.tabbed;
12
12
13
import java.util.ArrayList;
13
import java.util.*;
14
import java.util.Collection;
15
import java.util.HashMap;
16
import java.util.Iterator;
17
import java.util.List;
18
import java.util.Map;
19
14
20
import org.eclipse.core.runtime.IAdaptable;
15
import org.eclipse.core.runtime.IAdaptable;
21
import org.eclipse.core.runtime.Platform;
16
import org.eclipse.core.runtime.Platform;
22
import org.eclipse.jface.action.IAction;
17
import org.eclipse.jface.action.IAction;
23
import org.eclipse.jface.viewers.ILabelProviderListener;
18
import org.eclipse.jface.viewers.*;
24
import org.eclipse.jface.viewers.ISelection;
25
import org.eclipse.jface.viewers.ISelectionChangedListener;
26
import org.eclipse.jface.viewers.IStructuredContentProvider;
27
import org.eclipse.jface.viewers.IStructuredSelection;
28
import org.eclipse.jface.viewers.LabelProvider;
29
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
30
import org.eclipse.jface.viewers.SelectionChangedEvent;
31
import org.eclipse.jface.viewers.StructuredSelection;
32
import org.eclipse.swt.SWT;
19
import org.eclipse.swt.SWT;
33
import org.eclipse.swt.events.ControlAdapter;
20
import org.eclipse.swt.events.ControlAdapter;
34
import org.eclipse.swt.events.ControlEvent;
21
import org.eclipse.swt.events.ControlEvent;
Lines 40-60 Link Here
40
import org.eclipse.swt.layout.FormLayout;
27
import org.eclipse.swt.layout.FormLayout;
41
import org.eclipse.swt.widgets.Composite;
28
import org.eclipse.swt.widgets.Composite;
42
import org.eclipse.swt.widgets.Control;
29
import org.eclipse.swt.widgets.Control;
43
import org.eclipse.ui.IActionBars;
30
import org.eclipse.ui.*;
44
import org.eclipse.ui.IEditorPart;
45
import org.eclipse.ui.IPartListener;
46
import org.eclipse.ui.IViewPart;
47
import org.eclipse.ui.IWorkbenchPart;
48
import org.eclipse.ui.IWorkbenchWindow;
49
import org.eclipse.ui.actions.ActionFactory;
31
import org.eclipse.ui.actions.ActionFactory;
50
import org.eclipse.ui.internal.views.properties.tabbed.view.Tab;
32
import org.eclipse.ui.internal.views.properties.tabbed.view.*;
51
import org.eclipse.ui.internal.views.properties.tabbed.view.TabDescriptor;
52
import org.eclipse.ui.internal.views.properties.tabbed.view.TabListContentProvider;
53
import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyComposite;
54
import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyRegistry;
55
import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyRegistryFactory;
56
import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyTitle;
57
import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyViewer;
58
import org.eclipse.ui.part.IContributedContentsView;
33
import org.eclipse.ui.part.IContributedContentsView;
59
import org.eclipse.ui.part.Page;
34
import org.eclipse.ui.part.Page;
60
import org.eclipse.ui.views.properties.IPropertySheetPage;
35
import org.eclipse.ui.views.properties.IPropertySheetPage;
Lines 64-69 Link Here
64
 * A property sheet page that provides a tabbed UI.
39
 * A property sheet page that provides a tabbed UI.
65
 * 
40
 * 
66
 * @author Anthony Hunter
41
 * @author Anthony Hunter
42
 * @version 31 May 2007
67
 */
43
 */
68
public class TabbedPropertySheetPage
44
public class TabbedPropertySheetPage
69
	extends Page
45
	extends Page
Lines 94-100 Link Here
94
70
95
	private TabbedPropertyViewer tabbedPropertyViewer;
71
	private TabbedPropertyViewer tabbedPropertyViewer;
96
72
97
	private Tab currentTab;
73
	private TabContents currentTab;
74
	
75
	private ITabDescriptor[] currentTabs;
98
76
99
	private Map descriptorToTab;
77
	private Map descriptorToTab;
100
78
Lines 105-115 Link Here
105
	private boolean selectionQueueLocked;
83
	private boolean selectionQueueLocked;
106
84
107
	private List tabSelectionListeners;
85
	private List tabSelectionListeners;
86
	private List tabSelectionListeners2;
108
87
109
	private IWorkbenchWindow cachedWorkbenchWindow;
88
	private IWorkbenchWindow cachedWorkbenchWindow;
110
89
111
	private boolean hasTitleBar;
90
	private boolean hasTitleBar;
112
91
92
	private TabDescriptorProviderManager tabDescriptorManager;
93
113
	/**
94
	/**
114
	 * a listener that is interested in part activation events.
95
	 * a listener that is interested in part activation events.
115
	 */
96
	 */
Lines 132-137 Link Here
132
		}
113
		}
133
	};
114
	};
134
115
116
117
135
	private class TabbedPropertySheetPageContributorFromSelection
118
	private class TabbedPropertySheetPageContributorFromSelection
136
		implements ITabbedPropertySheetPageContributor {
119
		implements ITabbedPropertySheetPageContributor {
137
120
Lines 165-172 Link Here
165
		extends LabelProvider {
148
		extends LabelProvider {
166
149
167
		public String getText(Object element) {
150
		public String getText(Object element) {
168
			if (element instanceof TabDescriptor) {
151
			if (element instanceof AbstractTabDescriptor) {
169
				return ((TabDescriptor) element).getLabel();
152
				return ((ITabDescriptor) element).getLabel();
170
			}
153
			}
171
			return null;
154
			return null;
172
		}
155
		}
Lines 184-191 Link Here
184
		public void selectionChanged(SelectionChangedEvent event) {
167
		public void selectionChanged(SelectionChangedEvent event) {
185
			IStructuredSelection selection = (IStructuredSelection) event
168
			IStructuredSelection selection = (IStructuredSelection) event
186
				.getSelection();
169
				.getSelection();
187
			Tab tab = null;
170
			TabContents tab = null;
188
			TabDescriptor descriptor = (TabDescriptor) selection
171
			ITabDescriptor descriptor = (ITabDescriptor) selection
189
				.getFirstElement();
172
				.getFirstElement();
190
173
191
			if (descriptor == null) {
174
			if (descriptor == null) {
Lines 195-201 Link Here
195
				// create tab if necessary
178
				// create tab if necessary
196
				// can not cache based on the id - tabs may have the same id,
179
				// can not cache based on the id - tabs may have the same id,
197
				// but different section depending on the selection
180
				// but different section depending on the selection
198
				tab = (Tab) descriptorToTab.get(descriptor);
181
				tab = (TabContents) descriptorToTab.get(descriptor);
199
182
200
				if (tab != currentTab) {
183
				if (tab != currentTab) {
201
					hideTab(currentTab);
184
					hideTab(currentTab);
Lines 234-240 Link Here
234
		/**
217
		/**
235
		 * Shows the given tab.
218
		 * Shows the given tab.
236
		 */
219
		 */
237
		private void showTab(Tab target) {
220
		private void showTab(TabContents target) {
238
			if (target != null) {
221
			if (target != null) {
239
				Composite tabComposite = (Composite) tabToComposite.get(target);
222
				Composite tabComposite = (Composite) tabToComposite.get(target);
240
				if (tabComposite != null) {
223
				if (tabComposite != null) {
Lines 252-258 Link Here
252
		/**
235
		/**
253
		 * Hides the given tab.
236
		 * Hides the given tab.
254
		 */
237
		 */
255
		private void hideTab(Tab target) {
238
		private void hideTab(TabContents target) {
256
			if (target != null) {
239
			if (target != null) {
257
				Composite tabComposite = (Composite) tabToComposite.get(target);
240
				Composite tabComposite = (Composite) tabToComposite.get(target);
258
				if (tabComposite != null) {
241
				if (tabComposite != null) {
Lines 275-281 Link Here
275
		contributor = tabbedPropertySheetPageContributor;
258
		contributor = tabbedPropertySheetPageContributor;
276
		tabToComposite = new HashMap();
259
		tabToComposite = new HashMap();
277
		selectionQueue = new ArrayList(10);
260
		selectionQueue = new ArrayList(10);
278
		tabSelectionListeners = new ArrayList();
261
		tabSelectionListeners2 = new ArrayList();
262
		tabDescriptorManager = new TabDescriptorProviderManager();
279
		initContributor(contributor.getContributorId());
263
		initContributor(contributor.getContributorId());
280
	}
264
	}
281
265
Lines 382-387 Link Here
382
	 */
366
	 */
383
	private void initContributor(String contributorId) {
367
	private void initContributor(String contributorId) {
384
		descriptorToTab = new HashMap();
368
		descriptorToTab = new HashMap();
369
		TabbedPropertyRegistry oldRegistry = registry;
370
		
385
		if (contributor.getContributorId().equals(contributorId)) {
371
		if (contributor.getContributorId().equals(contributorId)) {
386
			/**
372
			/**
387
			 * default contributor from the workbench part.
373
			 * default contributor from the workbench part.
Lines 397-402 Link Here
397
			registry = TabbedPropertyRegistryFactory.getInstance()
383
			registry = TabbedPropertyRegistryFactory.getInstance()
398
				.createRegistry(selectionContributor);
384
				.createRegistry(selectionContributor);
399
		}
385
		}
386
		if (oldRegistry != null && !oldRegistry.equals(registry)) {
387
			tabDescriptorManager.removeTabDescriptorProvider(oldRegistry);
388
		}
389
		tabDescriptorManager.insertTabDescriptorProvider(0, registry);
390
		
400
		currentContributorId = contributorId;
391
		currentContributorId = contributorId;
401
		tabListContentProvider = getTabListContentProvider();
392
		tabListContentProvider = getTabListContentProvider();
402
		hasTitleBar = registry.getLabelProvider() != null;
393
		hasTitleBar = registry.getLabelProvider() != null;
Lines 420-426 Link Here
420
	 * @return the tab list content provider for the contributor.
411
	 * @return the tab list content provider for the contributor.
421
	 */
412
	 */
422
	protected IStructuredContentProvider getTabListContentProvider() {
413
	protected IStructuredContentProvider getTabListContentProvider() {
423
		return new TabListContentProvider(registry);
414
		return new TabListContentProvider(this);
424
	}
415
	}
425
416
426
	/**
417
	/**
Lines 543-549 Link Here
543
	}
534
	}
544
535
545
	/**
536
	/**
546
	 * Stores the current tab label in the selection queue. Tab labels are used
537
	 * Stores the current tab label in the selection queue. TabContents labels are used
547
	 * to carry the tab context from one input object to another. The queue
538
	 * to carry the tab context from one input object to another. The queue
548
	 * specifies the selection priority. So if the first tab in the queue is not
539
	 * specifies the selection priority. So if the first tab in the queue is not
549
	 * available for the input we try the second tab and so on. If none of the
540
	 * available for the input we try the second tab and so on. If none of the
Lines 579-585 Link Here
579
570
580
	private void disposeTabs(Collection tabs) {
571
	private void disposeTabs(Collection tabs) {
581
		for (Iterator iter = tabs.iterator(); iter.hasNext();) {
572
		for (Iterator iter = tabs.iterator(); iter.hasNext();) {
582
			Tab tab = (Tab) iter.next();
573
			TabContents tab = (TabContents) iter.next();
583
			Composite composite = (Composite) tabToComposite.remove(tab);
574
			Composite composite = (Composite) tabToComposite.remove(tab);
584
			tab.dispose();
575
			tab.dispose();
585
			if (composite != null) {
576
			if (composite != null) {
Lines 589-598 Link Here
589
	}
580
	}
590
581
591
	/**
582
	/**
592
	 * Returns the last known selected tab for the given input.
583
	 * Returns the last known selected tab for the current input
593
	 */
584
	 */
594
	private int getLastTabSelection(IWorkbenchPart part, ISelection input) {
585
	private int getLastTabSelection() {
595
		TabDescriptor[] descriptors = registry.getTabDescriptors(part, input);
586
		ITabDescriptor[] descriptors = currentTabs;
596
		if (descriptors.length != 0) {
587
		if (descriptors.length != 0) {
597
			for (Iterator iter = selectionQueue.iterator(); iter.hasNext();) {
588
			for (Iterator iter = selectionQueue.iterator(); iter.hasNext();) {
598
				String text = (String) iter.next();
589
				String text = (String) iter.next();
Lines 612-629 Link Here
612
	 * disposed. If the current visible tab will not be reused (i.e. will be
603
	 * disposed. If the current visible tab will not be reused (i.e. will be
613
	 * disposed) we have to send it an aboutToBeHidden() message.
604
	 * disposed) we have to send it an aboutToBeHidden() message.
614
	 */
605
	 */
615
	protected void updateTabs(TabDescriptor[] descriptors) {
606
	protected void updateTabs(ITabDescriptor[] descriptors) {
616
		Map newTabs = new HashMap(descriptors.length * 2);
607
		Map newTabs = new HashMap(descriptors.length * 2);
617
		boolean disposingCurrentTab = (currentTab != null);
608
		boolean disposingCurrentTab = (currentTab != null);
618
		for (int i = 0; i < descriptors.length; i++) {
609
		for (int i = 0; i < descriptors.length; i++) {
619
			Tab tab = (Tab) descriptorToTab.remove(descriptors[i]);
610
			TabContents tab = (TabContents) descriptorToTab.remove(descriptors[i]);
620
611
621
			if (tab != null && tab.controlsHaveBeenCreated()) {
612
			if (tab != null && tab.controlsHaveBeenCreated()) {
622
				if (tab == currentTab) {
613
				if (tab == currentTab) {
623
					disposingCurrentTab = false;
614
					disposingCurrentTab = false;
624
				}
615
				}
625
			} else {
616
			} else {
626
				tab = (descriptors[i]).createTab();
617
				tab = createTab(descriptors[i]);
627
			}
618
			}
628
619
629
			newTabs.put(descriptors[i], tab);
620
			newTabs.put(descriptors[i], tab);
Lines 641-646 Link Here
641
	}
632
	}
642
633
643
	/**
634
	/**
635
	 * Creates a new {@link TabContents} for the given tabDescriptor
636
	 * @param aDescriptor the descriptor to create the new TabContents for
637
	 * @return the new TabContents
638
	 */
639
	protected TabContents createTab(ITabDescriptor tabDescriptor) {
640
		return tabDescriptor.createTab();
641
	}
642
643
	/**
644
	 * Helper method for creating property tab composites.
644
	 * Helper method for creating property tab composites.
645
	 */
645
	 */
646
	private Composite createTabComposite() {
646
	private Composite createTabComposite() {
Lines 670-686 Link Here
670
670
671
		// see if the selection provides a new contributor
671
		// see if the selection provides a new contributor
672
		validateRegistry(selection);
672
		validateRegistry(selection);
673
		TabDescriptor[] descriptors = registry.getTabDescriptors(part,
673
		ITabDescriptor[] descriptors = getTabDescriptorsForSelection(part, currentSelection);
674
			currentSelection);
675
		// If there are no descriptors for the given input we do not need to
674
		// If there are no descriptors for the given input we do not need to
676
		// touch the tab objects. We might reuse them for the next valid
675
		// touch the tab objects. We might reuse them for the next valid
677
		// input.
676
		// input.
678
		if (descriptors.length > 0) {
677
		if (descriptors.length > 0) {
679
			updateTabs(descriptors);
678
			updateTabs(descriptors);
680
		}
679
		}
680
		// update the content provider, which must return exactly the above descriptors
681
		currentTabs = descriptors;
682
		
681
		// update tabs list
683
		// update tabs list
682
		tabbedPropertyViewer.setInput(part, currentSelection);
684
		tabbedPropertyViewer.setInput(part, currentSelection);
683
		int lastTabSelectionIndex = getLastTabSelection(part, currentSelection);
685
		int lastTabSelectionIndex = getLastTabSelection();
684
		Object selectedTab = tabbedPropertyViewer
686
		Object selectedTab = tabbedPropertyViewer
685
			.getElementAt(lastTabSelectionIndex);
687
			.getElementAt(lastTabSelectionIndex);
686
		selectionQueueLocked = true;
688
		selectionQueueLocked = true;
Lines 698-703 Link Here
698
	}
700
	}
699
701
700
	/**
702
	/**
703
	 * Returns the {@link ITabDescriptor} applicable to the given part and selection.
704
	 * These descriptors will be used and shown in the property sheet.
705
	 * @param part
706
	 * @param currentSelection
707
	 * @return The tab descriptors for the given selection 
708
	 */
709
	protected ITabDescriptor[] getTabDescriptorsForSelection(IWorkbenchPart part, ISelection currentSelection) {
710
		ITabDescriptor[] descriptors = tabDescriptorManager.getTabDescriptors(part,
711
				currentSelection);
712
		return descriptors;
713
	}
714
715
	/**
701
	 * Refresh the currently active tab.
716
	 * Refresh the currently active tab.
702
	 */
717
	 */
703
	public void refresh() {
718
	public void refresh() {
Lines 709-733 Link Here
709
	 * 
724
	 * 
710
	 * @return the currently active tab.
725
	 * @return the currently active tab.
711
	 */
726
	 */
712
	public Tab getCurrentTab() {
727
	public TabContents getCurrentTab() {
713
		return currentTab;
728
		return currentTab;
714
	}
729
	}
715
730
716
	/**
731
	/**
732
	 * @return Returns the descriptors for the currently used tabs
733
	 */
734
	public ITabDescriptor[] getCurrentTabs() {
735
		return currentTabs;
736
	}
737
	
738
	/**
717
	 * Handle the tab selected change event.
739
	 * Handle the tab selected change event.
718
	 * 
740
	 * 
719
	 * @param tabDescriptor
741
	 * @param tabDescriptor
720
	 *            the new selected tab.
742
	 *            the new selected tab.
721
	 */
743
	 */
722
	private void handleTabSelection(TabDescriptor tabDescriptor) {
744
	private void handleTabSelection(ITabDescriptor tabDescriptor) {
723
		if (selectionQueueLocked) {
745
		if (selectionQueueLocked) {
724
			/*
746
			/*
725
			 * don't send tab selection events for non user changes.
747
			 * don't send tab selection events for non user changes.
726
			 */
748
			 */
727
			return;
749
			return;
728
		}
750
		}
729
		for (Iterator i = tabSelectionListeners.iterator(); i.hasNext();) {
751
		if (tabSelectionListeners != null && tabDescriptor instanceof TabDescriptor) {
730
			ITabSelectionListener listener = (ITabSelectionListener) i.next();
752
			for (Iterator i = tabSelectionListeners.iterator(); i.hasNext();) {
753
				ITabSelectionListener listener = (ITabSelectionListener) i.next();
754
				listener.tabSelected((TabDescriptor) tabDescriptor);
755
			}
756
		}
757
		
758
		for (Iterator i = tabSelectionListeners2.iterator(); i.hasNext();) {
759
			ITabSelectionListener2 listener = (ITabSelectionListener2) i.next();
731
			listener.tabSelected(tabDescriptor);
760
			listener.tabSelected(tabDescriptor);
732
		}
761
		}
733
	}
762
	}
Lines 737-744 Link Here
737
	 * 
766
	 * 
738
	 * @param listener
767
	 * @param listener
739
	 *            a tab selection listener.
768
	 *            a tab selection listener.
769
	 * @deprecated use {@link #addTabSelectionListener(ITabSelectionListener2)} instead
740
	 */
770
	 */
741
	public void addTabSelectionListener(ITabSelectionListener listener) {
771
	public void addTabSelectionListener(ITabSelectionListener listener) {
772
		if (tabSelectionListeners == null) {
773
			tabSelectionListeners = new ArrayList();
774
		}
742
		tabSelectionListeners.add(listener);
775
		tabSelectionListeners.add(listener);
743
	}
776
	}
744
777
Lines 747-755 Link Here
747
	 * 
780
	 * 
748
	 * @param listener
781
	 * @param listener
749
	 *            a tab selection listener.
782
	 *            a tab selection listener.
783
	 * @deprecated use {@link #removeTabSelectionListener(ITabSelectionListener2)}
750
	 */
784
	 */
751
	public void removeTabSelectionListener(ITabSelectionListener listener) {
785
	public void removeTabSelectionListener(ITabSelectionListener listener) {
752
		tabSelectionListeners.remove(listener);
786
		tabSelectionListeners.remove(listener);
787
		if (tabSelectionListeners.isEmpty()) {
788
			tabSelectionListeners = null;
789
		}
790
	}
791
	
792
	/**
793
	 * Add a tab selection listener.
794
	 * 
795
	 * @param listener
796
	 *            a tab selection listener.
797
	 */
798
	public void addTabSelectionListener(ITabSelectionListener2 listener) {
799
		tabSelectionListeners2.add(listener);
800
	}
801
802
	/**
803
	 * Remove a tab selection listener.
804
	 * 
805
	 * @param listener
806
	 *            a tab selection listener.
807
	 */
808
	public void removeTabSelectionListener(ITabSelectionListener2 listener) {
809
		tabSelectionListeners2.remove(listener);
753
	}
810
	}
754
811
755
	/**
812
	/**
(-)src/org/eclipse/ui/views/properties/tabbed/TabContents.java (+239 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2001, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.ui.views.properties.tabbed;
12
13
import org.eclipse.core.runtime.ISafeRunnable;
14
import org.eclipse.core.runtime.Platform;
15
import org.eclipse.jface.viewers.ISelection;
16
import org.eclipse.swt.SWT;
17
import org.eclipse.swt.layout.FillLayout;
18
import org.eclipse.swt.layout.GridData;
19
import org.eclipse.swt.layout.GridLayout;
20
import org.eclipse.swt.widgets.Composite;
21
import org.eclipse.ui.IWorkbenchPart;
22
23
/**
24
 * A property tab is composed by one or more property sections and is used to
25
 * categorize sections.
26
 * 
27
 * @author Anthony Hunter
28
 * @version 14 May 2007
29
 */
30
public class TabContents {
31
32
    private ISection[] sections;
33
34
    private boolean controlsCreated;
35
36
    public TabContents() {
37
        controlsCreated = false;
38
    }
39
40
    /**
41
     * Retrieve a numbered index for the section.
42
     * @param section the section.
43
     * @return the section index.
44
     */
45
    public int getSectionIndex(ISection section) {
46
        for (int i = 0; i < sections.length; i++) {
47
			if (section == sections[i]) {
48
				return i;
49
			}
50
		}
51
        return -1;
52
    }
53
54
    /**
55
     * Retrieve the section at a numbered index.
56
     * @param i a numbered index.
57
     * @return the section.
58
     */
59
    public ISection getSectionAtIndex(int i) {
60
        if (i >= 0 && i < sections.length) {
61
			return sections[i];
62
		}
63
        return null;
64
    }
65
66
    /**
67
     * Retrieve the sections on the tab.
68
     * 
69
     * @return the sections on the tab.
70
     */
71
    public ISection[] getSections() {
72
        return sections;
73
    }
74
75
    /**
76
     * Creates page's sections controls.
77
     * 
78
     * @param parent
79
     * @param page
80
     */
81
    public void createControls(Composite parent,
82
            final TabbedPropertySheetPage page) {
83
        Composite pageComposite = page.getWidgetFactory().createComposite(
84
            parent, SWT.NO_FOCUS);
85
        GridLayout layout = new GridLayout();
86
        layout.marginWidth = 0;
87
        layout.marginHeight = 0;
88
        layout.verticalSpacing = 0;
89
        pageComposite.setLayout(layout);
90
91
        for (int i = 0; i < sections.length; i++) {
92
            final ISection section = sections[i];
93
            final Composite sectionComposite = page.getWidgetFactory()
94
                .createComposite(pageComposite, SWT.NO_FOCUS);
95
            sectionComposite.setLayout(new FillLayout());
96
            int style = (section.shouldUseExtraSpace()) ? GridData.FILL_BOTH
97
                : GridData.FILL_HORIZONTAL;
98
            GridData data = new GridData(style);
99
            data.heightHint = section.getMinimumHeight();
100
            sectionComposite.setLayoutData(data);
101
102
            ISafeRunnable runnable = new ISafeRunnable() {
103
104
                public void run()
105
                    throws Exception {
106
                    section.createControls(sectionComposite, page);
107
                }
108
109
                public void handleException(Throwable exception) {
110
                    /* not used */
111
                }
112
            };
113
            Platform.run(runnable);
114
        }
115
        controlsCreated = true;
116
    }
117
118
    /**
119
     * Dispose of page's sections controls.
120
     */
121
    public void dispose() {
122
        for (int i = 0; i < sections.length; i++) {
123
            final ISection section = sections[i];
124
            ISafeRunnable runnable = new ISafeRunnable() {
125
126
                public void run()
127
                    throws Exception {
128
                    section.dispose();
129
                }
130
131
                public void handleException(Throwable exception) {
132
                    /* not used */
133
                }
134
            };
135
            Platform.run(runnable);
136
        }
137
    }
138
139
    /**
140
     * Sends the lifecycle event to the page's sections.
141
     */
142
    public void aboutToBeShown() {
143
        for (int i = 0; i < sections.length; i++) {
144
            final ISection section = sections[i];
145
            ISafeRunnable runnable = new ISafeRunnable() {
146
147
                public void run()
148
                    throws Exception {
149
                    section.aboutToBeShown();
150
                }
151
152
                public void handleException(Throwable exception) {
153
                    /* not used */
154
                }
155
            };
156
            Platform.run(runnable);
157
        }
158
    }
159
160
    /**
161
     * Sends the lifecycle event to the page's sections.
162
     */
163
    public void aboutToBeHidden() {
164
        for (int i = 0; i < sections.length; i++) {
165
            final ISection section = sections[i];
166
            ISafeRunnable runnable = new ISafeRunnable() {
167
168
                public void run()
169
                    throws Exception {
170
                    section.aboutToBeHidden();
171
                }
172
173
                public void handleException(Throwable exception) {
174
                    /* not used */
175
                }
176
            };
177
            Platform.run(runnable);
178
        }
179
    }
180
181
    /**
182
     * Sets page's sections input objects.
183
     * 
184
     * @param part
185
     * @param selection
186
     */
187
    public void setInput(final IWorkbenchPart part, final ISelection selection) {
188
        for (int i = 0; i < sections.length; i++) {
189
            final ISection section = sections[i];
190
            ISafeRunnable runnable = new ISafeRunnable() {
191
192
                public void run()
193
                    throws Exception {
194
                    section.setInput(part, selection);
195
                }
196
197
                public void handleException(Throwable throwable) {
198
                    throwable.printStackTrace();
199
                }
200
            };
201
            Platform.run(runnable);
202
        }
203
    }
204
205
    public void setSections(ISection[] sections) {
206
        this.sections = sections;
207
    }
208
209
    /**
210
     * 
211
     * @return <code>true</code> if controls have been created.
212
     */
213
    public boolean controlsHaveBeenCreated() {
214
        return controlsCreated;
215
    }
216
217
    /**
218
     * If controls have been created, refresh all sections on the page.
219
     */
220
    public void refresh() {
221
        if (controlsCreated) {
222
            for (int i = 0; i < sections.length; i++) {
223
                final ISection section = sections[i];
224
                ISafeRunnable runnable = new ISafeRunnable() {
225
226
                    public void run()
227
                        throws Exception {
228
                        section.refresh();
229
                    }
230
231
                    public void handleException(Throwable throwable) {
232
                        throwable.printStackTrace();
233
                    }
234
                };
235
                Platform.run(runnable);
236
            }
237
        }
238
    }
239
}
(-)src/org/eclipse/ui/views/properties/tabbed/AbstractSectionDescriptor.java (+207 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2001, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.ui.views.properties.tabbed;
12
13
import java.util.Collections;
14
import java.util.List;
15
16
import org.eclipse.core.runtime.CoreException;
17
import org.eclipse.core.runtime.IStatus;
18
import org.eclipse.core.runtime.Status;
19
import org.eclipse.jface.viewers.IFilter;
20
import org.eclipse.jface.viewers.ISelection;
21
import org.eclipse.ui.IWorkbenchPart;
22
import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewPlugin;
23
import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewStatusCodes;
24
import org.eclipse.ui.internal.views.properties.tabbed.l10n.TabbedPropertyMessages;
25
import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyRegistryClassSectionFilter;
26
27
import com.ibm.icu.text.MessageFormat;
28
29
/**
30
 * Represents the default implementation of a section descriptor on the tabbed
31
 * property sections extensions. This implementation assumes that we are
32
 * interested in selected objects in an IStructuredSelection.
33
 * 
34
 * The id and targetTab properties are mandatory and must not be null. 
35
 * 
36
 * @author Anthony Hunter
37
 * @version 31 May 2007
38
 */
39
public abstract class AbstractSectionDescriptor
40
	implements ISectionDescriptor {
41
42
	private final static String SECTION_ERROR = TabbedPropertyMessages.SectionDescriptor_Section_error;
43
44
	private static final String TOP = "top"; //$NON-NLS-1$
45
46
	private String id;
47
48
	private String targetTab;
49
50
	private String afterSection;
51
52
	private TabbedPropertyRegistryClassSectionFilter classFilter;
53
54
	private IFilter filter;
55
56
	private int enablesFor = ENABLES_FOR_ANY;
57
58
	/**
59
	 * Constructor for the section descriptor.
60
	 * 
61
	 * @param id 
62
	 * 			The id of this section descriptor (must not be null).
63
	 * @param targetTab 
64
	 * 			The tab that this section applies to (must not be null).
65
	 * @param typeMapper
66
	 *          The type mapper.
67
	 */
68
	protected AbstractSectionDescriptor(String id, String targetTab, ITypeMapper typeMapper) {
69
		this();
70
		classFilter = new TabbedPropertyRegistryClassSectionFilter(typeMapper);
71
		this.id = id;
72
		this.targetTab = targetTab;
73
74
		if (id == null || targetTab == null) {
75
			// the section id and tab are mandatory - log error
76
			handleSectionError(null);
77
		}
78
	}
79
80
	/**
81
	 * Creates a new section descriptor. It is the resposibility of the subclass to ensure
82
	 * that at least a valid id and targetTab are set afterwards.
83
	 * @see #setId(String)
84
	 * @see #setTargetTab(String)
85
	 */
86
	protected AbstractSectionDescriptor() {
87
		afterSection = TOP;
88
	}
89
90
	/**
91
	 * Handle the section error when an issue is found loading from the
92
	 * configuration element.
93
	 * 
94
	 * @param exception
95
	 *            an optional CoreException
96
	 */
97
	private void handleSectionError(CoreException exception) {
98
		String pluginId = TabbedPropertyViewPlugin.getPlugin().getBundle().getSymbolicName(); 
99
		String message = MessageFormat.format(SECTION_ERROR,
100
			new Object[] {pluginId});
101
		IStatus status = new Status(IStatus.ERROR, pluginId,
102
			TabbedPropertyViewStatusCodes.SECTION_ERROR, message, exception);
103
		TabbedPropertyViewPlugin.getPlugin().getLog().log(status);
104
	}
105
106
	/**
107
	 * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getId()
108
	 */
109
	public String getId() {
110
		return id;
111
	}
112
113
	/**
114
	 * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getFilter()
115
	 */
116
	public IFilter getFilter() {
117
		return filter;
118
	}
119
	
120
	/**
121
	 * @param aEnablesFor The enablesFor to set.
122
	 */
123
	public void setEnablesFor(int enablesFor) {
124
		this.enablesFor = enablesFor;
125
	}
126
	
127
	/**
128
	 * Retrieves the value for section enablement which is a precise number of
129
	 * items selected. For example: enablesFor=" 4" enables the action only when
130
	 * 4 items are selected. If not specified, enable for all selections.
131
	 * 
132
	 * @return the value for section enablement.
133
	 */
134
	public int getEnablesFor() {
135
		return enablesFor;
136
	}
137
138
	/**
139
	 * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getTargetTab()
140
	 */
141
	public String getTargetTab() {
142
		return targetTab;
143
	}
144
145
	/**
146
	 * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#appliesTo(org.eclipse.ui.IWorkbenchPart,
147
	 *      org.eclipse.jface.viewers.ISelection)
148
	 */
149
	public boolean appliesTo(IWorkbenchPart part, ISelection selection) {
150
		return classFilter.appliesToSelection(this, selection);
151
	}
152
153
	/**
154
	 * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getAfterSection()
155
	 */
156
	public String getAfterSection() {
157
		return afterSection;
158
	}
159
160
	/**
161
	 * @see java.lang.Object#toString()
162
	 */
163
	public String toString() {
164
		return getId();
165
	}
166
	
167
	/**
168
	 * @param id The id to set (must not be null).
169
	 */
170
	protected void setId(String id) {
171
		if (id == null) {
172
			throw new IllegalArgumentException("id must not be null"); //$NON-NLS-1$
173
		}
174
		
175
		this.id = id;
176
	}
177
	
178
	/**
179
	 * @param targetTab The targetTab to set (must not be null).
180
	 */
181
	protected void setTargetTab(String targetTab) {
182
		if (targetTab == null) {
183
			throw new IllegalArgumentException("targetTab must not be null"); //$NON-NLS-1$
184
		}
185
		this.targetTab = targetTab;
186
	}
187
	
188
	protected void setTypeMapper(ITypeMapper typeMapper) {
189
		classFilter = new TabbedPropertyRegistryClassSectionFilter(typeMapper);
190
	}
191
192
	/**
193
	 * @param aAfterSection The afterSection to set.
194
	 */
195
	protected void setAfterSection(String afterSection) {
196
		this.afterSection = afterSection;
197
	}
198
	
199
	/* (non-Javadoc)
200
	 * @see org.eclipse.ui.views.properties.tabbed.ISectionDescriptor#getInputTypes()
201
	 * Returns an empty list by default. Actually only applicable to subclass SectionDescriptor
202
	 * but already released in ISectionDescriptor
203
	 */
204
	public List getInputTypes() {
205
		return Collections.EMPTY_LIST;
206
	}
207
}
(-)src/org/eclipse/ui/views/properties/tabbed/ITabSelectionListener2.java (+31 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2001, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.ui.views.properties.tabbed;
12
13
14
15
/**
16
 * A listener interested in tab selection events that occur for the tabbed
17
 * property sheet page.
18
 * 
19
 * @author Anthony Hunter 
20
 * @version 21 May 2007
21
 */
22
public interface ITabSelectionListener2 {
23
24
	/**
25
	 * Notifies this listener that the selected tab has changed.
26
	 * 
27
	 * @param tabDescriptor
28
	 *            the selected tab descriptor.
29
	 */
30
	public void tabSelected(ITabDescriptor tabDescriptor);
31
}
(-)src/org/eclipse/ui/views/properties/tabbed/AbstractTabDescriptor.java (+415 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2001, 2006 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.ui.views.properties.tabbed;
12
13
import java.util.ArrayList;
14
import java.util.Iterator;
15
import java.util.List;
16
17
import org.eclipse.core.runtime.CoreException;
18
import org.eclipse.core.runtime.IStatus;
19
import org.eclipse.core.runtime.Status;
20
import org.eclipse.swt.graphics.Image;
21
import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewPlugin;
22
import org.eclipse.ui.internal.views.properties.tabbed.TabbedPropertyViewStatusCodes;
23
import org.eclipse.ui.internal.views.properties.tabbed.l10n.TabbedPropertyMessages;
24
25
import com.ibm.icu.text.MessageFormat;
26
27
/**
28
 * Realizes the base implementation of a tab descriptor on the tabbed
29
 * property tabs extensions.
30
 * 
31
 * Clients should subclass this class instead of implementing ITabDescriptor directly. 
32
 * 
33
 * The id, label, category and section descriptors properties are mandatory and must not be null.
34
 * 
35
 * @author Anthony Hunter
36
 * @version 31 May 2007
37
 */
38
public abstract class AbstractTabDescriptor
39
	implements Cloneable, ITabItem, ITabDescriptor {
40
41
	public static final String TOP = "top"; //$NON-NLS-1$
42
43
	private final static String TAB_ERROR = TabbedPropertyMessages.TabDescriptor_Tab_error;
44
45
	private String id;
46
47
	private String label;
48
49
	private Image image;
50
51
	private boolean selected;
52
53
	private boolean indented;
54
55
	private String category;
56
57
	private String afterTab;
58
59
	private List sectionDescriptors;
60
61
	/**
62
	 * Constructor for AbstractTabDescriptor.
63
	 * @param id
64
	 * 			The id of this tab (must not be null)
65
	 * @param label
66
	 * 			The label for this tab (must not be null)
67
	 * @param category
68
	 * 			The category this tab belongs to (must not be null)
69
	 */
70
	protected AbstractTabDescriptor(String id, String label, String category) {
71
		this();
72
		
73
		this.id = id;
74
		this.label = label;
75
		this.category = category;
76
		if (id == null || label == null || category == null) {
77
			// the tab id, label and category are mandatory - log error
78
			String pluginId = TabbedPropertyViewPlugin.getPlugin().getBundle().getSymbolicName();
79
			handleTabError(pluginId, null);
80
		}
81
	}
82
83
	/**
84
	 * Creates a new AbstractTabDescriptor.
85
	 * It is the resposibility of the subclass to ensure
86
	 * that at least a valid id, label, category a section descriptors are set afterwards.
87
	 * @see #setId(String)
88
	 * @see #setCategory(String)
89
	 * @see #setSectionDescriptors(List)
90
	 */
91
	protected AbstractTabDescriptor() {
92
		afterTab = TOP;
93
		sectionDescriptors = new ArrayList(5);
94
		selected = false;
95
	}
96
	
97
	/* (non-Javadoc)
98
	 * @see org.eclipse.ui.internal.views.properties.tabbed.view.ITabDescriptor#getId()
99
	 */
100
	public String getId() {
101
		return id;
102
	}
103
104
	/**
105
	 * @param aId The id to set (must not be null).
106
	 */
107
	protected void setId(String id) {
108
		if (id == null) {
109
			throw new IllegalArgumentException("id must not be null"); //$NON-NLS-1$
110
		}
111
		
112
		this.id = id;
113
	}
114
	
115
	/* (non-Javadoc)
116
	 * @see org.eclipse.ui.internal.views.properties.tabbed.view.ITabDescriptor#getLabel()
117
	 */
118
	public String getLabel() {
119
		return label;
120
	}
121
122
	/**
123
	 * Get the identifier of the tab after which this tab should be displayed.
124
	 * When two or more tabs belong to the same category, they are sorted by the
125
	 * after tab values.
126
	 * 
127
	 * @return the identifier of the tab.
128
	 */
129
	public String getAfterTab() {
130
		return afterTab;
131
	}
132
133
	/**
134
	 * Get the category this tab belongs to.
135
	 * 
136
	 * @return Get the category this tab belongs to.
137
	 */
138
	public String getCategory() {
139
		return category;
140
	}
141
142
	/**
143
	 * Returns whether the given section was added to this tab. The section can
144
	 * be appended if its tab attribute matches the tab id. The afterSection
145
	 * attribute indicates the order in which the section should be appended.
146
	 * 
147
	 * @param target
148
	 *            the section descriptor to append.
149
	 */
150
	public boolean append(ISectionDescriptor target) {
151
		if (!target.getTargetTab().equals(id)) {
152
			return false;
153
		}
154
155
		if (insertSectionDescriptor(target)) {
156
			return true;
157
		}
158
159
		sectionDescriptors.add(target);
160
		return true;
161
	}
162
163
	/**
164
	 * Insert the section descriptor into the section descriptor list.
165
	 * 
166
	 * @param target
167
	 *            the section descriptor to insert.
168
	 * @return <code>true</code> if the target descriptor was added to the
169
	 *         descriptors list.
170
	 */
171
	private boolean insertSectionDescriptor(ISectionDescriptor target) {
172
		if (target.getAfterSection().equals(TOP)) {
173
			sectionDescriptors.add(0, target);
174
			return true;
175
		}
176
		for (int i = 0; i < sectionDescriptors.size(); i++) {
177
			ISectionDescriptor descriptor = (ISectionDescriptor) sectionDescriptors
178
				.get(i);
179
			if (target.getAfterSection().equals(descriptor.getId())) {
180
				sectionDescriptors.add(i + 1, target);
181
				return true;
182
			} else {
183
				if (descriptor.getAfterSection().equals(target.getId())) {
184
					sectionDescriptors.add(i, target);
185
					return true;
186
				}
187
			}
188
		}
189
		return false;
190
	}
191
192
	/* (non-Javadoc)
193
	 * @see org.eclipse.ui.internal.views.properties.tabbed.view.ITabDescriptor#createTab()
194
	 */
195
	public TabContents createTab() {
196
		List sections = new ArrayList(sectionDescriptors.size());
197
		for (Iterator iter = sectionDescriptors.iterator(); iter.hasNext();) {
198
			ISectionDescriptor descriptor = (ISectionDescriptor) iter.next();
199
			ISection section = descriptor.getSectionClass();
200
			sections.add(section);
201
		}
202
		TabContents tab = new TabContents();
203
		tab.setSections((ISection[]) sections.toArray(new ISection[sections
204
			.size()]));
205
		return tab;
206
	}
207
208
	/**
209
	 * Get the list of section descriptors for the tab.
210
	 * 
211
	 * @return the list of section descriptors for the tab.
212
	 */
213
	public List getSectionDescriptors() {
214
		return sectionDescriptors;
215
	}
216
217
	/**
218
	 * Set the list of section descriptors for the tab.
219
	 * 
220
	 * @param sectionDescriptors
221
	 *            the list of section descriptors for the tab.
222
	 */
223
	protected void setSectionDescriptors(List sectionDescriptors) {
224
		this.sectionDescriptors = sectionDescriptors;
225
	}
226
227
	/**
228
	 * @see java.lang.Object#toString()
229
	 */
230
	public String toString() {
231
		return getId();
232
	}
233
234
	/**
235
	 * Handle the tab error when an issue is found loading from the
236
	 * configuration element.
237
	 * 
238
	 * @param configurationElement
239
	 *            the configuration element
240
	 * @param exception
241
	 *            an optional CoreException
242
	 */
243
	protected void handleTabError(String pluginId, CoreException exception) {
244
		String message = MessageFormat.format(TAB_ERROR,
245
			new Object[] {pluginId});
246
		IStatus status = new Status(IStatus.ERROR, pluginId,
247
			TabbedPropertyViewStatusCodes.TAB_ERROR, message, exception);
248
		TabbedPropertyViewPlugin.getPlugin().getLog().log(status);
249
	}
250
251
	/**
252
	 * @see java.lang.Object#equals(java.lang.Object)
253
	 */
254
	public boolean equals(Object object) {
255
		if (this == object) {
256
			return true;
257
		}
258
259
		if (this.getClass() == object.getClass()) {
260
			AbstractTabDescriptor descriptor = (AbstractTabDescriptor) object;
261
			if (this.getCategory().equals(descriptor.getCategory())
262
				&& this.getId().equals(descriptor.getId())
263
				&& this.getSectionDescriptors().size() == descriptor
264
					.getSectionDescriptors().size()) {
265
266
				Iterator i = this.getSectionDescriptors().iterator();
267
				Iterator j = descriptor.getSectionDescriptors().iterator();
268
269
				// the order is importent here - so as long as the sizes of the
270
				// lists are the same and id of the section at the same
271
				// positions are the same - the lists are the same
272
				while (i.hasNext()) {
273
					ISectionDescriptor source = (ISectionDescriptor) i.next();
274
					ISectionDescriptor target = (ISectionDescriptor) j.next();
275
					if (!source.getId().equals(target.getId())) {
276
						return false;
277
					}
278
				}
279
280
				return true;
281
			}
282
283
		}
284
285
		return false;
286
	}
287
288
	/**
289
	 * @see java.lang.Object#hashCode()
290
	 */
291
	public int hashCode() {
292
293
		int hashCode = getCategory().hashCode();
294
		hashCode ^= getId().hashCode();
295
		Iterator i = this.getSectionDescriptors().iterator();
296
		while (i.hasNext()) {
297
			ISectionDescriptor section = (ISectionDescriptor) i.next();
298
			hashCode ^= section.getId().hashCode();
299
		}
300
		return hashCode;
301
	}
302
303
	/**
304
	 * @see java.lang.Object#clone()
305
	 */
306
	public Object clone() {
307
		try {
308
			return super.clone();
309
		} catch (CloneNotSupportedException exception) {
310
			IStatus status = new Status(IStatus.ERROR, TabbedPropertyViewPlugin
311
				.getPlugin().getBundle().getSymbolicName(), 666, exception
312
				.getMessage(), exception);
313
			TabbedPropertyViewPlugin.getPlugin().getLog().log(status);
314
		}
315
		return null;
316
	}
317
318
	/**
319
	 * @param afterTab The id of another tab that should appear before this tab
320
	 */
321
	protected void setAfterTab(String afterTab) {
322
		if (afterTab == null) {
323
			this.afterTab = TOP;
324
		} else {
325
			this.afterTab = afterTab;
326
		}
327
	}
328
	
329
	/**
330
	 * @param category The category this tab belongs to (must not be null).
331
	 */
332
	protected void setCategory(String category) {
333
		if (category == null) {
334
			throw new IllegalArgumentException("category must not be null"); //$NON-NLS-1$
335
		}
336
		
337
		this.category = category;
338
	}
339
	
340
	/**
341
	 * Set the image for the tab.
342
	 * 
343
	 * @param image
344
	 *            the image for the tab.
345
	 */
346
	protected void setImage(Image image) {
347
		this.image = image;
348
	}
349
350
	/**
351
	 * Set the indicator to determine if the tab should be displayed as
352
	 * indented.
353
	 * 
354
	 * @param indented
355
	 *            <code>true</code> if the tab should be displayed as
356
	 *            indented.
357
	 */
358
	protected void setIndented(boolean indented) {
359
		this.indented = indented;
360
	}
361
362
	/**
363
	 * Set the indicator to determine if the tab should be the selected tab in
364
	 * the list.
365
	 * 
366
	 * @param selected
367
	 *            <code>true</code> if the tab should be the selected tab in
368
	 *            the list.
369
	 */
370
	protected void setSelected(boolean selected) {
371
		this.selected = selected;
372
	}
373
374
	/**
375
	 * Set the text label for the tab (must not be null).
376
	 * 
377
	 * @param label
378
	 *            the text label for the tab.
379
	 */
380
	protected void setLabel(String label) {
381
		if (label == null) {
382
			throw new IllegalArgumentException("label must not be null"); //$NON-NLS-1$
383
		}
384
		
385
		this.label = label;
386
	}
387
388
	/* (non-Javadoc)
389
	 * @see org.eclipse.ui.internal.views.properties.tabbed.view.ITabDescriptor#getImage()
390
	 */
391
	public Image getImage() {
392
		return image;
393
	}
394
395
	/* (non-Javadoc)
396
	 * @see org.eclipse.ui.internal.views.properties.tabbed.view.ITabDescriptor#isSelected()
397
	 */
398
	public boolean isSelected() {
399
		return selected;
400
	}
401
402
	/* (non-Javadoc)
403
	 * @see org.eclipse.ui.internal.views.properties.tabbed.view.ITabDescriptor#isIndented()
404
	 */
405
	public boolean isIndented() {
406
		return indented;
407
	}
408
409
	/* (non-Javadoc)
410
	 * @see org.eclipse.ui.internal.views.properties.tabbed.view.ITabDescriptor#getText()
411
	 */
412
	public String getText() {
413
		return label;
414
	}
415
}
(-)src/org/eclipse/ui/views/properties/tabbed/ITabDescriptorProvider.java (+37 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.ui.views.properties.tabbed;
13
14
import org.eclipse.core.runtime.IAdaptable;
15
import org.eclipse.jface.viewers.ISelection;
16
import org.eclipse.ui.IWorkbenchPart;
17
18
19
/**
20
 * This interface may be implemented clients who wish to dynamically provide 
21
 * ITabDescriptors instead of registering them statically with the extension 
22
 * point org.eclipse.ui.views.properties.tabbed.propertyTabs.
23
 * The tabbed properties view queries the current selection for instances of
24
 * this interface, both directly and through the {@link IAdaptable} mechanism.
25
 * 
26
 * @since 3.4
27
 * @version 31 May 2007
28
 */
29
public interface ITabDescriptorProvider {
30
	/**
31
	 * Returns the descriptors for the tabs to be shown for the given selection.
32
	 * Note that "this" may actually be part of or derived from the selection.
33
	 * @return the {@link ITabDescriptor} to be shown in the tabbed properties view
34
	 * TODO: really pass part and selection? "this" may actually be part of the selection...
35
	 */
36
	public ITabDescriptor[] getTabDescriptors(IWorkbenchPart currentPart, ISelection currentSelection);
37
}
(-)src/org/eclipse/ui/views/properties/tabbed/ITabDescriptor.java (+91 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.ui.views.properties.tabbed;
13
14
import java.util.List;
15
16
import org.eclipse.swt.graphics.Image;
17
18
/**
19
 * <p>
20
 * Not intended to be implemented by clients. Clients should subclass 
21
 * <code>AbstractTabDescriptor</code> instead.
22
 * </p>
23
 * @since 3.4
24
 * @version 21 May 2007
25
 * @see AbstractTabDescriptor
26
 */
27
public interface ITabDescriptor {
28
29
	/**
30
	 * Get the unique identifier for the tab.
31
	 * 
32
	 * @return the unique identifier for the tab.
33
	 */
34
	public String getId();
35
36
	/**
37
	 * Get the text label for the tab.
38
	 * 
39
	 * @return the text label for the tab.
40
	 */
41
	public String getLabel();
42
43
	/**
44
	 * Instantiate this tab's sections.
45
	 */
46
	public TabContents createTab();
47
48
	/**
49
	 * Get the image for the tab.
50
	 * 
51
	 * @return the image for the tab.
52
	 */
53
	public Image getImage();
54
55
	/**
56
	 * Determine if the tab is selected.
57
	 * 
58
	 * @return <code>true</code> if the tab is selected.
59
	 */
60
	public boolean isSelected();
61
62
	/**
63
	 * Determine if the tab should be displayed as indented.
64
	 * 
65
	 * @return <code>true</code> if the tab should be displayed as indented.
66
	 */
67
	public boolean isIndented();
68
69
	/**
70
	 * Get the text label for the tab.
71
	 * TODO: why getText() and getLabel()?
72
	 * 
73
	 * @return the text label for the tab.
74
	 */
75
	public String getText();
76
	
77
	/**
78
	 * Get the list of section descriptors for the tab.
79
	 * 
80
	 * @return the list of section descriptors for the tab.
81
	 * TODO: probably arrayify this
82
	 */
83
	public List getSectionDescriptors();
84
	
85
	/**
86
	 * Get the category this tab belongs to.
87
	 * 
88
	 * @return Get the category this tab belongs to.
89
	 */
90
	public String getCategory();
91
}
(-)src/org/eclipse/ui/internal/views/properties/tabbed/view/TabDescriptorProviderManager.java (+269 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2007 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 ******************************************************************************/
11
12
package org.eclipse.ui.internal.views.properties.tabbed.view;
13
14
import java.util.*;
15
16
import org.eclipse.core.runtime.IAdaptable;
17
import org.eclipse.core.runtime.Platform;
18
import org.eclipse.jface.viewers.ISelection;
19
import org.eclipse.jface.viewers.IStructuredSelection;
20
import org.eclipse.ui.IWorkbenchPart;
21
import org.eclipse.ui.views.properties.tabbed.AbstractTabDescriptor;
22
import org.eclipse.ui.views.properties.tabbed.ITabDescriptor;
23
import org.eclipse.ui.views.properties.tabbed.ITabDescriptorProvider;
24
25
26
/**
27
 * Manages {@link ITabDescriptorProvider}s and ensures the correct tab sort order
28
 * 
29
 * @since 3.4
30
 * @version 31 May 2007
31
 */
32
public class TabDescriptorProviderManager {
33
34
	private List descriptorProviders = new ArrayList();
35
36
	/**
37
	 * Creates a new TabDescriptorProviderManager 
38
	 */
39
	public TabDescriptorProviderManager() {
40
	}
41
42
	/**
43
	 * Inserts a new {@link ITabDescriptorProvider} at the given index
44
	 * @param index the position where the descriptor should be added
45
	 * @param provider the provider to add
46
	 */
47
	public void insertTabDescriptorProvider(int index, ITabDescriptorProvider provider) {
48
		descriptorProviders.add(index, provider);
49
	}
50
	
51
	/**
52
	 * Adds a new {@link ITabDescriptorProvider} to the end of the list
53
	 * @param provider the provider to add
54
	 */
55
	public void addTabDescriptorProvider(ITabDescriptorProvider provider) {
56
		descriptorProviders.add(provider);
57
	}
58
	
59
	/**
60
	 * Removes the given provider from the list.
61
	 * @return Returns true if the provider was previously present in the list
62
	 */
63
	public boolean removeTabDescriptorProvider(ITabDescriptorProvider provider) {
64
		return descriptorProviders.remove(provider);
65
	}
66
	
67
	/**
68
	 * @return Returns all the providers
69
	 */
70
	public ITabDescriptorProvider[] getDescriptorProviders() {
71
		return (ITabDescriptorProvider[]) descriptorProviders.toArray(new ITabDescriptorProvider[descriptorProviders.size()]);
72
	}
73
	
74
	/**
75
	 * Returns the {@link ITabDescriptor}s applicable to the IWorkbenchPart and the 
76
	 * given ISelection. Asks all {@link ITabDescriptorProvider}s as well as 
77
	 * {@link TabbedPropertyRegistry} and returns their descriptors in the correct sort order
78
	 * @param currentPart
79
	 * @param currentSelection
80
	 * @return all applicable {@link ITabDescriptor}s 
81
	 */
82
	public ITabDescriptor[] getTabDescriptors(IWorkbenchPart currentPart, ISelection currentSelection) {
83
		Set descriptorSet = new HashSet();
84
		
85
		// first those from the selection
86
		for (Iterator iter = getProvidersFromSelection(currentPart, currentSelection).iterator(); iter.hasNext();) {
87
			ITabDescriptorProvider provider = (ITabDescriptorProvider) iter.next();
88
			addReplaceDescriptors(descriptorSet, provider.getTabDescriptors(currentPart, currentSelection));
89
		}
90
		
91
		// then the explicitly registered ones (including the registry)
92
		for (Iterator iter = descriptorProviders.iterator(); iter.hasNext();) {
93
			ITabDescriptorProvider provider = (ITabDescriptorProvider) iter.next();
94
			addReplaceDescriptors(descriptorSet, provider.getTabDescriptors(currentPart, currentSelection));
95
		}
96
	
97
		String[] categories = getAllCategories(descriptorSet);
98
		List sortedDescriptors = new ArrayList(descriptorSet);
99
		sortedDescriptors = sortTabDescriptorsByCategory(categories, sortedDescriptors);
100
		sortedDescriptors = sortTabDescriptorsByAfterTab(categories, sortedDescriptors);
101
		
102
		return (ITabDescriptor[]) sortedDescriptors.toArray(new ITabDescriptor[sortedDescriptors.size()]);
103
	}
104
	
105
	/**
106
	 * @param aCurrentPart
107
	 * @param aCurrentSelection
108
	 * @return Returns a list of all available {@link ITabDescriptorProvider}s for the given selection
109
	 * @see #getProviderFor(Object)
110
	 */
111
	private List getProvidersFromSelection(IWorkbenchPart currentPart, ISelection currentSelection) {
112
		if (currentSelection instanceof IStructuredSelection) {
113
			IStructuredSelection ssel = (IStructuredSelection) currentSelection;
114
			List result = new ArrayList();
115
			for (Iterator iter = ssel.iterator(); iter.hasNext();) {
116
				Object element = iter.next();
117
				ITabDescriptorProvider provider = getProviderFor(element);
118
				if (provider != null) {
119
					result.add(provider);
120
				}
121
			}
122
			
123
			return result; 
124
		}
125
		
126
		return Collections.EMPTY_LIST;
127
	}
128
129
	/**
130
	 * Returns an {@link ITabDescriptorProvider} for the given element if available.
131
	 * Returns the element itself if it is an ITabDescriptorProvider or uses the {@link IAdaptable}
132
	 * mechanism.   
133
	 * @param element the element to query an ITabDescriptorProvider for
134
	 */
135
	protected ITabDescriptorProvider getProviderFor(Object element) {
136
		if (element instanceof ITabDescriptorProvider) {
137
			return (ITabDescriptorProvider) element;
138
		}
139
		
140
		ITabDescriptorProvider provider = null;
141
		
142
		if (element instanceof IAdaptable) {
143
			IAdaptable adaptable = (IAdaptable) element;
144
			provider = (ITabDescriptorProvider) adaptable.getAdapter(ITabDescriptorProvider.class);
145
			if (provider != null) {
146
				return provider;
147
			}
148
			
149
			if (Platform.getAdapterManager().hasAdapter(adaptable, ITabDescriptorProvider.class.getName())) {
150
				provider = (ITabDescriptorProvider) Platform.getAdapterManager().loadAdapter(adaptable, ITabDescriptorProvider.class.getName());
151
			}
152
		}
153
		
154
		return provider;
155
	}
156
157
	/**
158
	 * @param descriptors a set of {@link ITabDescriptor}s
159
	 * @return Returns all categories referenced by the given set of ITabDescriptors
160
	 */
161
	private String[] getAllCategories(Set descriptors) {
162
		Set allCategories = new HashSet();
163
		
164
		for (Iterator iter = descriptors.iterator(); iter.hasNext();) {
165
			ITabDescriptor descriptor = (ITabDescriptor) iter.next();
166
			String category = descriptor.getCategory();
167
			allCategories.add(category);
168
		}
169
		
170
		return (String[]) allCategories.toArray(new String[allCategories.size()]);
171
	}
172
173
	/**
174
	 * Adds the given descriptors to the set of {@link ITabDescriptor}s. If an equal
175
	 * descriptor is already in the set, it is replaced.  
176
	 * @param descriptorSet the Set<ITabDescriptor>
177
	 * @param descriptors the descriptors to add to the set
178
	 */
179
	protected void addReplaceDescriptors(Set descriptorSet, ITabDescriptor[] descriptors) {
180
		if (descriptors != null) {
181
			for (int i = 0; i < descriptors.length; i++) {
182
				descriptorSet.remove(descriptors[i]); // last one takes precedence
183
				descriptorSet.add(descriptors[i]);
184
			}
185
		}
186
	}
187
	
188
	/**
189
	 * Sorts the tab descriptors in the given list according to category.
190
	 * @param categories 
191
	 */
192
	protected List sortTabDescriptorsByCategory(final String[] categories, List descriptors) {
193
		Collections.sort(descriptors, new Comparator() {
194
195
			public int compare(Object arg0, Object arg1) {
196
				AbstractTabDescriptor one = (AbstractTabDescriptor) arg0;
197
				AbstractTabDescriptor two = (AbstractTabDescriptor) arg1;
198
				String categoryOne = one.getCategory();
199
				String categoryTwo = two.getCategory();
200
				int categoryOnePosition = getIndex(categories, categoryOne);
201
				int categoryTwoPosition = getIndex(categories, categoryTwo);
202
				return categoryOnePosition - categoryTwoPosition;
203
			}
204
		});
205
		return descriptors;
206
	}
207
208
	/**
209
	 * Sorts the tab descriptors in the given list according to afterTab.
210
	 * @param categories 
211
	 */
212
	protected List sortTabDescriptorsByAfterTab(String[] categories, List tabs) {
213
		if (tabs.size() == 0 || categories == null) {
214
			return tabs;
215
		}
216
		List sorted = new ArrayList();
217
		int categoryIndex = 0;
218
		for (int i = 0; i < categories.length; i++) {
219
			List categoryList = new ArrayList();
220
			String category = categories[i];
221
			int topOfCategory = categoryIndex;
222
			int endOfCategory = categoryIndex;
223
			while (endOfCategory < tabs.size()
224
				&& ((AbstractTabDescriptor) tabs.get(endOfCategory)).getCategory()
225
					.equals(category)) {
226
				endOfCategory++;
227
			}
228
			for (int j = topOfCategory; j < endOfCategory; j++) {
229
				AbstractTabDescriptor tab = (AbstractTabDescriptor) tabs.get(j);
230
				if (tab.getAfterTab().equals(AbstractTabDescriptor.TOP)) {
231
					categoryList.add(0, tabs.get(j));
232
				} else {
233
					categoryList.add(tabs.get(j));
234
				}
235
			}
236
			Collections.sort(categoryList, new Comparator() {
237
238
				public int compare(Object arg0, Object arg1) {
239
					AbstractTabDescriptor one = (AbstractTabDescriptor) arg0;
240
					AbstractTabDescriptor two = (AbstractTabDescriptor) arg1;
241
					if (two.getAfterTab().equals(one.getId())) {
242
						return -1;
243
					} else if (one.getAfterTab().equals(two.getId())) {
244
						return 1;
245
					} else {
246
						return 0;
247
					}
248
				}
249
			});
250
			for (int j = 0; j < categoryList.size(); j++) {
251
				sorted.add(categoryList.get(j));
252
			}
253
			categoryIndex = endOfCategory;
254
		}
255
		return sorted;
256
	}
257
	
258
	/**
259
	 * Returns the index of the given element in the array.
260
	 */
261
	private int getIndex(Object[] array, Object target) {
262
		for (int i = 0; i < array.length; i++) {
263
			if (array[i].equals(target)) {
264
				return i;
265
			}
266
		}
267
		return -1; // should never happen
268
	}
269
}
(-)src/org/eclipse/ui/tests/views/properties/tabbed/TabbedPropertySheetPageTest.java (-3 / +3 lines)
Lines 22-28 Link Here
22
import org.eclipse.ui.IWorkbenchPage;
22
import org.eclipse.ui.IWorkbenchPage;
23
import org.eclipse.ui.IWorkbenchWindow;
23
import org.eclipse.ui.IWorkbenchWindow;
24
import org.eclipse.ui.PlatformUI;
24
import org.eclipse.ui.PlatformUI;
25
import org.eclipse.ui.internal.views.properties.tabbed.view.Tab;
26
import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyComposite;
25
import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyComposite;
27
import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyList;
26
import org.eclipse.ui.internal.views.properties.tabbed.view.TabbedPropertyList;
28
import org.eclipse.ui.tests.views.properties.tabbed.sections.InformationTwoSection;
27
import org.eclipse.ui.tests.views.properties.tabbed.sections.InformationTwoSection;
Lines 31-36 Link Here
31
import org.eclipse.ui.tests.views.properties.tabbed.views.TestsView;
30
import org.eclipse.ui.tests.views.properties.tabbed.views.TestsView;
32
import org.eclipse.ui.tests.views.properties.tabbed.views.TestsViewContentProvider;
31
import org.eclipse.ui.tests.views.properties.tabbed.views.TestsViewContentProvider;
33
import org.eclipse.ui.views.properties.tabbed.ISection;
32
import org.eclipse.ui.views.properties.tabbed.ISection;
33
import org.eclipse.ui.views.properties.tabbed.TabContents;
34
34
35
public class TabbedPropertySheetPageTest
35
public class TabbedPropertySheetPageTest
36
    extends TestCase {
36
    extends TestCase {
Lines 202-208 Link Here
202
         * First tab is Information
202
         * First tab is Information
203
         */
203
         */
204
        assertEquals(tabbedPropertyList.getElementAt(0).toString(), "Name");//$NON-NLS-1$
204
        assertEquals(tabbedPropertyList.getElementAt(0).toString(), "Name");//$NON-NLS-1$
205
        Tab tab = testsView.getTabbedPropertySheetPage().getCurrentTab();
205
        TabContents tab = testsView.getTabbedPropertySheetPage().getCurrentTab();
206
        /**
206
        /**
207
         * the tab has two sections.
207
         * the tab has two sections.
208
         */
208
         */
Lines 258-264 Link Here
258
     * viewer.
258
     * viewer.
259
     */
259
     */
260
    public void test_noPropertiesAvailable() {
260
    public void test_noPropertiesAvailable() {
261
        Tab tab = testsView.getTabbedPropertySheetPage().getCurrentTab();
261
        TabContents tab = testsView.getTabbedPropertySheetPage().getCurrentTab();
262
        assertNull(tab);
262
        assertNull(tab);
263
        TabbedPropertyList tabbedPropertyList = getTabbedPropertyList();
263
        TabbedPropertyList tabbedPropertyList = getTabbedPropertyList();
264
        assertNull(tabbedPropertyList.getElementAt(0));
264
        assertNull(tabbedPropertyList.getElementAt(0));

Return to bug 131855