001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.dialogs;
011:
012: import java.util.ArrayList;
013: import java.util.LinkedList;
014:
015: import org.eclipse.core.runtime.IBundleGroup;
016: import org.eclipse.core.runtime.IBundleGroupProvider;
017: import org.eclipse.core.runtime.IProduct;
018: import org.eclipse.core.runtime.Platform;
019: import org.eclipse.jface.dialogs.IDialogConstants;
020: import org.eclipse.jface.resource.ImageDescriptor;
021: import org.eclipse.jface.resource.JFaceColors;
022: import org.eclipse.osgi.util.NLS;
023: import org.eclipse.swt.SWT;
024: import org.eclipse.swt.accessibility.AccessibleAdapter;
025: import org.eclipse.swt.accessibility.AccessibleEvent;
026: import org.eclipse.swt.custom.BusyIndicator;
027: import org.eclipse.swt.custom.StyledText;
028: import org.eclipse.swt.events.DisposeEvent;
029: import org.eclipse.swt.events.DisposeListener;
030: import org.eclipse.swt.events.SelectionAdapter;
031: import org.eclipse.swt.events.SelectionEvent;
032: import org.eclipse.swt.graphics.Color;
033: import org.eclipse.swt.graphics.Cursor;
034: import org.eclipse.swt.graphics.Image;
035: import org.eclipse.swt.layout.GridData;
036: import org.eclipse.swt.layout.GridLayout;
037: import org.eclipse.swt.layout.RowLayout;
038: import org.eclipse.swt.widgets.Button;
039: import org.eclipse.swt.widgets.Composite;
040: import org.eclipse.swt.widgets.Control;
041: import org.eclipse.swt.widgets.Label;
042: import org.eclipse.swt.widgets.Shell;
043: import org.eclipse.ui.PlatformUI;
044: import org.eclipse.ui.internal.IWorkbenchHelpContextIds;
045: import org.eclipse.ui.internal.ProductProperties;
046: import org.eclipse.ui.internal.WorkbenchMessages;
047: import org.eclipse.ui.internal.about.AboutBundleGroupData;
048: import org.eclipse.ui.internal.about.AboutFeaturesButtonManager;
049:
050: /**
051: * Displays information about the product.
052: */
053: public class AboutDialog extends ProductInfoDialog {
054: private final static int MAX_IMAGE_WIDTH_FOR_TEXT = 250;
055:
056: private final static int FEATURES_ID = IDialogConstants.CLIENT_ID + 1;
057:
058: private final static int PLUGINS_ID = IDialogConstants.CLIENT_ID + 2;
059:
060: private final static int INFO_ID = IDialogConstants.CLIENT_ID + 3;
061:
062: private String productName;
063:
064: private IProduct product;
065:
066: private AboutBundleGroupData[] bundleGroupInfos;
067:
068: private ArrayList images = new ArrayList();
069:
070: private AboutFeaturesButtonManager buttonManager = new AboutFeaturesButtonManager();
071:
072: // TODO should the styled text be disposed? if not then it likely
073: // doesn't need to be a member
074: private StyledText text;
075:
076: /**
077: * Create an instance of the AboutDialog for the given window.
078: * @param parentShell The parent of the dialog.
079: */
080: public AboutDialog(Shell parentShell) {
081: super (parentShell);
082:
083: product = Platform.getProduct();
084: if (product != null) {
085: productName = product.getName();
086: }
087: if (productName == null) {
088: productName = WorkbenchMessages.AboutDialog_defaultProductName;
089: }
090:
091: // create a descriptive object for each BundleGroup
092: IBundleGroupProvider[] providers = Platform
093: .getBundleGroupProviders();
094: LinkedList groups = new LinkedList();
095: if (providers != null) {
096: for (int i = 0; i < providers.length; ++i) {
097: IBundleGroup[] bundleGroups = providers[i]
098: .getBundleGroups();
099: for (int j = 0; j < bundleGroups.length; ++j) {
100: groups
101: .add(new AboutBundleGroupData(
102: bundleGroups[j]));
103: }
104: }
105: }
106: bundleGroupInfos = (AboutBundleGroupData[]) groups
107: .toArray(new AboutBundleGroupData[0]);
108: }
109:
110: /*
111: * (non-Javadoc) Method declared on Dialog.
112: */
113: protected void buttonPressed(int buttonId) {
114: switch (buttonId) {
115: case FEATURES_ID:
116: new AboutFeaturesDialog(getShell(), productName,
117: bundleGroupInfos).open();
118: break;
119: case PLUGINS_ID:
120: new AboutPluginsDialog(getShell(), productName).open();
121: break;
122: case INFO_ID:
123: BusyIndicator.showWhile(null, new Runnable() {
124: public void run() {
125: new AboutSystemDialog(getShell()).open();
126: }
127: });
128: break;
129: default:
130: super .buttonPressed(buttonId);
131: break;
132: }
133: }
134:
135: public boolean close() {
136: // dispose all images
137: for (int i = 0; i < images.size(); ++i) {
138: Image image = (Image) images.get(i);
139: image.dispose();
140: }
141:
142: return super .close();
143: }
144:
145: /*
146: * (non-Javadoc) Method declared on Window.
147: */
148: protected void configureShell(Shell newShell) {
149: super .configureShell(newShell);
150: newShell.setText(NLS.bind(
151: WorkbenchMessages.AboutDialog_shellTitle, productName));
152: PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell,
153: IWorkbenchHelpContextIds.ABOUT_DIALOG);
154: }
155:
156: /**
157: * Add buttons to the dialog's button bar.
158: *
159: * Subclasses should override.
160: *
161: * @param parent
162: * the button bar composite
163: */
164: protected void createButtonsForButtonBar(Composite parent) {
165: parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
166:
167: // bug 64232: the feature details button should only be created if there
168: // are features to show
169: if (bundleGroupInfos != null && bundleGroupInfos.length > 0) {
170: createButton(parent, FEATURES_ID,
171: WorkbenchMessages.AboutDialog_featureInfo, false);
172: }
173:
174: createButton(parent, PLUGINS_ID,
175: WorkbenchMessages.AboutDialog_pluginInfo, false);
176: createButton(parent, INFO_ID,
177: WorkbenchMessages.AboutDialog_systemInfo, false);
178:
179: Label l = new Label(parent, SWT.NONE);
180: l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
181: GridLayout layout = (GridLayout) parent.getLayout();
182: layout.numColumns++;
183: layout.makeColumnsEqualWidth = false;
184:
185: Button b = createButton(parent, IDialogConstants.OK_ID,
186: IDialogConstants.OK_LABEL, true);
187: b.setFocus();
188: }
189:
190: /**
191: * Creates and returns the contents of the upper part
192: * of the dialog (above the button bar).
193: *
194: * Subclasses should overide.
195: *
196: * @param parent the parent composite to contain the dialog area
197: * @return the dialog area control
198: */
199: protected Control createDialogArea(Composite parent) {
200: final Cursor hand = new Cursor(parent.getDisplay(),
201: SWT.CURSOR_HAND);
202: final Cursor busy = new Cursor(parent.getDisplay(),
203: SWT.CURSOR_WAIT);
204: setHandCursor(hand);
205: setBusyCursor(busy);
206: getShell().addDisposeListener(new DisposeListener() {
207: public void widgetDisposed(DisposeEvent e) {
208: setHandCursor(null);
209: hand.dispose();
210: setBusyCursor(null);
211: busy.dispose();
212: }
213: });
214:
215: // brand the about box if there is product info
216: Image aboutImage = null;
217: if (product != null) {
218: ImageDescriptor imageDescriptor = ProductProperties
219: .getAboutImage(product);
220: if (imageDescriptor != null) {
221: aboutImage = imageDescriptor.createImage();
222: }
223:
224: // if the about image is small enough, then show the text
225: if (aboutImage == null
226: || aboutImage.getBounds().width <= MAX_IMAGE_WIDTH_FOR_TEXT) {
227: String aboutText = ProductProperties
228: .getAboutText(product);
229: if (aboutText != null) {
230: setItem(scan(aboutText));
231: }
232: }
233:
234: if (aboutImage != null) {
235: images.add(aboutImage);
236: }
237: }
238:
239: // create a composite which is the parent of the top area and the bottom
240: // button bar, this allows there to be a second child of this composite with
241: // a banner background on top but not have on the bottom
242: Composite workArea = new Composite(parent, SWT.NONE);
243: GridLayout workLayout = new GridLayout();
244: workLayout.marginHeight = 0;
245: workLayout.marginWidth = 0;
246: workLayout.verticalSpacing = 0;
247: workLayout.horizontalSpacing = 0;
248: workArea.setLayout(workLayout);
249: workArea.setLayoutData(new GridData(GridData.FILL_BOTH));
250:
251: // page group
252: Color background = JFaceColors.getBannerBackground(parent
253: .getDisplay());
254: Color foreground = JFaceColors.getBannerForeground(parent
255: .getDisplay());
256: Composite top = (Composite) super .createDialogArea(workArea);
257:
258: // override any layout inherited from createDialogArea
259: GridLayout layout = new GridLayout();
260: layout.marginHeight = 0;
261: layout.marginWidth = 0;
262: layout.verticalSpacing = 0;
263: layout.horizontalSpacing = 0;
264: top.setLayout(layout);
265: top.setLayoutData(new GridData(GridData.FILL_BOTH));
266: top.setBackground(background);
267: top.setForeground(foreground);
268:
269: // the image & text
270: Composite topContainer = new Composite(top, SWT.NONE);
271: topContainer.setBackground(background);
272: topContainer.setForeground(foreground);
273:
274: layout = new GridLayout();
275: layout.numColumns = (aboutImage == null || getItem() == null ? 1
276: : 2);
277: layout.marginWidth = 0;
278: layout.marginHeight = 0;
279: layout.verticalSpacing = 0;
280: layout.horizontalSpacing = 0;
281: topContainer.setLayout(layout);
282: GridData data = new GridData();
283: data.horizontalAlignment = GridData.FILL;
284: data.grabExcessHorizontalSpace = true;
285: topContainer.setLayoutData(data);
286:
287: //image on left side of dialog
288: if (aboutImage != null) {
289: Label imageLabel = new Label(topContainer, SWT.NONE);
290: imageLabel.setBackground(background);
291: imageLabel.setForeground(foreground);
292:
293: data = new GridData();
294: data.horizontalAlignment = GridData.FILL;
295: data.verticalAlignment = GridData.BEGINNING;
296: data.grabExcessHorizontalSpace = false;
297: imageLabel.setLayoutData(data);
298: imageLabel.setImage(aboutImage);
299: }
300:
301: if (getItem() != null) {
302: // there is no margins around the image, so insert an extra composite
303: // here to provide some margins for the text.
304: Composite textContainer = new Composite(topContainer,
305: SWT.NONE);
306: textContainer.setBackground(background);
307: textContainer.setForeground(foreground);
308:
309: layout = new GridLayout();
310: layout.numColumns = 1;
311: textContainer.setLayout(layout);
312: data = new GridData();
313: data.horizontalAlignment = GridData.FILL;
314: data.verticalAlignment = GridData.BEGINNING;
315: data.grabExcessHorizontalSpace = true;
316: textContainer.setLayoutData(data);
317:
318: // text on the right
319: text = new StyledText(textContainer, SWT.MULTI
320: | SWT.READ_ONLY);
321: text.setCaret(null);
322: text.setFont(parent.getFont());
323: data = new GridData();
324: data.horizontalAlignment = GridData.FILL;
325: data.verticalAlignment = GridData.BEGINNING;
326: data.grabExcessHorizontalSpace = true;
327: text.setText(getItem().getText());
328: text.setLayoutData(data);
329: text.setCursor(null);
330: text.setBackground(background);
331: text.setForeground(foreground);
332:
333: setLinkRanges(text, getItem().getLinkRanges());
334: addListeners(text);
335: }
336:
337: // horizontal bar
338: Label bar = new Label(workArea, SWT.HORIZONTAL | SWT.SEPARATOR);
339: data = new GridData();
340: data.horizontalAlignment = GridData.FILL;
341: bar.setLayoutData(data);
342:
343: // add image buttons for bundle groups that have them
344: Composite bottom = (Composite) super .createDialogArea(workArea);
345: // override any layout inherited from createDialogArea
346: layout = new GridLayout();
347: bottom.setLayout(layout);
348: bottom.setLayoutData(new GridData(GridData.FILL_BOTH));
349:
350: createFeatureImageButtonRow(bottom);
351:
352: // spacer
353: bar = new Label(bottom, SWT.NONE);
354: data = new GridData();
355: data.horizontalAlignment = GridData.FILL;
356: bar.setLayoutData(data);
357:
358: return workArea;
359: }
360:
361: private void createFeatureImageButtonRow(Composite parent) {
362: Composite featureContainer = new Composite(parent, SWT.NONE);
363: RowLayout rowLayout = new RowLayout();
364: rowLayout.wrap = true;
365: featureContainer.setLayout(rowLayout);
366: GridData data = new GridData();
367: data.horizontalAlignment = GridData.FILL;
368: featureContainer.setLayoutData(data);
369:
370: for (int i = 0; i < bundleGroupInfos.length; i++) {
371: createFeatureButton(featureContainer, bundleGroupInfos[i]);
372: }
373: }
374:
375: private Button createFeatureButton(Composite parent,
376: final AboutBundleGroupData info) {
377: if (!buttonManager.add(info)) {
378: return null;
379: }
380:
381: ImageDescriptor desc = info.getFeatureImage();
382: Image featureImage = null;
383:
384: Button button = new Button(parent, SWT.FLAT | SWT.PUSH);
385: button.setData(info);
386: featureImage = desc.createImage();
387: images.add(featureImage);
388: button.setImage(featureImage);
389: button.setToolTipText(info.getProviderName());
390:
391: button.getAccessible().addAccessibleListener(
392: new AccessibleAdapter() {
393: /* (non-Javadoc)
394: * @see org.eclipse.swt.accessibility.AccessibleAdapter#getName(org.eclipse.swt.accessibility.AccessibleEvent)
395: */
396: public void getName(AccessibleEvent e) {
397: e.result = info.getProviderName();
398: }
399: });
400: button.addSelectionListener(new SelectionAdapter() {
401: public void widgetSelected(SelectionEvent event) {
402: AboutBundleGroupData[] groupInfos = buttonManager
403: .getRelatedInfos(info);
404: AboutBundleGroupData selection = (AboutBundleGroupData) event.widget
405: .getData();
406:
407: AboutFeaturesDialog d = new AboutFeaturesDialog(
408: getShell(), productName, groupInfos);
409: d.setInitialSelection(selection);
410: d.open();
411: }
412: });
413:
414: return button;
415: }
416: }
|