Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 54548 | Differences between
and this patch

Collapse All | Expand All

(-)src/org/eclipse/ui/internal/ide/messages.properties (+1 lines)
Lines 361-366 Link Here
361
AboutDialog.platformInfo = Built with Eclipse technology
361
AboutDialog.platformInfo = Built with Eclipse technology
362
AboutDialog.systemInfo = &Configuration Details
362
AboutDialog.systemInfo = &Configuration Details
363
AboutDialog.notSpecified= Not Specified
363
AboutDialog.notSpecified= Not Specified
364
AboutDialog.defaultProductName = Eclipse-based Product
364
ProductInfoDialog.errorTitle = Problems Opening Link
365
ProductInfoDialog.errorTitle = Problems Opening Link
365
ProductInfoDialog.unableToOpenWebBrowser = Unable to open web browser.
366
ProductInfoDialog.unableToOpenWebBrowser = Unable to open web browser.
366
AboutPluginsDialog.shellTitle = About {0} Plug-ins
367
AboutPluginsDialog.shellTitle = About {0} Plug-ins
(-)src/org/eclipse/ui/internal/ide/actions/AboutAction.java (-26 / +17 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2003 IBM Corporation and others.
2
 * Copyright (c) 2000, 2004 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials 
3
 * All rights reserved. This program and the accompanying materials 
4
 * are made available under the terms of the Common Public License v1.0
4
 * are made available under the terms of the Common Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 10-23 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.ui.internal.ide.actions;
11
package org.eclipse.ui.internal.ide.actions;
12
12
13
import org.eclipse.core.runtime.IBundleGroupProvider;
14
import org.eclipse.core.runtime.IProduct;
15
import org.eclipse.core.runtime.Platform;
13
import org.eclipse.jface.action.Action;
16
import org.eclipse.jface.action.Action;
14
// @issue org.eclipse.ui.internal.AboutInfo - illegal reference to generic workbench internals
15
import org.eclipse.ui.internal.AboutInfo;
16
import org.eclipse.ui.IWorkbenchWindow;
17
import org.eclipse.ui.IWorkbenchWindow;
17
import org.eclipse.ui.actions.ActionFactory;
18
import org.eclipse.ui.actions.ActionFactory;
18
import org.eclipse.ui.help.WorkbenchHelp;
19
import org.eclipse.ui.help.WorkbenchHelp;
19
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
20
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
20
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
21
import org.eclipse.ui.internal.ide.IHelpContextIds;
21
import org.eclipse.ui.internal.ide.IHelpContextIds;
22
import org.eclipse.ui.internal.ide.dialogs.AboutDialog;
22
import org.eclipse.ui.internal.ide.dialogs.AboutDialog;
23
23
Lines 44-57 Link Here
44
	this.workbenchWindow = window;
44
	this.workbenchWindow = window;
45
	
45
	
46
	// use message with no fill-in
46
	// use message with no fill-in
47
	AboutInfo primaryInfo = IDEWorkbenchPlugin.getDefault().getPrimaryInfo();
47
	IProduct product = Platform.getProduct();
48
	String productName = null;
48
	String productName = null;
49
	if (primaryInfo != null) {
49
	if (product != null)
50
		productName = primaryInfo.getProductName();
50
		productName = product.getName();
51
	}
51
	if (productName == null)
52
	if (productName == null) {
53
		productName = ""; //$NON-NLS-1$
52
		productName = ""; //$NON-NLS-1$
54
	}
55
	setText(IDEWorkbenchMessages.format("AboutAction.text", new Object[] { productName })); //$NON-NLS-1$
53
	setText(IDEWorkbenchMessages.format("AboutAction.text", new Object[] { productName })); //$NON-NLS-1$
56
	setToolTipText(IDEWorkbenchMessages.format("AboutAction.toolTip", new Object[] { productName})); //$NON-NLS-1$
54
	setToolTipText(IDEWorkbenchMessages.format("AboutAction.toolTip", new Object[] { productName})); //$NON-NLS-1$
57
	setId("about"); //$NON-NLS-1$
55
	setId("about"); //$NON-NLS-1$
Lines 63-84 Link Here
63
 * Method declared on IAction.
61
 * Method declared on IAction.
64
 */
62
 */
65
public void run() {
63
public void run() {
66
	if (workbenchWindow == null) {
64
67
		// action has been disposed
65
    // make sure action is not disposed
68
		return;
66
    if (workbenchWindow == null)
69
	}
67
        return;
70
	AboutInfo primaryInfo = IDEWorkbenchPlugin.getDefault().getPrimaryInfo();
68
71
	AboutInfo[] featureInfos = IDEWorkbenchPlugin.getDefault().getFeatureInfos();
69
    IProduct product = Platform.getProduct();
72
//	if (primaryInfo == null) {
70
    IBundleGroupProvider[] providers = Platform.getBundleGroupProviders();
73
//		// @issue illegal to pass null status to openError
71
74
//		ErrorDialog.openError(
72
    new AboutDialog(workbenchWindow, product, providers).open();
75
//				workbenchWindow.getShell(), 
76
//				IDEWorkbenchMessages.format("AboutAction.errorDialogTitle", new Object[] {getText()}),  //$NON-NLS-1$
77
//				IDEWorkbenchMessages.getString("AboutInfo.infoReadError"),  //$NON-NLS-1$
78
//				null);
79
//		return;
80
//	}
81
	new AboutDialog(workbenchWindow, primaryInfo, featureInfos).open();
82
}
73
}
83
74
84
/* (non-Javadoc)
75
/* (non-Javadoc)
(-)src/org/eclipse/ui/internal/ide/dialogs/AboutDialog.java (-211 / +194 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2003 IBM Corporation and others.
2
 * Copyright (c) 2000, 2004 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials 
3
 * All rights reserved. This program and the accompanying materials 
4
 * are made available under the terms of the Common Public License v1.0
4
 * are made available under the terms of the Common Public License v1.0
5
 * which accompanies this distribution, and is available at
5
 * which accompanies this distribution, and is available at
Lines 8-19 Link Here
8
 * Contributors:
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
10
 *******************************************************************************/
11
12
package org.eclipse.ui.internal.ide.dialogs;
11
package org.eclipse.ui.internal.ide.dialogs;
13
12
14
import java.util.ArrayList;
13
import java.util.ArrayList;
15
import java.util.List;
14
import java.util.LinkedList;
16
15
16
import org.eclipse.core.runtime.IBundleGroup;
17
import org.eclipse.core.runtime.IBundleGroupProvider;
18
import org.eclipse.core.runtime.IProduct;
17
import org.eclipse.jface.dialogs.IDialogConstants;
19
import org.eclipse.jface.dialogs.IDialogConstants;
18
import org.eclipse.jface.resource.ImageDescriptor;
20
import org.eclipse.jface.resource.ImageDescriptor;
19
import org.eclipse.swt.SWT;
21
import org.eclipse.swt.SWT;
Lines 32-40 Link Here
32
import org.eclipse.swt.widgets.Control;
34
import org.eclipse.swt.widgets.Control;
33
import org.eclipse.swt.widgets.Label;
35
import org.eclipse.swt.widgets.Label;
34
import org.eclipse.swt.widgets.Shell;
36
import org.eclipse.swt.widgets.Shell;
35
import org.eclipse.ui.internal.AboutInfo;
36
import org.eclipse.ui.IWorkbenchWindow;
37
import org.eclipse.ui.IWorkbenchWindow;
37
import org.eclipse.ui.help.WorkbenchHelp;
38
import org.eclipse.ui.help.WorkbenchHelp;
39
import org.eclipse.ui.internal.ide.AboutBundleGroupData;
38
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
40
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
39
import org.eclipse.ui.internal.ide.IHelpContextIds;
41
import org.eclipse.ui.internal.ide.IHelpContextIds;
40
42
Lines 42-48 Link Here
42
 * Displays information about the product.
44
 * Displays information about the product.
43
 *
45
 *
44
 * @private
46
 * @private
45
 *		This class is internal to the workbench and must not be called outside the workbench
47
 *		this class is internal to the ide
46
 */
48
 */
47
public class AboutDialog extends ProductInfoDialog {
49
public class AboutDialog extends ProductInfoDialog {
48
	private final static int MAX_IMAGE_WIDTH_FOR_TEXT = 250;
50
	private final static int MAX_IMAGE_WIDTH_FOR_TEXT = 250;
Lines 50-157 Link Here
50
	private final static int PLUGINS_ID = IDialogConstants.CLIENT_ID + 2;
52
	private final static int PLUGINS_ID = IDialogConstants.CLIENT_ID + 2;
51
	private final static int INFO_ID = IDialogConstants.CLIENT_ID + 3;
53
	private final static int INFO_ID = IDialogConstants.CLIENT_ID + 3;
52
54
53
	/**
55
	private String productName;
54
	 * About info for the primary feature.
56
	private AboutBundleGroupData[] bundleGroupInfos;
55
	 * Private field used in inner class.
56
	 * @issue org.eclipse.ui.internal.AboutInfo - illegal reference to generic workbench internals
57
	 */
58
	/* package */ AboutInfo primaryInfo;
59
60
	/**
61
	 * About info for the all features.
62
	 * Private field used in inner class.
63
	 * @issue org.eclipse.ui.internal.AboutInfo - illegal reference to generic workbench internals
64
	 */
65
	/* package */ AboutInfo[] featureInfos;
66
	private Image image; //image to display on dialog
67
57
68
	private ArrayList images = new ArrayList();
58
	private ArrayList images = new ArrayList();
59
	private AboutFeaturesButtonManager buttonManager = new AboutFeaturesButtonManager();
60
61
    // TODO should the styled text be disposed? if not then it likely
62
    //      doesn't need to be a member
69
	private StyledText text;
63
	private StyledText text;
70
64
71
	/**
65
	/**
72
	 * Create an instance of the AboutDialog
66
	 * Create an instance of the AboutDialog
73
	 */
67
	 */
74
	public AboutDialog(
68
	public AboutDialog(IWorkbenchWindow window, IProduct product,
75
		IWorkbenchWindow window,
69
            IBundleGroupProvider[] providers) {
76
		AboutInfo primaryInfo,
70
	    super(window.getShell());
77
		AboutInfo[] featureInfos) {
71
78
		super(window.getShell());
72
		String productId = ""; //$NON-NLS-1$
79
		this.primaryInfo = primaryInfo;
73
        if (product == null)
80
		this.featureInfos = featureInfos;
74
            productName = IDEWorkbenchMessages
75
                    .getString("AboutDialog.defaultProductName"); //$NON-NLS-1$
76
        else {
77
            productId = product.getId();
78
            productName = product.getName();
79
        }
80
81
        // create a descriptive object for each BundleGroup, putting the primary
82
        // first if it can be found
83
        LinkedList groups = new LinkedList();
84
        if (providers != null)
85
            for (int i = 0; i < providers.length; ++i) {
86
                IBundleGroup[] bundleGroups = providers[i].getBundleGroups();
87
                for (int j = 0; j < bundleGroups.length; ++j) {
88
                    AboutBundleGroupData info = new AboutBundleGroupData(
89
                                bundleGroups[j]);
90
91
                    // if there's a bundle with the same id as the product,
92
                    // assume its the primary bundle and put it first
93
                    if (info.getId().equals(productId))
94
                        groups.addFirst(info);
95
                    else
96
                        groups.add(info);
97
                }
98
            }
99
        bundleGroupInfos = (AboutBundleGroupData[]) groups
100
                .toArray(new AboutBundleGroupData[0]);
81
	}
101
	}
82
102
83
	/* (non-Javadoc)
103
	/*
84
	 * Method declared on Dialog.
104
     * (non-Javadoc) Method declared on Dialog.
85
	 */
105
     */
86
	protected void buttonPressed(int buttonId) {
106
    protected void buttonPressed(int buttonId) {
87
		switch (buttonId) {
107
        switch (buttonId) {
88
			case FEATURES_ID :
108
        case FEATURES_ID:
89
				new AboutFeaturesDialog(getShell(), primaryInfo, featureInfos)
109
            new AboutFeaturesDialog(getShell(), productName, bundleGroupInfos).open();
90
					.open();
110
            break;
91
				return;
111
        case PLUGINS_ID:
92
			case PLUGINS_ID :
112
            new AboutPluginsDialog(getShell(), productName).open();
93
				new AboutPluginsDialog(getShell(), primaryInfo).open();
113
            break;
94
				return;
114
        case INFO_ID:
95
			case INFO_ID :
115
            new SystemSummaryDialog(getShell()).open();
96
				new SystemSummaryDialog(getShell()).open();
116
            break;
97
				return;
117
        default:
98
		}
118
            super.buttonPressed(buttonId);
99
119
            break;
100
		super.buttonPressed(buttonId);
120
        }
101
	}
121
    }
102
122
103
	public boolean close() {
123
	public boolean close() {
104
		//get rid of the image that was displayed on the left-hand side of the Welcome dialog
124
        // dispose all images
105
		if (image != null) {
125
        for (int i = 0; i < images.size(); ++i) {
106
			image.dispose();
126
            Image image = (Image) images.get(i);
107
		}
127
            image.dispose();
108
		for (int i = 0; i < images.size(); i++) {
128
        }
109
			((Image) images.get(i)).dispose();
129
110
		}
130
        return super.close();
111
		return super.close();
131
    }
112
	}
132
113
	/* (non-Javadoc)
133
	/*
114
	 * Method declared on Window.
134
     * (non-Javadoc) Method declared on Window.
115
	 */
135
     */
116
	protected void configureShell(Shell newShell) {
136
    protected void configureShell(Shell newShell) {
117
		super.configureShell(newShell);
137
        super.configureShell(newShell);
118
		String name = null;
138
        newShell.setText(IDEWorkbenchMessages.format("AboutDialog.shellTitle", //$NON-NLS-1$
119
		if (primaryInfo != null) {
139
                new Object[] { productName }));
120
			name = primaryInfo.getProductName();
140
        WorkbenchHelp.setHelp(newShell, IHelpContextIds.ABOUT_DIALOG);
121
		}
141
    }
122
		if (name != null) {
142
123
			newShell.setText(IDEWorkbenchMessages.format("AboutDialog.shellTitle", new Object[] { name })); //$NON-NLS-1$
124
		}
125
		WorkbenchHelp.setHelp(newShell, IHelpContextIds.ABOUT_DIALOG);
126
	}
127
	/**
143
	/**
128
	 * Add buttons to the dialog's button bar.
144
     * Add buttons to the dialog's button bar.
129
	 *
145
     * 
130
	 * Subclasses should override.
146
     * Subclasses should override.
131
	 *
147
     * 
132
	 * @param parent the button bar composite
148
     * @param parent
133
	 */
149
     *            the button bar composite
134
	protected void createButtonsForButtonBar(Composite parent) {
150
     */
135
		parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
151
    protected void createButtonsForButtonBar(Composite parent) {
152
        parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
153
154
        createButton(parent, FEATURES_ID, IDEWorkbenchMessages
155
                .getString("AboutDialog.featureInfo"), false); //$NON-NLS-1$
156
        createButton(parent, PLUGINS_ID, IDEWorkbenchMessages
157
                .getString("AboutDialog.pluginInfo"), false); //$NON-NLS-1$
158
        createButton(parent, INFO_ID, IDEWorkbenchMessages
159
                .getString("AboutDialog.systemInfo"), false); //$NON-NLS-1$
160
161
        Label l = new Label(parent, SWT.NONE);
162
        l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
163
        GridLayout layout = (GridLayout) parent.getLayout();
164
        layout.numColumns++;
165
        layout.makeColumnsEqualWidth = false;
166
167
        Button b = createButton(parent, IDialogConstants.OK_ID,
168
                IDialogConstants.OK_LABEL, true);
169
        b.setFocus();
170
    }
136
171
137
		createButton(parent, FEATURES_ID, IDEWorkbenchMessages.getString("AboutDialog.featureInfo"), false); //$NON-NLS-1$
138
		createButton(parent, PLUGINS_ID, IDEWorkbenchMessages.getString("AboutDialog.pluginInfo"), false); //$NON-NLS-1$
139
		createButton(parent, INFO_ID, IDEWorkbenchMessages.getString("AboutDialog.systemInfo"), false); //$NON-NLS-1$
140
141
		Label l = new Label(parent, SWT.NONE);
142
		l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
143
		GridLayout layout = (GridLayout) parent.getLayout();
144
		layout.numColumns++;
145
		layout.makeColumnsEqualWidth = false;
146
147
		Button b =
148
			createButton(
149
				parent,
150
				IDialogConstants.OK_ID,
151
				IDialogConstants.OK_LABEL,
152
				true);
153
		b.setFocus();
154
	}
155
	/**
172
	/**
156
	 * Creates and returns the contents of the upper part 
173
	 * Creates and returns the contents of the upper part 
157
	 * of the dialog (above the button bar).
174
	 * of the dialog (above the button bar).
Lines 162-198 Link Here
162
	 * @return the dialog area control
179
	 * @return the dialog area control
163
	 */
180
	 */
164
	protected Control createDialogArea(Composite parent) {
181
	protected Control createDialogArea(Composite parent) {
165
		setHandCursor(new Cursor(parent.getDisplay(), SWT.CURSOR_HAND));
182
		final Cursor hand = new Cursor(parent.getDisplay(), SWT.CURSOR_HAND);
166
		setBusyCursor(new Cursor(parent.getDisplay(), SWT.CURSOR_WAIT));
183
        final Cursor busy = new Cursor(parent.getDisplay(), SWT.CURSOR_WAIT);
167
		getShell().addDisposeListener(new DisposeListener() {
184
        setHandCursor(hand);
168
			public void widgetDisposed(DisposeEvent e) {
185
        setBusyCursor(busy);
169
				if (getHandCursor() != null) {
186
        getShell().addDisposeListener(new DisposeListener() {
170
					getHandCursor().dispose();
187
            public void widgetDisposed(DisposeEvent e) {
171
				}
188
                setHandCursor(null);
172
				if (getBusyCursor() != null) {
189
                hand.dispose();
173
					getBusyCursor().dispose();
190
                setBusyCursor(null);
174
				}
191
                busy.dispose();
175
			}
192
            }
176
		});
193
        });
177
194
178
		ImageDescriptor imageDescriptor = null;
195
		// if there is product info (index 0), then brand the about box
179
		if (primaryInfo != null) {
196
		Image aboutImage = null;
180
			imageDescriptor = primaryInfo.getAboutImage(); // may be null
197
        if (bundleGroupInfos.length > 0) {
181
		}
198
        	AboutBundleGroupData productInfo = bundleGroupInfos[0];
182
		if (imageDescriptor != null) {
199
183
			image = imageDescriptor.createImage();
200
	        ImageDescriptor imageDescriptor = null;
184
		}
201
	        if (productInfo != null)
185
		if (image == null
202
	        	imageDescriptor = productInfo.getAboutImage();
186
			|| image.getBounds().width <= MAX_IMAGE_WIDTH_FOR_TEXT) {
203
	        if (imageDescriptor != null)
187
			// show text
204
	            aboutImage = imageDescriptor.createImage();
188
			String aboutText = null;
205
189
			if (primaryInfo != null) {
206
			// if the about image is small enough, then show the text
190
				aboutText = primaryInfo.getAboutText(); // may be null
207
			if (aboutImage == null
191
			}
208
                    || aboutImage.getBounds().width <= MAX_IMAGE_WIDTH_FOR_TEXT) {
192
			if (aboutText != null) {
209
	            String aboutText = null;
193
				// get an about item
210
	            if (productInfo != null)
194
				setItem(scan(aboutText));
211
	            	aboutText = productInfo.getAboutText();
195
			}
212
	            if (aboutText != null)
213
	            	setItem(scan(aboutText));
214
	        }
215
216
			if(aboutImage != null)
217
			    images.add(aboutImage);
196
		}
218
		}
197
219
198
		// page group
220
		// page group
Lines 205-211 Link Here
205
		// the image & text	
227
		// the image & text	
206
		Composite topContainer = new Composite(outer, SWT.NONE);
228
		Composite topContainer = new Composite(outer, SWT.NONE);
207
		layout = new GridLayout();
229
		layout = new GridLayout();
208
		layout.numColumns = (image == null || getItem() == null ? 1 : 2);
230
		layout.numColumns = (aboutImage == null || getItem() == null ? 1 : 2);
209
		layout.marginWidth = 0;
231
		layout.marginWidth = 0;
210
		topContainer.setLayout(layout);
232
		topContainer.setLayout(layout);
211
		GridData data = new GridData();
233
		GridData data = new GridData();
Lines 214-227 Link Here
214
		topContainer.setLayoutData(data);
236
		topContainer.setLayoutData(data);
215
237
216
		//image on left side of dialog
238
		//image on left side of dialog
217
		if (image != null) {
239
		if (aboutImage != null) {
218
			Label imageLabel = new Label(topContainer, SWT.NONE);
240
			Label imageLabel = new Label(topContainer, SWT.NONE);
219
			data = new GridData();
241
			data = new GridData();
220
			data.horizontalAlignment = GridData.FILL;
242
			data.horizontalAlignment = GridData.FILL;
221
			data.verticalAlignment = GridData.BEGINNING;
243
			data.verticalAlignment = GridData.BEGINNING;
222
			data.grabExcessHorizontalSpace = false;
244
			data.grabExcessHorizontalSpace = false;
223
			imageLabel.setLayoutData(data);
245
			imageLabel.setLayoutData(data);
224
			imageLabel.setImage(image);
246
			imageLabel.setImage(aboutImage);
225
		}
247
		}
226
248
227
		if (getItem() != null) {
249
		if (getItem() != null) {
Lines 247-291 Link Here
247
		data.horizontalAlignment = GridData.FILL;
269
		data.horizontalAlignment = GridData.FILL;
248
		bar.setLayoutData(data);
270
		bar.setLayoutData(data);
249
271
250
		// feature images
272
		// add image buttons for bundle groups that have them
251
		Composite featureContainer = new Composite(outer, SWT.NONE);
273
		createFeatureImageButtonRow(outer);
252
		RowLayout rowLayout = new RowLayout();
253
		rowLayout.wrap = true;
254
		featureContainer.setLayout(rowLayout);
255
		data = new GridData();
256
		data.horizontalAlignment = GridData.FILL;
257
		featureContainer.setLayoutData(data);
258
259
		final AboutInfo[] infoArray = getFeaturesWithImages();
260
		for (int i = 0; i < infoArray.length; i++) {
261
			ImageDescriptor desc = infoArray[i].getFeatureImage();
262
			Image featureImage = null;
263
			if (desc != null) {
264
				Button button =
265
					new Button(featureContainer, SWT.FLAT | SWT.PUSH);
266
				button.setData(infoArray[i]);
267
				featureImage = desc.createImage();
268
				images.add(featureImage);
269
				button.setImage(featureImage);
270
				String name = infoArray[i].getProviderName();
271
				if (name == null) {
272
					name = ""; //$NON-NLS-1$
273
				}
274
				button.setToolTipText(name);
275
				button.addSelectionListener(new SelectionAdapter() {
276
					public void widgetSelected(SelectionEvent event) {
277
						AboutFeaturesDialog d =
278
							new AboutFeaturesDialog(
279
								getShell(),
280
								primaryInfo,
281
								featureInfos);
282
						d.setInitialSelection(
283
							(AboutInfo) event.widget.getData());
284
						d.open();
285
					}
286
				});
287
			}
288
		}
289
274
290
		// spacer
275
		// spacer
291
		bar = new Label(outer, SWT.NONE);
276
		bar = new Label(outer, SWT.NONE);
Lines 296-346 Link Here
296
		return outer;
281
		return outer;
297
	}
282
	}
298
283
299
	/**
284
	private void createFeatureImageButtonRow(Composite parent) {
300
	 * Returns the feature info for non-primary features with a feature image.
285
		// feature images
301
	 * If several features share the same image bitmap, include only one per
286
		Composite featureContainer = new Composite(parent, SWT.NONE);
302
	 * provider.
287
		RowLayout rowLayout = new RowLayout();
303
	 */
288
		rowLayout.wrap = true;
304
	private AboutInfo[] getFeaturesWithImages() {
289
		featureContainer.setLayout(rowLayout);
305
		// quickly exclude any that do not have a provider name and image
290
		GridData data = new GridData();
306
		List infoList = new ArrayList(featureInfos.length + 1);
291
		data.horizontalAlignment = GridData.FILL;
307
292
		featureContainer.setLayoutData(data);
308
		// make sure primary is first
309
		if (primaryInfo != null && primaryInfo.getProviderName() != null
310
				&& primaryInfo.getFeatureImageName() != null) {
311
			infoList.add(primaryInfo);
312
		}
313
293
314
		for (int i = 0; i < featureInfos.length; i++) {
294
		// create buttons for all the rest
315
			if (featureInfos[i].getProviderName() != null
295
		for (int i = 0; i < bundleGroupInfos.length; i++)
316
				&& featureInfos[i].getFeatureImageName() != null) {
296
			createFeatureButton(featureContainer, bundleGroupInfos[i]);
317
				infoList.add(featureInfos[i]);
297
	}
318
			}
319
		}
320
		List keepers = new ArrayList(infoList.size());
321
298
322
		// precompute CRCs of all the feature images
299
	private Button createFeatureButton(Composite parent,
323
		long[] featureImageCRCs = new long[infoList.size()];
300
            final AboutBundleGroupData info) {
324
		for (int i = 0; i < infoList.size(); i++) {
301
        if (!buttonManager.add(info))
325
			AboutInfo info = (AboutInfo) infoList.get(i);
302
			return null;
326
			featureImageCRCs[i] = info.getFeatureImageCRC().longValue();
303
327
		}
304
        ImageDescriptor desc = info.getFeatureImage();
328
		for (int i = 0; i < infoList.size(); i++) {
305
        Image featureImage = null;
329
			AboutInfo outer = (AboutInfo) infoList.get(i);
306
330
			boolean found = false;
307
	    Button button = new Button(parent, SWT.FLAT | SWT.PUSH);
331
			// see whether we already have one for same provider and same image
308
        button.setData(info);
332
			for (int j = 0; j < keepers.size(); j++) {
309
        featureImage = desc.createImage();
333
				AboutInfo k = (AboutInfo) keepers.get(j);
310
        images.add(featureImage);
334
				if (k.getProviderName().equals(outer.getProviderName())
311
        button.setImage(featureImage);
335
					&& featureImageCRCs[j] == featureImageCRCs[i]) {
312
        button.setToolTipText(info.getProviderName());
336
					found = true;
313
        button.addSelectionListener(new SelectionAdapter() {
337
					break;
314
            public void widgetSelected(SelectionEvent event) {
338
				}
315
                AboutBundleGroupData[] groupInfos = buttonManager
339
			}
316
                        .getRelatedInfos(info);
340
			if (!found) {
317
				AboutBundleGroupData selection = (AboutBundleGroupData) event.widget
341
				keepers.add(outer);
318
                        .getData();
342
			}
319
343
		}
320
                AboutFeaturesDialog d = new AboutFeaturesDialog(getShell(),
344
		return (AboutInfo[]) keepers.toArray(new AboutInfo[keepers.size()]);
321
                        productName, groupInfos);
322
                d.setInitialSelection(selection);
323
                d.open();
324
            }
325
        });
326
327
		return button;
345
	}
328
	}
346
}
329
}
(-)src/org/eclipse/ui/internal/ide/dialogs/AboutFeaturesDialog.java (-638 / +433 lines)
Lines 1-5 Link Here
1
/******************************************************************************* 
1
/******************************************************************************* 
2
 * Copyright (c) 2000, 2003 IBM Corporation and others. 
2
 * Copyright (c) 2000, 2004 IBM Corporation and others. 
3
 * All rights reserved. This program and the accompanying materials! 
3
 * All rights reserved. This program and the accompanying materials! 
4
 * are made available under the terms of the Common Public License v1.0 
4
 * are made available under the terms of the Common Public License v1.0 
5
 * which accompanies this distribution, and is available at 
5
 * which accompanies this distribution, and is available at 
Lines 10-35 Link Here
10
 *  	Sebastian Davids <sdavids@gmx.de> - Fix for bug 19346 - Dialog
10
 *  	Sebastian Davids <sdavids@gmx.de> - Fix for bug 19346 - Dialog
11
 *      font should be activated and used by other components.
11
 *      font should be activated and used by other components.
12
************************************************************************/
12
************************************************************************/
13
14
package org.eclipse.ui.internal.ide.dialogs;
13
package org.eclipse.ui.internal.ide.dialogs;
15
14
16
import java.text.Collator;
17
import java.util.ArrayList;
18
import java.util.Arrays;
19
import java.util.Collection;
20
import java.util.Collections;
21
import java.util.Comparator;
22
import java.util.HashMap;
15
import java.util.HashMap;
23
import java.util.Iterator;
16
import java.util.Iterator;
24
import java.util.Locale;
25
import java.util.Map;
17
import java.util.Map;
26
18
27
import org.eclipse.core.runtime.CoreException;
19
import org.eclipse.core.runtime.CoreException;
28
import org.eclipse.core.runtime.IPluginDescriptor;
20
import org.eclipse.core.runtime.IBundleGroup;
29
import org.eclipse.core.runtime.IPluginRegistry;
30
import org.eclipse.core.runtime.NullProgressMonitor;
21
import org.eclipse.core.runtime.NullProgressMonitor;
31
import org.eclipse.core.runtime.Platform;
22
import org.eclipse.jface.dialogs.IDialogConstants;
32
23
import org.eclipse.jface.dialogs.MessageDialog;
24
import org.eclipse.jface.resource.ImageDescriptor;
25
import org.eclipse.jface.window.Window;
33
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.SWT;
34
import org.eclipse.swt.custom.BusyIndicator;
27
import org.eclipse.swt.custom.BusyIndicator;
35
import org.eclipse.swt.custom.StyledText;
28
import org.eclipse.swt.custom.StyledText;
Lines 37-43 Link Here
37
import org.eclipse.swt.events.DisposeListener;
30
import org.eclipse.swt.events.DisposeListener;
38
import org.eclipse.swt.events.SelectionAdapter;
31
import org.eclipse.swt.events.SelectionAdapter;
39
import org.eclipse.swt.events.SelectionEvent;
32
import org.eclipse.swt.events.SelectionEvent;
40
import org.eclipse.swt.events.SelectionListener;
41
import org.eclipse.swt.graphics.Cursor;
33
import org.eclipse.swt.graphics.Cursor;
42
import org.eclipse.swt.graphics.Font;
34
import org.eclipse.swt.graphics.Font;
43
import org.eclipse.swt.graphics.Image;
35
import org.eclipse.swt.graphics.Image;
Lines 51-93 Link Here
51
import org.eclipse.swt.widgets.Table;
43
import org.eclipse.swt.widgets.Table;
52
import org.eclipse.swt.widgets.TableColumn;
44
import org.eclipse.swt.widgets.TableColumn;
53
import org.eclipse.swt.widgets.TableItem;
45
import org.eclipse.swt.widgets.TableItem;
54
55
import org.eclipse.jface.dialogs.IDialogConstants;
56
import org.eclipse.jface.dialogs.MessageDialog;
57
import org.eclipse.jface.resource.ImageDescriptor;
58
59
import org.eclipse.ui.help.WorkbenchHelp;
46
import org.eclipse.ui.help.WorkbenchHelp;
60
47
import org.eclipse.ui.internal.ide.AboutBundleGroupData;
61
import org.eclipse.ui.internal.AboutInfo;
48
import org.eclipse.ui.internal.ide.AboutData;
62
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
49
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
63
import org.eclipse.ui.internal.ide.IHelpContextIds;
50
import org.eclipse.ui.internal.ide.IHelpContextIds;
64
65
import org.eclipse.update.configuration.IConfiguredSite;
51
import org.eclipse.update.configuration.IConfiguredSite;
66
import org.eclipse.update.configuration.IInstallConfiguration;
52
import org.eclipse.update.configuration.IInstallConfiguration;
67
import org.eclipse.update.configuration.ILocalSite;
53
import org.eclipse.update.configuration.ILocalSite;
68
import org.eclipse.update.core.IFeature;
54
import org.eclipse.update.core.IFeature;
69
import org.eclipse.update.core.IFeatureReference;
55
import org.eclipse.update.core.IFeatureReference;
70
import org.eclipse.update.core.IPluginEntry;
71
import org.eclipse.update.core.IURLEntry;
56
import org.eclipse.update.core.IURLEntry;
72
import org.eclipse.update.core.SiteManager;
57
import org.eclipse.update.core.SiteManager;
73
import org.eclipse.update.core.VersionedIdentifier;
58
import org.osgi.framework.Bundle;
74
59
75
/**
60
/**
76
 * Displays information about the product plugins.
61
 * Displays information about the product plugins.
77
 *
62
 *
78
 * @private
63
 * @private
79
 *		This class is internal to the workbench and must not be called outside the workbench
64
 *		This class is internal to the workbench and must not be called outside
65
 *		the workbench.
80
 */
66
 */
81
public class AboutFeaturesDialog extends ProductInfoDialog {
67
public class AboutFeaturesDialog extends ProductInfoDialog {
82
68
83
	/**
69
    /**
84
	 * Table height in dialog units (value 150).
70
     * Table height in dialog units (value 150).
85
	 */
71
     */
86
	private static final int TABLE_HEIGHT = 150;
72
    private static final int TABLE_HEIGHT = 150;
87
	private static final int INFO_HEIGHT = 100;
73
    private static final int INFO_HEIGHT = 100;
88
74
    private final static int MORE_ID = IDialogConstants.CLIENT_ID + 1;
89
	private final static int MORE_ID = IDialogConstants.CLIENT_ID + 1;
75
    private final static int PLUGINS_ID = IDialogConstants.CLIENT_ID + 2;
90
	private final static int PLUGINS_ID = IDialogConstants.CLIENT_ID + 2;
91
76
92
	private Table table;
77
	private Table table;
93
	private Label imageLabel;
78
	private Label imageLabel;
Lines 96-113 Link Here
96
81
97
	private Map cachedImages = new HashMap();
82
	private Map cachedImages = new HashMap();
98
83
99
	private String columnTitles[] = { IDEWorkbenchMessages.getString("AboutFeaturesDialog.provider"), //$NON-NLS-1$
84
	private String columnTitles[] = {
85
	    IDEWorkbenchMessages.getString("AboutFeaturesDialog.provider"), //$NON-NLS-1$
100
		IDEWorkbenchMessages.getString("AboutFeaturesDialog.featureName"), //$NON-NLS-1$
86
		IDEWorkbenchMessages.getString("AboutFeaturesDialog.featureName"), //$NON-NLS-1$
101
		IDEWorkbenchMessages.getString("AboutFeaturesDialog.version"), //$NON-NLS-1$
87
		IDEWorkbenchMessages.getString("AboutFeaturesDialog.version"), //$NON-NLS-1$
102
		IDEWorkbenchMessages.getString("AboutFeaturesDialog.featureId"), //$NON-NLS-1$
88
		IDEWorkbenchMessages.getString("AboutFeaturesDialog.featureId"), //$NON-NLS-1$
103
	};
89
	};
104
90
105
	private AboutInfo[] featureInfos;
91
	private String productName;
106
	private AboutInfo primaryInfo;
92
	private AboutBundleGroupData[] bundleGroupInfos;
107
93
108
	private int lastColumnChosen = 0; // initially sort by provider
94
	private int lastColumnChosen = 0; // initially sort by provider
109
	private boolean reverseSort = false; // initially sort ascending
95
	private boolean reverseSort = false; // initially sort ascending
110
	private AboutInfo lastSelection = null;
96
	private AboutBundleGroupData lastSelection = null;
111
	private Button moreButton;
97
	private Button moreButton;
112
	private Button pluginsButton;
98
	private Button pluginsButton;
113
99
Lines 116-268 Link Here
116
	/**
102
	/**
117
	 * Constructor for AboutFeaturesDialog
103
	 * Constructor for AboutFeaturesDialog
118
	 */
104
	 */
119
	public AboutFeaturesDialog(
105
	public AboutFeaturesDialog(Shell parentShell, String productName,
120
		Shell parentShell,
106
            AboutBundleGroupData[] bundleGroupInfos) {
121
		AboutInfo primaryInfo,
107
        super(parentShell);
122
		AboutInfo[] featureInfos) {
108
        setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.APPLICATION_MODAL);
123
		super(parentShell);
109
124
		setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.APPLICATION_MODAL);
110
        this.productName = productName;
125
111
        this.bundleGroupInfos = bundleGroupInfos;
126
		this.primaryInfo = primaryInfo;
112
127
		this.featureInfos = featureInfos;
113
        AboutData.sortByProvider(reverseSort, bundleGroupInfos);
128
114
    }
129
		sortByProvider();
115
130
	}
116
	/**
131
117
	 * The More Info button was pressed.  Open a browser with the license for the
132
	/* (non-Javadoc)
118
	 * selected item or an information dialog if there is no license, or the browser
133
	 * Method declared on Dialog.
119
	 * cannot be opened. 
134
	 */
120
	 */
135
	protected void buttonPressed(int buttonId) {
121
	private void handleMoreInfoPressed() {
136
		switch (buttonId) {
122
        TableItem[] items = table.getSelection();
137
			case MORE_ID :
123
        if (items.length <= 0)
138
				{
124
            return;
139
					TableItem[] items = table.getSelection();
125
140
					if (items.length > 0) {
126
        AboutBundleGroupData info = (AboutBundleGroupData) items[0].getData();
141
						AboutInfo info = (AboutInfo) items[0].getData();
127
        IFeature feature = getFeatureFor(info);
142
						IFeature feature = getFeatureFor(info);
128
        IURLEntry entry = feature == null ? null : feature.getLicense();
143
						IURLEntry entry = feature == null ? null : feature.getLicense(); 
129
        if (feature == null || entry == null || !openBrowser(entry.getURL())) {
144
						if (feature == null || entry == null
130
            MessageDialog.openInformation(getShell(), IDEWorkbenchMessages
145
								|| !openBrowser(entry.getURL()))
131
                    .getString("AboutFeaturesDialog.noInfoTitle"), //$NON-NLS-1$
146
							MessageDialog
132
                    IDEWorkbenchMessages
147
									.openInformation(
133
                            .getString("AboutFeaturesDialog.noInformation")); //$NON-NLS-1$
148
											getShell(),
134
        }
149
											IDEWorkbenchMessages
135
    }
150
													.getString("AboutFeaturesDialog.noInfoTitle"), //$NON-NLS-1$
136
151
											IDEWorkbenchMessages
137
	/**
152
													.getString("AboutFeaturesDialog.noInformation")); //$NON-NLS-1$
138
     * The Plugins button was pressed. Open an about dialog on the plugins for
153
					}
139
     * the selected feature.
154
					return;
140
     */
155
				}
141
    private void handlePluginInfoPressed() {
156
			case PLUGINS_ID :
142
        TableItem[] items = table.getSelection();
157
				{
143
        if (items.length <= 0)
158
					TableItem[] items = table.getSelection();
144
            return;
159
					if (items.length > 0) {
145
160
						AboutInfo info = (AboutInfo) items[0].getData();
146
        AboutBundleGroupData info = (AboutBundleGroupData) items[0].getData();
161
						IFeature feature = getFeatureFor(info);
147
        IBundleGroup bundleGroup = info.getBundleGroup();
162
						IPluginDescriptor[] descriptors;
148
        Bundle[] bundles = bundleGroup == null ? new Bundle[0] : bundleGroup
163
						if (feature == null)
149
                .getBundles();
164
							descriptors = new IPluginDescriptor[0];
150
165
						else
151
        AboutPluginsDialog d = new AboutPluginsDialog(getShell(), productName,
166
							descriptors = getPluginsFor(feature);
152
                bundles, IDEWorkbenchMessages
167
						AboutPluginsDialog d =
153
                        .getString("AboutFeaturesDialog.pluginInfoTitle"), //$NON-NLS-1$
168
							new AboutPluginsDialog(
154
                IDEWorkbenchMessages.format(
169
								getShell(),
155
                        "AboutFeaturesDialog.pluginInfoMessage", //$NON-NLS-1$
170
								primaryInfo,
156
                        new Object[] { bundleGroup.getIdentifier()}),
171
								descriptors,
157
                IHelpContextIds.ABOUT_FEATURES_PLUGINS_DIALOG);
172
								IDEWorkbenchMessages.getString(
158
        d.open();
173
									"AboutFeaturesDialog.pluginInfoTitle"), //$NON-NLS-1$
159
    }
174
								IDEWorkbenchMessages.format(
160
175
									"AboutFeaturesDialog.pluginInfoMessage", //$NON-NLS-1$
161
	/*
176
									new Object[] { info.getFeatureLabel()}),
162
     * (non-Javadoc) Method declared on Dialog.
177
								IHelpContextIds.ABOUT_FEATURES_PLUGINS_DIALOG);
163
     */
178
						d.open();
164
    protected void buttonPressed(int buttonId) {
179
					}
165
        switch (buttonId) {
180
					return;
166
        case MORE_ID:
181
				}
167
            handleMoreInfoPressed();
182
		}
168
            break;
183
		super.buttonPressed(buttonId);
169
        case PLUGINS_ID:
184
	}
170
            handlePluginInfoPressed();
171
            break;
172
        default:
173
            super.buttonPressed(buttonId);
174
            break;
175
        }
176
    }
177
178
	/*
179
     * (non-Javadoc) Method declared on Window.
180
     */
181
    protected void configureShell(Shell newShell) {
182
        super.configureShell(newShell);
183
        if (productName != null)
184
            newShell.setText(IDEWorkbenchMessages.format(
185
                    "AboutFeaturesDialog.shellTitle", //$NON-NLS-1$
186
                    new Object[] { productName }));
187
188
        WorkbenchHelp.setHelp(newShell, IHelpContextIds.ABOUT_FEATURES_DIALOG);
189
    }
190
191
    /**
192
     * Add buttons to the dialog's button bar.
193
     * 
194
     * Subclasses should override.
195
     * 
196
     * @param parent
197
     *            the button bar composite
198
     */
199
    protected void createButtonsForButtonBar(Composite parent) {
200
        parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
201
202
        moreButton = createButton(parent, MORE_ID, IDEWorkbenchMessages
203
                .getString("AboutFeaturesDialog.moreInfo"), false); //$NON-NLS-1$
204
        pluginsButton = createButton(parent, PLUGINS_ID, IDEWorkbenchMessages
205
                .getString("AboutFeaturesDialog.pluginsInfo"), false); //$NON-NLS-1$
206
207
        Label l = new Label(parent, SWT.NONE);
208
        l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
209
        GridLayout layout = (GridLayout) parent.getLayout();
210
        layout.numColumns++;
211
        layout.makeColumnsEqualWidth = false;
212
213
        Button b = createButton(parent, IDialogConstants.OK_ID,
214
                IDialogConstants.OK_LABEL, true);
215
        b.setFocus();
216
217
        TableItem[] items = table.getSelection();
218
        if (items.length > 0)
219
            updateButtons((AboutBundleGroupData) items[0].getData());
220
    }
221
222
	/**
223
     * Create the contents of the dialog (above the button bar).
224
     * 
225
     * Subclasses should overide.
226
     * 
227
     * @param the
228
     *            parent composite to contain the dialog area
229
     * @return the dialog area control
230
     */
231
    protected Control createDialogArea(Composite parent) {
232
        setHandCursor(new Cursor(parent.getDisplay(), SWT.CURSOR_HAND));
233
        setBusyCursor(new Cursor(parent.getDisplay(), SWT.CURSOR_WAIT));
234
        getShell().addDisposeListener(new DisposeListener() {
235
            public void widgetDisposed(DisposeEvent e) {
236
                if (getHandCursor() != null)
237
                    getHandCursor().dispose();
238
                if (getBusyCursor() != null)
239
                    getBusyCursor().dispose();
240
            }
241
        });
242
243
        Composite outer = (Composite) super.createDialogArea(parent);
244
245
        createTable(outer);
246
        createInfoArea(outer);
247
248
        GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL,
249
                GridData.VERTICAL_ALIGN_FILL, true, true);
250
        gridData.heightHint = convertVerticalDLUsToPixels(TABLE_HEIGHT);
251
        table.setLayoutData(gridData);
185
252
186
	/* (non-Javadoc)
253
        return outer;
187
	 * Method declared on Window.
254
    }
188
	 */
189
	protected void configureShell(Shell newShell) {
190
		super.configureShell(newShell);
191
		String title = null;
192
		if (primaryInfo != null) {
193
			title = primaryInfo.getProductName();
194
		}
195
		if (title != null) {
196
			newShell.setText(IDEWorkbenchMessages.format("AboutFeaturesDialog.shellTitle", //$NON-NLS-1$
197
			new Object[] { title }));
198
		}
199
		WorkbenchHelp.setHelp(newShell, IHelpContextIds.ABOUT_FEATURES_DIALOG);
200
	}
201
	/**
202
	 * Add buttons to the dialog's button bar.
203
	 *
204
	 * Subclasses should override.
205
	 *
206
	 * @param parent the button bar composite
207
	 */
208
	protected void createButtonsForButtonBar(Composite parent) {
209
		parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
210
255
211
		moreButton = createButton(parent, MORE_ID, IDEWorkbenchMessages.getString("AboutFeaturesDialog.moreInfo"), false); //$NON-NLS-1$
256
    /** 
212
		pluginsButton = createButton(parent, PLUGINS_ID, IDEWorkbenchMessages.getString("AboutFeaturesDialog.pluginsInfo"), false); //$NON-NLS-1$
213
214
		Label l = new Label(parent, SWT.NONE);
215
		l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
216
		GridLayout layout = (GridLayout) parent.getLayout();
217
		layout.numColumns++;
218
		layout.makeColumnsEqualWidth = false;
219
220
		Button b = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
221
		b.setFocus();
222
223
		TableItem[] items = table.getSelection();
224
		if (items.length > 0)
225
			updateButtons((AboutInfo) items[0].getData());
226
	}
227
228
	/**
229
	 * Create the contents of the dialog (above the button bar).
230
	 *
231
	 * Subclasses should overide.
232
	 *
233
	 * @param the parent composite to contain the dialog area
234
	 * @return the dialog area control
235
	 */
236
	protected Control createDialogArea(Composite parent) {
237
		setHandCursor(new Cursor(parent.getDisplay(), SWT.CURSOR_HAND));
238
		setBusyCursor(new Cursor(parent.getDisplay(), SWT.CURSOR_WAIT));
239
		getShell().addDisposeListener(new DisposeListener() {
240
			public void widgetDisposed(DisposeEvent e) {
241
				if (getHandCursor() != null)
242
					getHandCursor().dispose();
243
				if (getBusyCursor() != null)
244
					getBusyCursor().dispose();
245
			}
246
		});
247
248
		Composite outer = (Composite) super.createDialogArea(parent);
249
250
		createTable(outer);
251
		createColumns();
252
		createInfoArea(outer);
253
254
		GridData gridData =
255
			new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
256
		gridData.grabExcessVerticalSpace = true;
257
		gridData.grabExcessHorizontalSpace = true;
258
259
		// suggest a height for the table
260
		gridData.heightHint = convertVerticalDLUsToPixels(TABLE_HEIGHT);
261
		table.setLayoutData(gridData);
262
263
		return outer;
264
	}
265
	/** 
266
	 * Create the info area containing the image and text
257
	 * Create the info area containing the image and text
267
	 */
258
	 */
268
	protected void createInfoArea(Composite parent) {
259
	protected void createInfoArea(Composite parent) {
Lines 303-309 Link Here
303
294
304
		TableItem[] items = table.getSelection();
295
		TableItem[] items = table.getSelection();
305
		if (items.length > 0)
296
		if (items.length > 0)
306
			updateInfoArea((AboutInfo) items[0].getData());
297
			updateInfoArea((AboutBundleGroupData) items[0].getData());
307
	}
298
	}
308
299
309
	/**
300
	/**
Lines 312-786 Link Here
312
	 * @param the parent composite to contain the dialog area
303
	 * @param the parent composite to contain the dialog area
313
	 */
304
	 */
314
	protected void createTable(Composite parent) {
305
	protected void createTable(Composite parent) {
315
		table =
306
        table = new Table(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE
316
			new Table(
307
                | SWT.FULL_SELECTION | SWT.BORDER);
317
				parent,
308
        table.setHeaderVisible(true);
318
				SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER);
309
        table.setLinesVisible(true);
319
		table.setHeaderVisible(true);
310
        table.setFont(parent.getFont());
320
		table.setLinesVisible(true);
311
        table.addSelectionListener(new SelectionAdapter() {
321
		table.setFont(parent.getFont());
322
323
		SelectionListener listener = new SelectionAdapter() {
324
			public void widgetSelected(SelectionEvent e) {
312
			public void widgetSelected(SelectionEvent e) {
325
				AboutInfo info = (AboutInfo) e.item.getData();
313
				AboutBundleGroupData info = (AboutBundleGroupData) e.item.getData();
326
				updateInfoArea(info);
314
				updateInfoArea(info);
327
				updateButtons(info);
315
				updateButtons(info);
328
			}
316
			}
329
		};
330
		table.addSelectionListener(listener);
331
	}
332
	/**
333
	 * @see Window#close()
334
	 */
335
	public boolean close() {
336
		Collection values = cachedImages.values();
337
		for (Iterator iter = values.iterator(); iter.hasNext();) {
338
			Image image = (Image) iter.next();
339
			image.dispose();
340
		}
341
		return super.close();
342
	}
343
	/**
344
	 * Returns a mapping from feature id to feature
345
	 */
346
	private Map getFeaturesMap() {
347
		if (featuresMap != null)
348
			return featuresMap;
349
350
		featuresMap = new HashMap();
351
352
		IPluginRegistry reg = Platform.getPluginRegistry();
353
		if (reg == null) {
354
			MessageDialog.openError(getShell(), IDEWorkbenchMessages.getString("AboutFeaturesDialog.errorTitle"), //$NON-NLS-1$
355
			IDEWorkbenchMessages.getString("AboutFeaturesDialog.unableToObtainFeatureInfo")); //$NON-NLS-1$
356
			return featuresMap;
357
		}
358
359
		final ILocalSite[] localSiteArray = new ILocalSite[1];
360
		BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
361
			public void run() {
362
				// this may take a few seconds
363
				try {
364
					localSiteArray[0] = SiteManager.getLocalSite();
365
				} catch (CoreException e) {
366
					MessageDialog.openError(getShell(), IDEWorkbenchMessages.getString("AboutFeaturesDialog.errorTitle"), //$NON-NLS-1$
367
					IDEWorkbenchMessages.getString("AboutFeaturesDialog.unableToObtainFeatureInfo")); //$NON-NLS-1$
368
				}
369
			}
370
		});
317
		});
371
		if (localSiteArray[0] == null)
372
			return featuresMap;
373
374
		IInstallConfiguration installConfiguration = localSiteArray[0].getCurrentConfiguration();
375
		IConfiguredSite[] configuredSites = installConfiguration.getConfiguredSites();
376
377
		for (int i = 0; i < configuredSites.length; i++) {
378
			IFeatureReference[] featureReferences = configuredSites[i].getConfiguredFeatures();
379
			for (int j = 0; j < featureReferences.length; j++) {
380
				IFeature feature;
381
				try {
382
					feature = featureReferences[j].getFeature(new NullProgressMonitor());
383
				} catch (CoreException e) {
384
					// just skip it
385
					break;
386
				}
387
				String key = feature.getVersionedIdentifier().toString();
388
				featuresMap.put(key, feature);
389
			}
390
		}
391
		return featuresMap;
392
	}
393
394
	/**
395
	 * Return the feature for the given info
396
	 */
397
	private IFeature getFeatureFor(AboutInfo info) {
398
		Map map = getFeaturesMap();
399
		if (map == null)
400
			return null;
401
		String key = info.getFeatureId() + "_" + info.getVersionId(); //$NON-NLS-1$
402
		return (IFeature) map.get(key);
403
	}
404
405
	/**
406
	 * Return the plugins for the given feature
407
	 */
408
	private IPluginDescriptor[] getPluginsFor(IFeature feature) {
409
		IPluginRegistry reg = Platform.getPluginRegistry();
410
		if (reg == null)
411
			return new IPluginDescriptor[0];
412
		IPluginEntry[] pluginEntries = feature.getPluginEntries();
413
		ArrayList plugins = new ArrayList();
414
		for (int k = 0; k < pluginEntries.length; k++) {
415
			VersionedIdentifier id = pluginEntries[k].getVersionedIdentifier();
416
417
			IPluginDescriptor desc = reg.getPluginDescriptor(id.getIdentifier(), id.getVersion());
418
			if (desc != null)
419
				plugins.add(desc);
420
		}
421
		return (IPluginDescriptor[]) plugins.toArray(new IPluginDescriptor[plugins.size()]);
422
	}
423
424
	/**
425
	 * Update the button enablement
426
	 */
427
	private void updateButtons(AboutInfo info) {
428
		if (info == null) {
429
			moreButton.setEnabled(false);
430
			pluginsButton.setEnabled(false);
431
			return;
432
		}
433
		boolean shouldEnable = true; // by default enable
434
		// Avoid creating the map just to determine enablement
435
		if (featuresMap != null) {
436
			IFeature feature = getFeatureFor(info);
437
			shouldEnable = feature != null && feature.getLicense() != null;
438
		}
439
		moreButton.setEnabled(shouldEnable);
440
441
		// Assume there is at least one plugin		
442
		shouldEnable = true; // by default enable
443
		if (featuresMap != null) {
444
			IFeature feature = getFeatureFor(info);
445
			shouldEnable = feature != null;
446
		}
447
		pluginsButton.setEnabled(shouldEnable);
448
	}
449
450
	/**
451
	 * Update the info area
452
	 */
453
	private void updateInfoArea(AboutInfo info) {
454
		if (info == null) {
455
			imageLabel.setImage(null);
456
			text.setText(""); //$NON-NLS-1$
457
			return;
458
		}
459
		ImageDescriptor desc = info.getFeatureImage();
460
		Image image = (Image) cachedImages.get(desc);
461
		if (image == null && desc != null) {
462
			image = desc.createImage();
463
			cachedImages.put(desc, image);
464
		}
465
		imageLabel.setImage(image);
466
		String aboutText = info.getAboutText();
467
		setItem(null);
468
		if (aboutText != null) {
469
			// get an about item
470
			setItem(scan(aboutText));
471
		}
472
		if (getItem() == null)
473
			text.setText(IDEWorkbenchMessages.getString("AboutFeaturesDialog.noInformation")); //$NON-NLS-1$
474
		else {
475
			text.setText(getItem().getText());
476
			text.setCursor(null);
477
			setLinkRanges(text, getItem().getLinkRanges());
478
		}
479
	}
480
318
481
	/** 
319
    	int[] columnWidths = {
482
	* Select the initial selection
320
    	        convertHorizontalDLUsToPixels(120),
483
	* 
321
                convertHorizontalDLUsToPixels(120),
484
	*/
322
                convertHorizontalDLUsToPixels(70),
485
	public void setInitialSelection(AboutInfo info) {
323
                convertHorizontalDLUsToPixels(130)
486
		lastSelection = info;
324
    	};
487
	}
488
325
489
	/**
490
	 * Populate the table with plugin info obtained from the registry.
491
	 *
492
	 * @param the parent composite to contain the dialog area
493
	 */
494
	protected void createColumns() {
495
		/* create table headers */
496
		int[] columnWidths =
497
			{
498
				convertHorizontalDLUsToPixels(120),
499
				convertHorizontalDLUsToPixels(180),
500
				convertHorizontalDLUsToPixels(70),
501
				convertHorizontalDLUsToPixels(70)};
502
		for (int i = 0; i < columnTitles.length; i++) {
326
		for (int i = 0; i < columnTitles.length; i++) {
503
			TableColumn tableColumn = new TableColumn(table, SWT.NULL);
327
            TableColumn tableColumn = new TableColumn(table, SWT.NULL);
504
			tableColumn.setWidth(columnWidths[i]);
328
            tableColumn.setWidth(columnWidths[i]);
505
			tableColumn.setText(columnTitles[i]);
329
            tableColumn.setText(columnTitles[i]);
506
			final int columnIndex = i;
330
            final int columnIndex = i;
507
			tableColumn.addSelectionListener(new SelectionAdapter() {
331
            tableColumn.addSelectionListener(new SelectionAdapter() {
508
				public void widgetSelected(SelectionEvent e) {
332
                public void widgetSelected(SelectionEvent e) {
509
					sort(columnIndex);
333
                    sort(columnIndex);
510
				}
334
                }
511
			});
335
            });
512
336
        }
513
		}
337
338
		// create a table row for each bundle group
339
		String selId = lastSelection == null ? null : lastSelection.getId();
340
		int sel = 0;
341
		for (int i = 0; i < bundleGroupInfos.length; i++) {
342
			if (bundleGroupInfos[i].getId().equals(selId))
343
			    sel = i;
514
344
515
		int initialSelectionIndex = 0;
516
		/* fill each row of the table with feature info */
517
		for (int i = 0; i < featureInfos.length; i++) {
518
			if (featureInfos[i] == lastSelection)
519
				initialSelectionIndex = i;
520
			String provider = featureInfos[i].getProviderName();
521
			String featureName = featureInfos[i].getFeatureLabel();
522
			String versionId = featureInfos[i].getVersionId();
523
			String featureId = featureInfos[i].getFeatureId();
524
			if (provider == null)
525
				provider = ""; //$NON-NLS-1$
526
			if (featureName == null)
527
				featureName = ""; //$NON-NLS-1$
528
			if (versionId == null)
529
				versionId = ""; //$NON-NLS-1$
530
			if (featureId == null)
531
				featureId = ""; //$NON-NLS-1$				
532
			String[] row = { provider, featureName, versionId, featureId };
533
			TableItem item = new TableItem(table, SWT.NULL);
345
			TableItem item = new TableItem(table, SWT.NULL);
534
			item.setText(row);
346
			item.setText(createRow(bundleGroupInfos[i]));
535
			item.setData(featureInfos[i]);
347
			item.setData(bundleGroupInfos[i]);
536
		}
537
538
		// set initial selection
539
		if (featureInfos.length > 0) {
540
			table.setSelection(initialSelectionIndex);
541
		}
348
		}
542
	}
543
349
544
	/**
350
		// if an item was specified during construction, it should be
545
	 * Sort the rows of the table based on the selected column.
351
		// selected when the table is created
546
	 *
352
		if (bundleGroupInfos.length > 0) {
547
	 * @param column index of table column selected as sort criteria
353
			table.setSelection(sel);
548
	 */
549
	private void sort(int column) {
550
		// Choose new sort algorithm
551
		if (lastColumnChosen == column) {
552
			reverseSort = !reverseSort;
553
		} else {
554
			reverseSort = false;
555
			lastColumnChosen = column;
556
		}
557
558
		if (table.getItemCount() <= 1)
559
			return;
560
561
		// Remember the last selection
562
		int idx = table.getSelectionIndex();
563
		if (idx != -1)
564
			lastSelection = featureInfos[idx];
565
566
		switch (column) {
567
			case 0 :
568
				sortByProvider();
569
				break;
570
			case 1 :
571
				sortByName();
572
				break;
573
			case 2 :
574
				sortByVersion();
575
				break;
576
			case 3 :
577
				sortByFeatureId();
578
				break;
579
		}
580
581
		refreshTable(column);
582
	}
583
584
	/**
585
	 * Refresh the rows of the table based on the selected column.
586
	 * Maintain selection from before sort action request.
587
	 *
588
	 * @param items the old state table items 
589
	 */
590
	private void refreshTable(int col) {
591
		TableItem[] items = table.getItems();
592
		int idx = -1; // the new index of the selection
593
		// Create new order of table items
594
		for (int i = 0; i < items.length; i++) {
595
			String provider = featureInfos[i].getProviderName();
596
			String featureName = featureInfos[i].getFeatureLabel();
597
			String versionId = featureInfos[i].getVersionId();
598
			String featureId = featureInfos[i].getFeatureId();
599
			if (provider == null)
600
				provider = ""; //$NON-NLS-1$
601
			if (featureName == null)
602
				featureName = ""; //$NON-NLS-1$
603
			if (versionId == null)
604
				versionId = ""; //$NON-NLS-1$
605
			if (featureId == null)
606
				featureId = ""; //$NON-NLS-1$
607
			String[] row = { provider, featureName, versionId, featureId };
608
			items[i].setText(row);
609
			items[i].setData(featureInfos[i]);
610
		}
611
		// Maintain the original selection
612
		if (lastSelection != null) {
613
			for (int k = 0; k < featureInfos.length; k++) {
614
				if (lastSelection == featureInfos[k])
615
					idx = k;
616
			}
617
			table.setSelection(idx);
618
			table.showSelection();
354
			table.showSelection();
619
		}
355
		}
620
621
		updateInfoArea(lastSelection);
622
	}
356
	}
623
	/**
624
	 * Sort the rows of the table based on the plugin provider.
625
	 * Secondary criteria is unique plugin id.
626
	 */
627
	private void sortByProvider() {
628
		/* If sorting in reverse, info array is already sorted forward by
629
		 * key so the info array simply needs to be reversed.
630
		 */
631
		if (reverseSort) {
632
			java.util.List infoList = Arrays.asList(featureInfos);
633
			Collections.reverse(infoList);
634
			for (int i = 0; i < featureInfos.length; i++) {
635
				featureInfos[i] = (AboutInfo) infoList.get(i);
636
			}
637
		} else {
638
			// Sort ascending
639
			Arrays.sort(featureInfos, new Comparator() {
640
				Collator coll = Collator.getInstance(Locale.getDefault());
641
				public int compare(Object a, Object b) {
642
					AboutInfo i1, i2;
643
					String provider1, provider2, name1, name2;
644
					i1 = (AboutInfo) a;
645
					provider1 = i1.getProviderName();
646
					name1 = i1.getFeatureLabel();
647
					if (provider1 == null)
648
						provider1 = ""; //$NON-NLS-1$
649
					if (name1 == null)
650
						name1 = ""; //$NON-NLS-1$
651
					i2 = (AboutInfo) b;
652
					provider2 = i2.getProviderName();
653
					name2 = i2.getFeatureLabel();
654
					if (provider2 == null)
655
						provider2 = ""; //$NON-NLS-1$
656
					if (name2 == null)
657
						name2 = ""; //$NON-NLS-1$
658
					if (provider1.equals(provider2))
659
						return coll.compare(name1, name2);
660
					else
661
						return coll.compare(provider1, provider2);
662
				}
663
			});
664
		}
665
	}
666
	/**
667
	 * Sort the rows of the table based on unique plugin id.
668
	 */
669
	private void sortByName() {
670
		/* If sorting in reverse, info array is already sorted forward by
671
		 * key so the info array simply needs to be reversed.
672
		 */
673
		if (reverseSort) {
674
			java.util.List infoList = Arrays.asList(featureInfos);
675
			Collections.reverse(infoList);
676
			for (int i = 0; i < featureInfos.length; i++) {
677
				featureInfos[i] = (AboutInfo) infoList.get(i);
678
			}
679
		} else {
680
			// Sort ascending
681
			Arrays.sort(featureInfos, new Comparator() {
682
				Collator coll = Collator.getInstance(Locale.getDefault());
683
				public int compare(Object a, Object b) {
684
					AboutInfo i1, i2;
685
					String name1, name2;
686
					i1 = (AboutInfo) a;
687
					name1 = i1.getFeatureLabel();
688
					i2 = (AboutInfo) b;
689
					name2 = i2.getFeatureLabel();
690
					if (name1 == null)
691
						name1 = ""; //$NON-NLS-1$
692
					if (name2 == null)
693
						name2 = ""; //$NON-NLS-1$
694
					return coll.compare(name1, name2);
695
				}
696
			});
697
		}
698
357
699
	}
700
	/**
701
	 * Sort the rows of the table based on the plugin version.
702
	 * Secondary criteria is unique plugin id.
703
	 */
704
	private void sortByVersion() {
705
		/* If sorting in reverse, info array is already sorted forward by
706
		 * key so the info array simply needs to be reversed.
707
		 */
708
		if (reverseSort) {
709
			java.util.List infoList = Arrays.asList(featureInfos);
710
			Collections.reverse(infoList);
711
			for (int i = 0; i < featureInfos.length; i++) {
712
				featureInfos[i] = (AboutInfo) infoList.get(i);
713
			}
714
		} else {
715
			// Sort ascending
716
			Arrays.sort(featureInfos, new Comparator() {
717
				Collator coll = Collator.getInstance(Locale.getDefault());
718
				public int compare(Object a, Object b) {
719
					AboutInfo i1, i2;
720
					String version1, version2, name1, name2;
721
					i1 = (AboutInfo) a;
722
					version1 = i1.getVersionId();
723
					name1 = i1.getFeatureLabel();
724
					if (version1 == null)
725
						version1 = ""; //$NON-NLS-1$
726
					if (name1 == null)
727
						name1 = ""; //$NON-NLS-1$
728
					i2 = (AboutInfo) b;
729
					version2 = i2.getVersionId();
730
					name2 = i2.getFeatureLabel();
731
					if (version2 == null)
732
						version2 = ""; //$NON-NLS-1$
733
					if (name2 == null)
734
						name2 = ""; //$NON-NLS-1$
735
					if (version1.equals(version2))
736
						return coll.compare(name1, name2);
737
					else
738
						return coll.compare(version1, version2);
739
				}
740
			});
741
		}
742
	}
743
	/**
358
	/**
744
	 * Sort the rows of the table based on the feature Id.
359
     * @see Window#close()
745
	 * Secondary criteria is unique plugin id.
360
     */
746
	 */
361
    public boolean close() {
747
	private void sortByFeatureId() {
362
        boolean ret = super.close();
748
		/* If sorting in reverse, info array is already sorted forward by
363
749
		 * key so the info array simply needs to be reversed.
364
        Iterator iter = cachedImages.values().iterator();
750
		 */
365
        while (iter.hasNext()) {
751
		if (reverseSort) {
366
            Image image = (Image) iter.next();
752
			java.util.List infoList = Arrays.asList(featureInfos);
367
            image.dispose();
753
			Collections.reverse(infoList);
368
        }
754
			for (int i = 0; i < featureInfos.length; i++) {
369
755
				featureInfos[i] = (AboutInfo) infoList.get(i);
370
        return ret;
756
			}
371
    }
757
		} else {
372
758
			// Sort ascending
373
	/**
759
			Arrays.sort(featureInfos, new Comparator() {
374
     * Returns a mapping from feature id to feature.
760
				Collator coll = Collator.getInstance(Locale.getDefault());
375
     */
761
				public int compare(Object a, Object b) {
376
    private Map getFeaturesMap() {
762
					AboutInfo i1, i2;
377
        if (featuresMap != null) return featuresMap;
763
					String featureId1, featureId2, name1, name2;
378
764
					i1 = (AboutInfo) a;
379
        featuresMap = new HashMap();
765
					featureId1 = i1.getFeatureId();
380
766
					name1 = i1.getFeatureLabel();
381
        final ILocalSite[] localSiteArray = new ILocalSite[1];
767
					if (featureId1 == null)
382
        BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
768
						featureId1 = ""; //$NON-NLS-1$
383
            public void run() {
769
					if (name1 == null)
384
                // this may take a few seconds
770
						name1 = ""; //$NON-NLS-1$
385
                try {
771
					i2 = (AboutInfo) b;
386
                    localSiteArray[0] = SiteManager.getLocalSite();
772
					featureId2 = i2.getFeatureId();
387
                } catch (CoreException e) {
773
					name2 = i2.getFeatureLabel();
388
                    MessageDialog
774
					if (featureId2 == null)
389
                    	.openError(
775
						featureId2 = ""; //$NON-NLS-1$
390
                    	        getShell(),
776
					if (name2 == null)
391
                                IDEWorkbenchMessages
777
						name2 = ""; //$NON-NLS-1$
392
                                	.getString("AboutFeaturesDialog.errorTitle"), //$NON-NLS-1$
778
					if (featureId1.equals(featureId2))
393
                                IDEWorkbenchMessages
779
						return coll.compare(name1, name2);
394
                                	.getString("AboutFeaturesDialog.unableToObtainFeatureInfo")); //$NON-NLS-1$
780
					else
395
                }
781
						return coll.compare(featureId1, featureId2);
396
            }
782
				}
397
        });
783
			});
398
        if (localSiteArray[0] == null)
784
		}
399
            return featuresMap;
785
	}
400
786
}
401
        IInstallConfiguration installConfiguration = localSiteArray[0]
402
                .getCurrentConfiguration();
403
        IConfiguredSite[] configuredSites = installConfiguration
404
                .getConfiguredSites();
405
406
        for (int i = 0; i < configuredSites.length; i++) {
407
            IFeatureReference[] featureReferences = configuredSites[i]
408
                    .getConfiguredFeatures();
409
410
            for (int j = 0; j < featureReferences.length; j++) {
411
                try {
412
                    IFeature feature = featureReferences[j]
413
                            .getFeature(new NullProgressMonitor());
414
415
                    String key = feature.getVersionedIdentifier().toString();
416
                    featuresMap.put(key, feature);
417
                } catch (CoreException e) {
418
                    // do nothing
419
                }
420
            }
421
        }
422
423
        return featuresMap;
424
    }
425
426
	/**
427
     * Return the feature for the given bundle group.
428
     */
429
    private IFeature getFeatureFor(AboutBundleGroupData info) {
430
        Map map = getFeaturesMap();
431
        if (map == null)
432
            return null;
433
434
        String key = info.getId() + "_" + info.getVersion(); //$NON-NLS-1$
435
        return (IFeature) map.get(key);
436
    }
437
438
	/**
439
     * Update the button enablement
440
     */
441
    private void updateButtons(AboutBundleGroupData info) {
442
        if (info == null) {
443
            moreButton.setEnabled(false);
444
            pluginsButton.setEnabled(false);
445
            return;
446
        }
447
448
        // Creating the feature map is too much just to determine enablement, so if
449
        // it doesn't already exist, just enable the buttons.  If this was the wrong
450
        // choice, then when the button is actually pressed an dialog will be opened. 
451
        if(featuresMap == null) {
452
            moreButton.setEnabled(true);
453
            pluginsButton.setEnabled(true);
454
            return;
455
        }
456
457
        IFeature feature = getFeatureFor(info);
458
        moreButton.setEnabled(feature != null && feature.getLicense() != null);
459
        pluginsButton.setEnabled(feature != null);
460
    }
461
462
	/**
463
     * Update the info area
464
     */
465
    private void updateInfoArea(AboutBundleGroupData info) {
466
        if (info == null) {
467
            imageLabel.setImage(null);
468
            text.setText(""); //$NON-NLS-1$
469
            return;
470
        }
471
472
        ImageDescriptor desc = info.getFeatureImage();
473
        Image image = (Image) cachedImages.get(desc);
474
        if (image == null && desc != null) {
475
            image = desc.createImage();
476
            cachedImages.put(desc, image);
477
        }
478
        imageLabel.setImage(image);
479
480
        String aboutText = info.getAboutText();
481
        setItem(null);
482
        if (aboutText != null)
483
            setItem(scan(aboutText));
484
485
        if (getItem() == null)
486
            text.setText(IDEWorkbenchMessages
487
                    .getString("AboutFeaturesDialog.noInformation")); //$NON-NLS-1$
488
        else {
489
            text.setText(getItem().getText());
490
            text.setCursor(null);
491
            setLinkRanges(text, getItem().getLinkRanges());
492
        }
493
    }
494
495
	/**
496
     * Select the initial selection
497
     */
498
    public void setInitialSelection(AboutBundleGroupData info) {
499
        lastSelection = info;
500
    }
501
502
	/**
503
     * Sort the rows of the table based on the selected column.
504
     * 
505
     * @param column
506
     *            index of table column selected as sort criteria
507
     */
508
    private void sort(int column) {
509
        if (lastColumnChosen == column)
510
            reverseSort = !reverseSort;
511
        else {
512
            reverseSort = false;
513
            lastColumnChosen = column;
514
        }
515
516
        if (table.getItemCount() <= 1)
517
            return;
518
519
        // Remember the last selection
520
        int sel = table.getSelectionIndex();
521
        if (sel != -1)
522
            lastSelection = bundleGroupInfos[sel];
523
524
        switch (column) {
525
        case 0:
526
            AboutData.sortByProvider(reverseSort, bundleGroupInfos);
527
            break;
528
        case 1:
529
            AboutData.sortByName(reverseSort, bundleGroupInfos);
530
            break;
531
        case 2:
532
            AboutData.sortByVersion(reverseSort, bundleGroupInfos);
533
            break;
534
        case 3:
535
            AboutData.sortById(reverseSort, bundleGroupInfos);
536
            break;
537
        }
538
539
        refreshTable(column);
540
    }
541
542
	/**
543
     * Refresh the rows of the table based on the selected column. Maintain
544
     * selection from before sort action request.
545
     */
546
    private void refreshTable(int col) {
547
        TableItem[] items = table.getItems();
548
549
        // create new order of table items
550
        for (int i = 0; i < items.length; i++) {
551
            items[i].setText(createRow(bundleGroupInfos[i]));
552
            items[i].setData(bundleGroupInfos[i]);
553
        }
554
555
        // Maintain the original selection
556
        int sel = -1;
557
        if (lastSelection != null) {
558
            String oldId = lastSelection.getId();
559
            for (int k = 0; k < bundleGroupInfos.length; k++)
560
                if (oldId.equalsIgnoreCase(bundleGroupInfos[k].getId()))
561
                    sel = k;
562
563
            table.setSelection(sel);
564
            table.showSelection();
565
        }
566
567
        updateInfoArea(lastSelection);
568
    }
569
570
    /**
571
     * Return an array of strings containing the argument's information in the
572
     * proper order for this table's columns.
573
     * 
574
     * @param info
575
     *            the source information for the new row, must not be null
576
     */
577
    private static String[] createRow(AboutBundleGroupData info) {
578
        return new String[] { info.getProviderName(), info.getName(),
579
                info.getVersion(), info.getId()};
580
    }
581
}
(-)src/org/eclipse/ui/internal/ide/dialogs/AboutPluginsDialog.java (-458 / +309 lines)
Lines 1-34 Link Here
1
/******************************************************************************* 
1
/******************************************************************************* 
2
 * Copyright (c) 2000, 2003 IBM Corporation and others. 
2
 * Copyright (c) 2000, 2004 IBM Corporation and others. 
3
 * All rights reserved. This program and the accompanying materials! 
3
 * All rights reserved. This program and the accompanying materials! 
4
 * are made available under the terms of the Common Public License v1.0 
4
 * are made available under the terms of the Common Public License v1.0 
5
 * which accompanies this distribution, and is available at 
5
 * which accompanies this distribution, and is available at 
6
 * http://www.eclipse.org/legal/cpl-v10.html 
6
 * http://www.eclipse.org/legal/cpl-v10.html 
7
 * 
7
 * 
8
 * Contributors: 
8
 * Contributors: 
9
 *     IBM Corporation - initial API and implementation 
9
 *		IBM Corporation - initial API and implementation 
10
 *  	Sebastian Davids <sdavids@gmx.de> - Fix for bug 19346 - Dialog font should be
10
 *  	Sebastian Davids <sdavids@gmx.de> - Fix for bug 19346 - Dialog
11
 * 	    activated and used by other components.
11
 * 		font should be activated and used by other components.
12
************************************************************************/
12
************************************************************************/
13
14
package org.eclipse.ui.internal.ide.dialogs;
13
package org.eclipse.ui.internal.ide.dialogs;
15
14
16
import java.net.URL;
15
import java.net.URL;
17
import java.text.Collator;
16
import java.util.ArrayList;
18
import java.util.Arrays;
19
import java.util.Collections;
20
import java.util.Comparator;
21
import java.util.Locale;
22
17
23
import org.eclipse.core.runtime.IPluginDescriptor;
18
import org.eclipse.core.runtime.IPluginDescriptor;
24
import org.eclipse.core.runtime.Path;
25
import org.eclipse.core.runtime.Platform;
19
import org.eclipse.core.runtime.Platform;
26
import org.eclipse.jface.dialogs.IDialogConstants;
20
import org.eclipse.jface.dialogs.IDialogConstants;
27
import org.eclipse.jface.dialogs.MessageDialog;
21
import org.eclipse.jface.dialogs.MessageDialog;
28
import org.eclipse.swt.SWT;
22
import org.eclipse.swt.SWT;
29
import org.eclipse.swt.events.SelectionAdapter;
23
import org.eclipse.swt.events.SelectionAdapter;
30
import org.eclipse.swt.events.SelectionEvent;
24
import org.eclipse.swt.events.SelectionEvent;
31
import org.eclipse.swt.events.SelectionListener;
32
import org.eclipse.swt.layout.GridData;
25
import org.eclipse.swt.layout.GridData;
33
import org.eclipse.swt.layout.GridLayout;
26
import org.eclipse.swt.layout.GridLayout;
34
import org.eclipse.swt.widgets.Button;
27
import org.eclipse.swt.widgets.Button;
Lines 40-55 Link Here
40
import org.eclipse.swt.widgets.TableColumn;
33
import org.eclipse.swt.widgets.TableColumn;
41
import org.eclipse.swt.widgets.TableItem;
34
import org.eclipse.swt.widgets.TableItem;
42
import org.eclipse.ui.help.WorkbenchHelp;
35
import org.eclipse.ui.help.WorkbenchHelp;
43
import org.eclipse.ui.internal.AboutInfo;
36
import org.eclipse.ui.internal.ide.AboutBundleData;
37
import org.eclipse.ui.internal.ide.AboutData;
44
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
38
import org.eclipse.ui.internal.ide.IDEWorkbenchMessages;
45
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
39
import org.eclipse.ui.internal.ide.IDEWorkbenchPlugin;
46
import org.eclipse.ui.internal.ide.IHelpContextIds;
40
import org.eclipse.ui.internal.ide.IHelpContextIds;
41
import org.eclipse.ui.internal.util.BundleUtility;
42
import org.osgi.framework.Bundle;
47
43
48
/**
44
/**
49
 * Displays information about the product plugins.
45
 * Displays information about the product plugins.
50
 *
46
 *
51
 * @private
47
 * @private
52
 *		This class is internal to the workbench and must not be called outside the workbench
48
 *		this class is internal to the ide
53
 */
49
 */
54
public class AboutPluginsDialog extends ProductInfoDialog {
50
public class AboutPluginsDialog extends ProductInfoDialog {
55
51
Lines 57-70 Link Here
57
	 * Table height in dialog units (value 200).
53
	 * Table height in dialog units (value 200).
58
	 */
54
	 */
59
	private static final int TABLE_HEIGHT = 200;
55
	private static final int TABLE_HEIGHT = 200;
60
61
	private static final String PLUGININFO = "about.html";	//$NON-NLS-1$
56
	private static final String PLUGININFO = "about.html";	//$NON-NLS-1$
62
	
63
	private final static int MORE_ID = IDialogConstants.CLIENT_ID + 1;
57
	private final static int MORE_ID = IDialogConstants.CLIENT_ID + 1;
64
58
65
	private Table vendorInfo;
59
	private Table vendorInfo;
66
	private Button moreInfo;
60
	private Button moreInfo;
67
	
61
68
	private String title;
62
	private String title;
69
	private String message;
63
	private String message;
70
	private String helpContextId;
64
	private String helpContextId;
Lines 76-545 Link Here
76
		IDEWorkbenchMessages.getString("AboutPluginsDialog.pluginId"), //$NON-NLS-1$
70
		IDEWorkbenchMessages.getString("AboutPluginsDialog.pluginId"), //$NON-NLS-1$
77
	};
71
	};
78
72
79
	private IPluginDescriptor[] info;
73
	private String productName;
74
	private AboutBundleData[] bundleInfos;
80
75
81
	private AboutInfo primaryInfo;
82
	
83
	private int lastColumnChosen = 0;	// initially sort by provider
76
	private int lastColumnChosen = 0;	// initially sort by provider
84
	private boolean reverseSort = false;	// initially sort ascending
77
	private boolean reverseSort = false;	// initially sort ascending
85
	private IPluginDescriptor lastSelection = null;
78
	private AboutBundleData lastSelection = null;
86
	
79
87
	/**
80
	/**
88
	 * Constructor for AboutPluginsDialog
81
	 * Constructor for AboutPluginsDialog
89
	 */
82
	 */
90
	public AboutPluginsDialog(Shell parentShell, AboutInfo primaryInfo) {
83
	public AboutPluginsDialog(Shell parentShell, String productName) {
91
		this(
84
		this(
92
			parentShell,
85
			parentShell,
93
			primaryInfo,
86
			productName,
94
			Platform.getPluginRegistry().getPluginDescriptors(),
87
			getAllBundles(),
95
			null,
88
			null,
96
			null,
89
			null,
97
			IHelpContextIds.ABOUT_PLUGINS_DIALOG);
90
			IHelpContextIds.ABOUT_PLUGINS_DIALOG);
98
	}
91
	}
99
92
100
	/**
93
	/**
101
	 * Constructor for AboutPluginsDialog
94
     * Constructor for AboutPluginsDialog
102
	 */
95
     * 
103
	public AboutPluginsDialog(Shell parentShell, AboutInfo primaryInfo, IPluginDescriptor[] descriptors, String title, String msg, String helpContextId) {
96
     * @param productName
97
     *            must not be null
98
     * @param bundles
99
     *            must not be null
100
     */
101
	public AboutPluginsDialog(Shell parentShell, String productName, Bundle[] bundles, String title, String message, String helpContextId) {
104
		super(parentShell);
102
		super(parentShell);
105
		setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.APPLICATION_MODAL);
103
		setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MAX | SWT.APPLICATION_MODAL);
106
		info = descriptors;
107
		this.title = title;
104
		this.title = title;
108
		message = msg;
105
		this.message = message;
109
		this.helpContextId = helpContextId;
106
		this.helpContextId = helpContextId;
110
		sortByProvider();
107
		this.productName = productName;
111
		this.primaryInfo = primaryInfo;
112
	}
113
114
	/* (non-Javadoc)
115
	 * Method declared on Dialog.
116
	 */
117
	protected void buttonPressed(int buttonId) {
118
		switch (buttonId) {
119
			case MORE_ID : {
120
				handleMoreInfoPressed();
121
				return;
122
			}
123
		}
124
		super.buttonPressed(buttonId);
125
	}
126
127
	/* (non-Javadoc)
128
	 * Method declared on Window.
129
	 */
130
	protected void configureShell(Shell newShell) {
131
		super.configureShell(newShell);
132
		if (title == null) {
133
			if (primaryInfo != null) {
134
				title = primaryInfo.getProductName();
135
			}
136
			if (title != null) { 
137
				title = IDEWorkbenchMessages.format(
138
						"AboutPluginsDialog.shellTitle",	//$NON-NLS-1$
139
						new Object[] {title});
140
			}
141
		} 
142
		if (title != null)
143
			newShell.setText(title);
144
145
		WorkbenchHelp.setHelp(
146
			newShell,
147
			helpContextId);
148
	}
149
	/**
150
	 * Add buttons to the dialog's button bar.
151
	 *
152
	 * Subclasses should override.
153
	 *
154
	 * @param parent the button bar composite
155
	 */
156
	protected void createButtonsForButtonBar(Composite parent) {
157
		parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
158
	
159
		moreInfo = createButton(parent, MORE_ID, IDEWorkbenchMessages.getString("AboutPluginsDialog.moreInfo"), false); //$NON-NLS-1$
160
161
		// set initial enablement
162
		moreInfo.setEnabled(tableHasSelection() & selectionHasInfo());
163
164
		Label l = new Label(parent, SWT.NONE);
165
		l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
166
		GridLayout layout = (GridLayout)parent.getLayout();
167
		layout.numColumns++;
168
		layout.makeColumnsEqualWidth = false;
169
	
170
		createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true);
171
	}
172
173
174
	/**
175
	 * Create the contents of the dialog (above the button bar).
176
	 *
177
	 * Subclasses should overide.
178
	 *
179
	 * @param the parent composite to contain the dialog area
180
	 * @return the dialog area control
181
	 */
182
	protected Control createDialogArea(Composite parent) {
183
184
		Composite outer = (Composite) super.createDialogArea(parent);
185
		
186
		if (message != null) {
187
			Label label = new Label(outer, SWT.NONE);
188
			label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
189
			label.setFont(parent.getFont());
190
			label.setText(message);
191
		}
192
193
		createTable(outer);
194
		createColumns();
195
196
		GridData gridData =
197
			new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_FILL);
198
		gridData.grabExcessVerticalSpace = true;
199
		gridData.grabExcessHorizontalSpace = true;
200
201
		// suggest a height for the table
202
		gridData.heightHint = convertVerticalDLUsToPixels(TABLE_HEIGHT);
203
		vendorInfo.setLayoutData(gridData);
204
205
		return outer;
206
	}
207
	/**
208
	 * Create the table part of the dialog.
209
	 *
210
	 * @param the parent composite to contain the dialog area
211
	 */
212
	protected void createTable(Composite parent) {
213
		vendorInfo =
214
			new Table(
215
				parent,
216
				SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE | SWT.FULL_SELECTION | SWT.BORDER);
217
		vendorInfo.setHeaderVisible(true);
218
		vendorInfo.setLinesVisible(true);
219
		vendorInfo.setFont(parent.getFont());
220
		
221
		SelectionListener listener = new SelectionAdapter() {
222
			public void widgetSelected(SelectionEvent e) {
223
				setMoreButtonEnablement(e.item != null);
224
			}
225
		};
226
		vendorInfo.addSelectionListener(listener);
227
	}
228
	/**
229
	 * Populate the table with plugin info obtained from the registry.
230
	 *
231
	 * @param the parent composite to contain the dialog area
232
	 */
233
	protected void createColumns() {
234
		/* create table headers */
235
		int[] columnWidths =
236
			{
237
				convertHorizontalDLUsToPixels(120),
238
				convertHorizontalDLUsToPixels(180),
239
				convertHorizontalDLUsToPixels(70),
240
				convertHorizontalDLUsToPixels(70)};
241
		for (int i = 0; i < columnTitles.length; i++) {
242
			TableColumn tableColumn = new TableColumn(vendorInfo, SWT.NULL);
243
			tableColumn.setWidth(columnWidths[i]);
244
			tableColumn.setText(columnTitles[i]);
245
			final int columnIndex = i;
246
			tableColumn.addSelectionListener(new SelectionAdapter() {		
247
				public void widgetSelected(SelectionEvent e) {
248
					sort(columnIndex);
249
				}
250
			});
251
		
252
		}
253
254
		/* fill each row of the table with plugin registry info */
255
		for (int i = 0; i < info.length; i++) {
256
			String provider = info[i].getProviderName();
257
			String pluginName = info[i].getLabel();
258
			String version = info[i].getVersionIdentifier().toString();
259
			String pluginId = info[i].getUniqueIdentifier();
260
			String[] row = { provider, pluginName, version, pluginId };
261
			TableItem item = new TableItem(vendorInfo, SWT.NULL);
262
			item.setText(row);
263
		}
264
	}
265
	/**
266
	 * Set enablement of moreInfo button based on whether or not 
267
	 * there is a selection in the table and if there is any additional
268
	 * info to show for that plugin.
269
	 *
270
	 * @param isSelected whether there is a selection in the table
271
	 */
272
	protected void setMoreButtonEnablement(boolean isSelected) {
273
		moreInfo.setEnabled(isSelected && selectionHasInfo());
274
	}
275
276
	/**
277
	 * Check if the currently selected plugin has additional
278
	 * information to show.
279
	 * 
280
	 * @return true if the selected plugin has additional info available to display
281
	 */
282
	private boolean selectionHasInfo(){
283
			TableItem[] items = vendorInfo.getSelection();
284
			if (items.length == 0)
285
				return false;
286
			int i = vendorInfo.getSelectionIndex();
287
			IPluginDescriptor desc = info[i];
288
			URL infoURL = desc.find(new Path(PLUGININFO));
289
			if (infoURL == null && IDEWorkbenchPlugin.DEBUG) {
290
				// only report ini problems if the -debug command line argument is used
291
				IDEWorkbenchPlugin.log("Problem reading plugin info for: " + desc.getLabel()); //$NON-NLS-1$
292
			}
293
			return infoURL != null;
294
	}
295
108
296
	/**
109
        ArrayList list = new ArrayList(bundles.length);
297
	 * Create the button to provide more info on the selected plugin.
110
		for(int i = 0; i < bundles.length; ++i )
298
	 *
111
		    list.add(new AboutBundleData(bundles[i]));
299
	 * @return true if there is an item selected in the table, false otherwise
112
		bundleInfos = (AboutBundleData[])list.toArray(new AboutBundleData[0]);
300
	 */
113
114
		AboutData.sortByProvider(reverseSort, bundleInfos);
115
	}
116
117
	// TODO when bug 54574 is fixed, this should be changed to use bundle
118
	//      providers -> bundle groups -> bundles
119
	private static Bundle[] getAllBundles() {
120
	    IPluginDescriptor[] descs = Platform.getPluginRegistry().getPluginDescriptors();
121
	    Bundle[] bundles = new Bundle[descs.length];
122
	    for(int i = 0; i < descs.length; ++i)
123
	        bundles[i] = Platform.getBundle(descs[i].getUniqueIdentifier());
124
125
	    return bundles;
126
	}
127
128
	/*
129
     * (non-Javadoc) Method declared on Dialog.
130
     */
131
    protected void buttonPressed(int buttonId) {
132
        switch (buttonId) {
133
        case MORE_ID:
134
            handleMoreInfoPressed();
135
            break;
136
        default:
137
            super.buttonPressed(buttonId);
138
            break;
139
        }
140
    }
141
142
	/*
143
     * (non-Javadoc) Method declared on Window.
144
     */
145
    protected void configureShell(Shell newShell) {
146
        super.configureShell(newShell);
147
        if (title == null && productName != null)
148
            title = IDEWorkbenchMessages.format(
149
                    "AboutPluginsDialog.shellTitle", //$NON-NLS-1$
150
                    new Object[] { productName });
151
152
        if (title != null)
153
            newShell.setText(title);
154
155
        WorkbenchHelp.setHelp(newShell, helpContextId);
156
    }
157
158
    /**
159
     * Add buttons to the dialog's button bar.
160
     * 
161
     * Subclasses should override.
162
     * 
163
     * @param parent
164
     *            the button bar composite
165
     */
166
    protected void createButtonsForButtonBar(Composite parent) {
167
        parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
168
169
        moreInfo = createButton(parent, MORE_ID, IDEWorkbenchMessages
170
                .getString("AboutPluginsDialog.moreInfo"), false); //$NON-NLS-1$
171
        moreInfo.setEnabled(tableHasSelection() && selectionHasInfo());
172
173
        Label l = new Label(parent, SWT.NONE);
174
        l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
175
        GridLayout layout = (GridLayout) parent.getLayout();
176
        layout.numColumns++;
177
        layout.makeColumnsEqualWidth = false;
178
179
        createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
180
                true);
181
    }
182
183
	/**
184
     * Create the contents of the dialog (above the button bar).
185
     * 
186
     * Subclasses should overide.
187
     * 
188
     * @param parent
189
     *            the parent composite to contain the dialog area
190
     * @return the dialog area control
191
     */
192
    protected Control createDialogArea(Composite parent) {
193
        Composite outer = (Composite) super.createDialogArea(parent);
194
195
        if (message != null) {
196
            Label label = new Label(outer, SWT.NONE);
197
            label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
198
            label.setFont(parent.getFont());
199
            label.setText(message);
200
        }
201
202
        createTable(outer);
203
204
        return outer;
205
    }
206
207
    /**
208
     * Create the table part of the dialog.
209
     * 
210
     * @param parent
211
     *            the parent composite to contain the dialog area
212
     */
213
    protected void createTable(Composite parent) {
214
        vendorInfo = new Table(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE
215
                | SWT.FULL_SELECTION | SWT.BORDER);
216
        vendorInfo.setHeaderVisible(true);
217
        vendorInfo.setLinesVisible(true);
218
        vendorInfo.setFont(parent.getFont());
219
        vendorInfo.addSelectionListener(new SelectionAdapter() {
220
            public void widgetSelected(SelectionEvent e) {
221
                // enable if there is an item selected and that
222
                // item has additional info
223
                moreInfo.setEnabled(e.item != null && selectionHasInfo());
224
            }
225
        });
226
227
        int[] columnWidths = {
228
                convertHorizontalDLUsToPixels(120),
229
                convertHorizontalDLUsToPixels(120),
230
                convertHorizontalDLUsToPixels(70),
231
                convertHorizontalDLUsToPixels(130)
232
        };
233
234
		// create table headers
235
        for (int i = 0; i < columnTitles.length; i++) {
236
            TableColumn column = new TableColumn(vendorInfo, SWT.NULL);
237
            column.setWidth(columnWidths[i]);
238
            column.setText(columnTitles[i]);
239
            final int columnIndex = i;
240
            column.addSelectionListener(new SelectionAdapter() {
241
                public void widgetSelected(SelectionEvent e) {
242
                    sort(columnIndex);
243
                }
244
            });
245
        }
246
247
		// create a row for each member of the bundleInfo array
248
		for (int i = 0; i < bundleInfos.length; ++i) {
249
		    TableItem item = new TableItem(vendorInfo, SWT.NULL);
250
		    item.setText(createRow(bundleInfos[i]));
251
		    item.setData(bundleInfos[i]);
252
		}
253
254
        GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_FILL,
255
                GridData.VERTICAL_ALIGN_FILL, true, true);
256
        gridData.heightHint = convertVerticalDLUsToPixels(TABLE_HEIGHT);
257
        vendorInfo.setLayoutData(gridData);
258
    }
259
260
	/**
261
     * Check if the currently selected plugin has additional information to
262
     * show.
263
     * 
264
     * @return true if the selected plugin has additional info available to
265
     *         display
266
     */
267
    private boolean selectionHasInfo() {
268
        TableItem[] items = vendorInfo.getSelection();
269
        if (items.length <= 0)
270
            return false;
271
272
        AboutBundleData bundleInfo = bundleInfos[vendorInfo.getSelectionIndex()];
273
        URL infoURL = BundleUtility.find(bundleInfo.getId(), PLUGININFO);
274
275
        // only report ini problems if the -debug command line argument is used
276
        if (infoURL == null && IDEWorkbenchPlugin.DEBUG)
277
            IDEWorkbenchPlugin.log("Problem reading plugin info for: " //$NON-NLS-1$
278
                    + bundleInfo.getName());
279
280
        return infoURL != null;
281
    }
282
283
	/**
284
     * Create the button to provide more info on the selected plugin.
285
     * 
286
     * @return true if there is an item selected in the table, false otherwise
287
     */
301
	private boolean tableHasSelection() {
288
	private boolean tableHasSelection() {
302
		if (vendorInfo == null)
289
        return vendorInfo == null ? false : vendorInfo.getSelectionCount() > 0;
303
			return false;
290
    }
304
		return (vendorInfo.getSelectionCount() > 0);
305
306
	}
307
291
308
	/** 
292
	/** 
309
	 * Respond to moreInfo button pressed.
293
	 * The More Info button was pressed.  Open a browser showing the license information
310
	 * 
294
	 * for the selected bundle or an error dialog if the browser cannot be opened.
311
	 */
295
	 */
312
	protected void handleMoreInfoPressed() {
296
	protected void handleMoreInfoPressed() {
313
		TableItem[] items = vendorInfo.getSelection();
297
	    if(vendorInfo == null)
314
		if (items.length == 0)
298
	        return;
315
			return;
316
		int i = vendorInfo.getSelectionIndex();
317
		IPluginDescriptor desc = info[i];
318
		openMoreInfo(desc);
319
	}
320
	/** 
321
	 * Open html file containing additional info about the selected
322
	 * plugin.
323
	 * 
324
	 */
325
	private void openMoreInfo(IPluginDescriptor desc) {
326
		if (desc != null && openBrowser(desc.find(new Path(PLUGININFO))))
327
			return;
328
		MessageDialog.openError(getShell(), IDEWorkbenchMessages
329
				.getString("AboutPluginsDialog.errorTitle"), //$NON-NLS-1$
330
				IDEWorkbenchMessages.format(
331
						"AboutPluginsDialog.unableToOpenFile", new Object[]{ //$NON-NLS-1$
332
								PLUGININFO, desc.getUniqueIdentifier()}));
333
	}
334
	
335
	/**
336
	 * Sort the rows of the table based on the selected column.
337
	 *
338
	 * @param column index of table column selected as sort criteria
339
	 */
340
	private void sort(int column) {
341
		// Choose new sort algorithm
342
		if (lastColumnChosen == column){
343
			reverseSort = !reverseSort;
344
		}
345
		else{
346
			reverseSort = false;
347
			lastColumnChosen = column;
348
		}
349
		
350
		if(vendorInfo.getItemCount() <= 1)	return;
351
352
		// Remember the last selection
353
		int idx = vendorInfo.getSelectionIndex();
354
		if (idx != -1)
355
			lastSelection = info[idx];
356
			
357
		switch (column){
358
			case 0:
359
				sortByProvider();
360
				break;
361
			case 1:
362
				sortByName();
363
				break;
364
			case 2: 
365
				sortByVersion();
366
				break;
367
			case 3:
368
				sortById();
369
				break;
370
		}
371
372
		refreshTable(column);
373
	}
374
299
375
	/**
300
		TableItem[] items = vendorInfo.getSelection();
376
	 * Refresh the rows of the table based on the selected column.
301
		if (items.length <= 0)
377
	 * Maintain selection from before sort action request.
302
		    return;
378
	 *
379
	 * @param items the old state table items 
380
	 */
381
	private void refreshTable(int col){
382
		TableItem[] items = vendorInfo.getItems();
383
		int idx = -1;	// the new index of the selection
384
		// Create new order of table items
385
		for(int i = 0; i < items.length; i++) {
386
			String provider = info[i].getProviderName();
387
			String pluginName = info[i].getLabel();
388
			String version = info[i].getVersionIdentifier().toString();
389
			String pluginId = info[i].getUniqueIdentifier();			
390
			String [] row = { provider, pluginName, version, pluginId };
391
			items[i].setText(row);
392
		}
393
		// Maintain the original selection
394
		if (lastSelection != null){
395
			String oldId = lastSelection.getUniqueIdentifier();
396
			for (int k = 0; k < info.length; k++){
397
				if (oldId.equalsIgnoreCase(info[k].getUniqueIdentifier()))
398
					idx = k;
399
			}	
400
			vendorInfo.setSelection(idx);
401
			vendorInfo.showSelection();
402
		}
403
303
404
		moreInfo.setEnabled(tableHasSelection() && selectionHasInfo());
304
		AboutBundleData bundleInfo = (AboutBundleData)items[0].getData();
405
	}
305
        if (bundleInfo == null)
406
	/**
306
            return;
407
	 * Sort the rows of the table based on the plugin provider.
307
408
	 * Secondary criteria is unique plugin id.
308
        if (!openBrowser(BundleUtility.find(bundleInfo.getId(), PLUGININFO)))
409
	 */
309
            MessageDialog
410
	private void sortByProvider(){
310
                    .openError(getShell(), IDEWorkbenchMessages
411
		/* If sorting in reverse, info array is already sorted forward by
311
                            .getString("AboutPluginsDialog.errorTitle"), //$NON-NLS-1$
412
		 * key so the info array simply needs to be reversed.
312
                            IDEWorkbenchMessages.format(
413
		 */
313
                                    "AboutPluginsDialog.unableToOpenFile", //$NON-NLS-1$
414
		if (reverseSort){
314
                                    new Object[] { PLUGININFO,
415
			java.util.List infoList = Arrays.asList(info);
315
                                            bundleInfo.getId()}));
416
			Collections.reverse(infoList);
316
    }
417
			for (int i=0; i< info.length; i++){
317
418
				info[i] = (IPluginDescriptor)infoList.get(i);
318
	/**
419
			}
319
     * Sort the rows of the table based on the selected column.
420
		}
320
     * 
421
		else {
321
     * @param column
422
			// Sort ascending
322
     *            index of table column selected as sort criteria
423
			Arrays.sort(info, new Comparator() {
323
     */
424
				Collator coll = Collator.getInstance(Locale.getDefault());
324
    private void sort(int column) {
425
				public int compare(Object a, Object b) {
325
        if (lastColumnChosen == column)
426
					IPluginDescriptor d1, d2;
326
            reverseSort = !reverseSort;
427
					String provider1, provider2, name1, name2;
327
        else {
428
					d1 = (IPluginDescriptor) a;
328
            reverseSort = false;
429
					provider1 = d1.getProviderName();
329
            lastColumnChosen = column;
430
					name1 = d1.getLabel();
330
        }
431
					d2 = (IPluginDescriptor) b;
331
432
					provider2 = d2.getProviderName();
332
        if (vendorInfo.getItemCount() <= 1)
433
					name2 = d2.getLabel();
333
            return;
434
					if (provider1.equals(provider2))
334
435
						return coll.compare(name1, name2);
335
        int sel = vendorInfo.getSelectionIndex();
436
					else
336
        if (sel != -1)
437
						return coll.compare(provider1, provider2);
337
            lastSelection = bundleInfos[sel];
438
				}
338
439
			});
339
        switch (column) {
440
		}
340
        case 0:
441
	}
341
            AboutData.sortByProvider(reverseSort, bundleInfos);
442
	/**
342
            break;
443
	 * Sort the rows of the table based on unique plugin id.
343
        case 1:
444
	 */	
344
            AboutData.sortByName(reverseSort, bundleInfos);
445
	private void sortByName(){
345
            break;
446
		/* If sorting in reverse, info array is already sorted forward by
346
        case 2:
447
		 * key so the info array simply needs to be reversed.
347
            AboutData.sortByVersion(reverseSort, bundleInfos);
448
		 */
348
            break;
449
		if (reverseSort){
349
        case 3:
450
			java.util.List infoList = Arrays.asList(info);
350
            AboutData.sortById(reverseSort, bundleInfos);
451
			Collections.reverse(infoList);
351
            break;
452
			for (int i=0; i< info.length; i++){
352
        }
453
				info[i] = (IPluginDescriptor)infoList.get(i);
353
454
			}
354
        refreshTable(column);
455
		}
355
    }
456
		else {
356
457
			// Sort ascending
357
	/**
458
			Arrays.sort(info, new Comparator() {
358
     * Refresh the rows of the table based on the selected column. Maintain
459
				Collator coll = Collator.getInstance(Locale.getDefault());
359
     * selection from before sort action request.
460
				public int compare(Object a, Object b) {
360
     */
461
					IPluginDescriptor d1, d2;
361
    private void refreshTable(int col) {
462
					String name1, name2;
362
        TableItem[] items = vendorInfo.getItems();
463
					d1 = (IPluginDescriptor) a;
363
464
					name1 = d1.getLabel();
364
        // create new order of table items
465
					d2 = (IPluginDescriptor) b;
365
        for (int i = 0; i < items.length; i++) {
466
					name2 = d2.getLabel();
366
            items[i].setText(createRow(bundleInfos[i]));
467
					return coll.compare(name1, name2);
367
            items[i].setData(bundleInfos[i]);
468
				}
368
        }
469
			});
369
470
		}
370
        // maintain the original selection
471
	
371
        int sel = -1;
472
	}
372
        if (lastSelection != null) {
473
	/**
373
            String oldId = lastSelection.getId();
474
	 * Sort the rows of the table based on the plugin version.
374
            for (int k = 0; k < bundleInfos.length; k++)
475
	 * Secondary criteria is unique plugin id.
375
                if (oldId.equalsIgnoreCase(bundleInfos[k].getId()))
476
	 */
376
                    sel = k;
477
	private void sortByVersion(){
377
478
		/* If sorting in reverse, info array is already sorted forward by
378
            vendorInfo.setSelection(sel);
479
		 * key so the info array simply needs to be reversed.
379
            vendorInfo.showSelection();
480
		 */		
380
        }
481
		if (reverseSort){
381
482
			java.util.List infoList = Arrays.asList(info);
382
        moreInfo.setEnabled(tableHasSelection() && selectionHasInfo());
483
			Collections.reverse(infoList);
383
    }
484
			for (int i=0; i< info.length; i++){
384
485
				info[i] = (IPluginDescriptor)infoList.get(i);
385
    /**
486
			}
386
     * Return an array of strings containing the argument's information in the
487
		}
387
     * proper order for this table's columns.
488
		else {
388
     * 
489
			// Sort ascending
389
     * @param info
490
			Arrays.sort(info, new Comparator() {
390
     *            the source information for the new row, must not be null
491
				Collator coll = Collator.getInstance(Locale.getDefault());
391
     */
492
				public int compare(Object a, Object b) {
392
    private static String[] createRow(AboutBundleData info) {
493
					IPluginDescriptor d1, d2;
393
        return new String[] { info.getProviderName(), info.getName(),
494
					String version1, version2, name1, name2;
394
                info.getVersion(), info.getId()};
495
					d1 = (IPluginDescriptor) a;
395
    }
496
					version1 = d1.getVersionIdentifier().toString();
396
}
497
					name1 = d1.getLabel();
498
					d2 = (IPluginDescriptor) b;
499
					version2 = d2.getVersionIdentifier().toString();
500
					name2 = d2.getLabel();
501
					if (version1.equals(version2))
502
						return coll.compare(name1, name2);
503
					else
504
						return coll.compare(version1, version2);
505
				}
506
			});
507
		}
508
	}
509
	/**
510
	 * Sort the rows of the table based on the plugin id.
511
	 * Secondary criteria is unique plugin id.
512
	 */
513
	private void sortById(){
514
		/* If sorting in reverse, info array is already sorted forward by
515
		 * key so the info array simply needs to be reversed.
516
		 */
517
		if (reverseSort){
518
			java.util.List infoList = Arrays.asList(info);
519
			Collections.reverse(infoList);
520
			for (int i=0; i< info.length; i++){
521
				info[i] = (IPluginDescriptor)infoList.get(i);
522
			}
523
		}
524
		else {
525
			// Sort ascending
526
			Arrays.sort(info, new Comparator() {
527
				Collator coll = Collator.getInstance(Locale.getDefault());
528
				public int compare(Object a, Object b) {
529
					IPluginDescriptor d1, d2;
530
					String pluginId1, pluginId2, name1, name2;
531
					d1 = (IPluginDescriptor) a;
532
					pluginId1 = d1.getUniqueIdentifier();
533
					name1 = d1.getLabel();
534
					d2 = (IPluginDescriptor) b;
535
					pluginId2 = d2.getUniqueIdentifier();
536
					name2 = d2.getLabel();
537
					if (pluginId1.equals(pluginId2))
538
						return coll.compare(name1, name2);
539
					else
540
						return coll.compare(pluginId1, pluginId2);
541
				}
542
			});
543
		}
544
	}
545
}
(-)src/org/eclipse/ui/internal/ide/AboutBundleData.java (+43 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2004 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials 
4
 * are made available under the terms of the Common Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/cpl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.ui.internal.ide;
12
13
import org.eclipse.core.runtime.Platform;
14
import org.osgi.framework.Bundle;
15
import org.osgi.framework.Constants;
16
17
18
/**
19
 * A small class to manage the about dialog information for a single bundle.
20
 * @since 3.0
21
 */
22
public class AboutBundleData extends AboutData {
23
24
    public AboutBundleData(Bundle bundle) {
25
        super(getResourceString(bundle, Constants.BUNDLE_VENDOR),
26
              getResourceString(bundle, Constants.BUNDLE_NAME),
27
              getResourceString(bundle, Constants.BUNDLE_VERSION),
28
              bundle.getSymbolicName());
29
    }
30
31
    /**
32
     * A function to translate the resource tags that may be embedded in a
33
     * string associated with some bundle.
34
     * 
35
     * @param headerName
36
     *            the used to retrieve the correct string
37
     * @return the string or null if the string cannot be found
38
     */
39
    private static String getResourceString(Bundle bundle, String headerName) {
40
        String value = (String) bundle.getHeaders().get(headerName);
41
        return value == null ? null : Platform.getResourceString(bundle, value);
42
    }
43
}
(-)src/org/eclipse/ui/internal/ide/AboutBundleGroupData.java (+102 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2004 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials 
4
 * are made available under the terms of the Common Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/cpl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.ui.internal.ide;
12
13
import java.io.IOException;
14
import java.io.InputStream;
15
import java.net.URL;
16
import java.util.zip.CRC32;
17
import java.util.zip.CheckedInputStream;
18
19
import org.eclipse.core.runtime.IBundleGroup;
20
import org.eclipse.jface.resource.ImageDescriptor;
21
import org.eclipse.ui.branding.IBundleGroupConstants;
22
import org.eclipse.ui.branding.IProductConstants;
23
24
/**
25
 * A small class to manage the information related to IBundleGroup's.
26
 * @since 3.0
27
 */
28
public class AboutBundleGroupData extends AboutData {
29
    private IBundleGroup bundleGroup;
30
31
    private URL featureImageUrl;
32
    private Long featureImageCrc;
33
    private ImageDescriptor featureImage;
34
35
	public AboutBundleGroupData(IBundleGroup bundleGroup) {
36
	    super(bundleGroup.getProviderName(),
37
	          bundleGroup.getName(),
38
	          bundleGroup.getVersion(),
39
	          bundleGroup.getIdentifier());
40
	    this.bundleGroup = bundleGroup;
41
	}
42
43
	public IBundleGroup getBundleGroup() {
44
	    return bundleGroup;
45
	}
46
47
	public URL getFeatureImageUrl() {
48
        if (featureImageUrl == null)
49
            featureImageUrl = getURL(bundleGroup
50
                    .getProperty(IBundleGroupConstants.FEATURE_IMAGE));
51
        return featureImageUrl;
52
    }
53
54
	public ImageDescriptor getFeatureImage() {
55
	    if(featureImage == null)
56
	        featureImage = getImage(getFeatureImageUrl());
57
	    return featureImage;
58
	}
59
60
	public Long getFeatureImageCrc() {
61
	    if(featureImageCrc != null)
62
	        return featureImageCrc;
63
64
	    URL url = getFeatureImageUrl();
65
	    if(url == null)
66
			return null;
67
68
		// Get the image bytes
69
		InputStream in = null;
70
		try {
71
		    CRC32 checksum = new CRC32();
72
		    in = new CheckedInputStream(url.openStream(), checksum);
73
74
		    // the contents don't matter, the read just needs a place to go
75
		    byte[] sink = new byte[1024];
76
		    while(true)
77
		        if(in.read(sink) <= 0)
78
		            break;
79
80
			featureImageCrc = new Long(checksum.getValue());
81
			return featureImageCrc;
82
83
		} catch (IOException e) {
84
			return null;
85
		} finally {
86
			if (in != null)
87
				try {
88
					in.close();
89
				} catch (IOException e) {
90
					// do nothing
91
				}
92
		}
93
	}
94
95
	public String getAboutText() {
96
	    return bundleGroup.getProperty(IProductConstants.ABOUT_TEXT);
97
	}
98
	
99
	public ImageDescriptor getAboutImage() {
100
        return getImage(bundleGroup.getProperty(IProductConstants.ABOUT_IMAGE));
101
	}
102
}
(-)src/org/eclipse/ui/internal/ide/AboutData.java (+220 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2004 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials 
4
 * are made available under the terms of the Common Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/cpl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.ui.internal.ide;
12
13
import java.io.IOException;
14
import java.net.URL;
15
import java.text.Collator;
16
import java.util.Arrays;
17
import java.util.Collections;
18
import java.util.Comparator;
19
import java.util.List;
20
import java.util.Locale;
21
22
import org.eclipse.jface.resource.ImageDescriptor;
23
24
25
/**
26
 * An abstract parent that describes data that can be displayed in a table in one of
27
 * the about dialogs.
28
 * @since 3.0 
29
 */
30
public abstract class AboutData {
31
    private String providerName;
32
    private String name;
33
    private String version;
34
    private String id;
35
36
    protected AboutData(String providerName, String name, String version, String id) {
37
        this.providerName = providerName == null ? "" : providerName; //$NON-NLS-1$
38
        this.name = name == null ? "" : name; //$NON-NLS-1$
39
        this.version = version == null ? "" : version; //$NON-NLS-1$
40
        this.id = id == null ? "" : id; //$NON-NLS-1$
41
    }
42
43
    public String getId() {
44
        return id;
45
    }
46
47
    public String getName() {
48
        return name;
49
    }
50
51
    public String getProviderName() {
52
        return providerName;
53
    }
54
55
    public String getVersion() {
56
        return version;
57
    }
58
59
    /**
60
     * Modify the argument array to reverse the sort order. 
61
     * @param infos
62
     */
63
    private static void reverse(AboutData[] infos) {
64
        List infoList = Arrays.asList(infos);
65
        Collections.reverse(infoList);
66
        for (int i = 0; i < infos.length; ++i)
67
            infos[i] = (AboutData) infoList.get(i);
68
    }
69
    
70
    /**
71
     * Modify the argument array to be sorted by provider. If the reverse
72
     * boolean is true, the array is assumed to already be sorted and the
73
     * direction of sort (ascending vs. descending) is reversed.  Entries
74
     * with the same name are sorted by name.
75
     * 
76
     * @param reverse
77
     *            if true then the order of the argument is reversed without
78
     *            examining the value of the fields
79
     * @param infos
80
     *            the data to be sorted
81
     */
82
    public static void sortByProvider(boolean reverse, AboutData[] infos) {
83
        if (reverse) {
84
            reverse(infos);
85
            return;
86
        }
87
88
        Arrays.sort(infos, new Comparator() {
89
            Collator collator = Collator.getInstance(Locale.getDefault());
90
            public int compare(Object a, Object b) {
91
                AboutData info1 = (AboutData) a;
92
                AboutData info2 = (AboutData) b;
93
94
                String provider1 = info1.getProviderName();
95
                String provider2 = info2.getProviderName();
96
97
                if (!provider1.equals(provider2))
98
                    return collator.compare(provider1, provider2);
99
100
                return collator.compare(info1.getName(), info2.getName());
101
            }
102
        });
103
    }
104
105
    /**
106
     * Modify the argument array to be sorted by name. If the reverse
107
     * boolean is true, the array is assumed to already be sorted and the
108
     * direction of sort (ascending vs. descending) is reversed.
109
     * 
110
     * @param reverse
111
     *            if true then the order of the argument is reversed without
112
     *            examining the value of the fields
113
     * @param infos
114
     *            the data to be sorted
115
     */
116
    public static void sortByName(boolean reverse, AboutData[] infos) {
117
        if (reverse) {
118
            reverse(infos);
119
            return;
120
        }
121
122
        Arrays.sort(infos, new Comparator() {
123
            Collator collator = Collator.getInstance(Locale.getDefault());
124
            public int compare(Object a, Object b) {
125
                AboutData info1 = (AboutData) a;
126
                AboutData info2 = (AboutData) b;
127
                return collator.compare(info1.getName(), info2.getName());
128
            }
129
        });
130
    }
131
132
    /**
133
     * Modify the argument array to be sorted by version. If the reverse
134
     * boolean is true, the array is assumed to already be sorted and the
135
     * direction of sort (ascending vs. descending) is reversed.  Entries
136
     * with the same name are sorted by name.
137
     * 
138
     * @param reverse
139
     *            if true then the order of the argument is reversed without
140
     *            examining the value of the fields
141
     * @param infos
142
     *            the data to be sorted
143
     */
144
    public static void sortByVersion(boolean reverse, AboutData[] infos) {
145
        if (reverse) {
146
            reverse(infos);
147
            return;
148
        }
149
150
        Arrays.sort(infos, new Comparator() {
151
            Collator collator = Collator.getInstance(Locale.getDefault());
152
            public int compare(Object a, Object b) {
153
                AboutData info1 = (AboutData) a;
154
                AboutData info2 = (AboutData) b;
155
156
                String version1 = info1.getVersion();
157
                String version2 = info2.getVersion();
158
159
                if (!version1.equals(version2))
160
                    return collator.compare(version1, version2);
161
162
                return collator.compare(info1.getName(), info2.getName());
163
            }
164
        });
165
    }
166
167
    /**
168
     * Modify the argument array to be sorted by id. If the reverse
169
     * boolean is true, the array is assumed to already be sorted and the
170
     * direction of sort (ascending vs. descending) is reversed.  Entries
171
     * with the same name are sorted by name.
172
     * 
173
     * @param reverse
174
     *            if true then the order of the argument is reversed without
175
     *            examining the value of the fields
176
     * @param infos
177
     *            the data to be sorted
178
     */
179
    public static void sortById(boolean reverse, AboutData[] infos) {
180
        if (reverse) {
181
            reverse(infos);
182
            return;
183
        }
184
185
        Arrays.sort(infos, new Comparator() {
186
            Collator collator = Collator.getInstance(Locale.getDefault());
187
            public int compare(Object a, Object b) {
188
                AboutData info1 = (AboutData) a;
189
                AboutData info2 = (AboutData) b;
190
191
                String id1 = info1.getId();
192
                String id2 = info2.getId();
193
194
                if (!id1.equals(id2))
195
                    return collator.compare(id1, id2);
196
197
                return collator.compare(info1.getName(), info2.getName());
198
            }
199
        });
200
    }
201
202
    protected static URL getURL(String value) {
203
        try {
204
            if (value != null)
205
                return new URL(value);
206
        } catch (IOException e) {
207
            // do nothing
208
        }
209
210
        return null;
211
    }
212
213
	protected static ImageDescriptor getImage(URL url) {
214
		return url == null ? null : ImageDescriptor.createFromURL(url);
215
	}
216
217
	protected static ImageDescriptor getImage(String value) {
218
	    return getImage(getURL(value));
219
	}
220
}
(-)src/org/eclipse/ui/internal/ide/dialogs/AboutFeaturesButtonManager.java (+99 lines)
Added Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2004 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials 
4
 * are made available under the terms of the Common Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/cpl-v10.html
7
 * 
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.ui.internal.ide.dialogs;
12
13
import java.util.ArrayList;
14
import java.util.HashMap;
15
import java.util.List;
16
import java.util.Map;
17
18
import org.eclipse.ui.internal.ide.AboutBundleGroupData;
19
20
/**
21
 * Utility class used to associate BundleInfo's that have the same provider and
22
 * image.  The algorithm in <code>java.util.zip.CRC32</code> is used to determine
23
 * image identity.
24
 */
25
public class AboutFeaturesButtonManager {
26
    private Map providerMap = new HashMap();
27
28
    private static class Key {
29
        public String providerName;
30
        public Long crc;
31
32
        /**
33
         * @param crc must not be null
34
         */
35
        public Key(String providerName, Long crc) {
36
            this.providerName = providerName;
37
            this.crc = crc;
38
        }
39
40
        public boolean equals(Object o) {
41
            if (!(o instanceof Key))
42
                return false;
43
            Key other = (Key) o;
44
            if (!providerName.equals(other.providerName))
45
                return false;
46
            return crc.equals(other.crc);
47
        }
48
49
        public int hashCode() {
50
            return providerName.hashCode();
51
        }
52
    }
53
54
    /**
55
     * @return true if a button should be added (i.e., the argument has an image
56
     *         and it does not already have a button)
57
     */
58
    public boolean add(AboutBundleGroupData info) {
59
        // no button for features without an image
60
        Long crc = info.getFeatureImageCrc();
61
        if (crc == null)
62
            return false;
63
64
        String providerName = info.getProviderName();
65
        Key key = new Key(providerName, crc);
66
67
        List infoList = (List) providerMap.get(key);
68
        if (infoList != null) {
69
            infoList.add(info);
70
            return false;
71
        }
72
73
        infoList = new ArrayList();
74
        infoList.add(info);
75
        providerMap.put(key, infoList);
76
        return true;
77
    }
78
79
    /**
80
     * Return an array of all bundle groups that share the argument's provider and
81
     * image.  Returns an empty array if there isn't any related information.
82
     */
83
    public AboutBundleGroupData[] getRelatedInfos(AboutBundleGroupData info) {
84
        // if there's no image, then there won't be a button
85
        Long crc = info.getFeatureImageCrc();
86
        if (crc == null) return
87
        	new AboutBundleGroupData[0];
88
89
        String providerName = info.getProviderName();
90
        Key key = new Key(providerName, crc);
91
92
        List infoList = (List) providerMap.get(key);
93
        if (infoList == null) return
94
        	new AboutBundleGroupData[0];
95
96
        return (AboutBundleGroupData[]) infoList
97
                .toArray(new AboutBundleGroupData[0]);
98
    }
99
}

Return to bug 54548