| /******************************************************************************* |
| * Copyright (c) 2000, 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Sebastian Davids <sdavids@gmx.de> - Fix for bug 19346 - Dialog |
| * font should be activated and used by other components. |
| *******************************************************************************/ |
| package org.eclipse.ui.internal.dialogs; |
| |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import org.eclipse.core.runtime.IBundleGroup; |
| import org.eclipse.jface.dialogs.IDialogConstants; |
| import org.eclipse.jface.dialogs.MessageDialog; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.window.Window; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.StyledText; |
| import org.eclipse.swt.events.DisposeEvent; |
| import org.eclipse.swt.events.DisposeListener; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Cursor; |
| import org.eclipse.swt.graphics.Font; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.Table; |
| import org.eclipse.swt.widgets.TableColumn; |
| import org.eclipse.swt.widgets.TableItem; |
| import org.eclipse.ui.PlatformUI; |
| import org.eclipse.ui.internal.IWorkbenchHelpContextIds; |
| import org.eclipse.ui.internal.WorkbenchMessages; |
| import org.eclipse.ui.internal.about.AboutBundleGroupData; |
| import org.eclipse.ui.internal.about.AboutData; |
| import org.osgi.framework.Bundle; |
| |
| /** |
| * Displays information about the product plugins. |
| * |
| * PRIVATE |
| * This class is internal to the workbench and must not be called outside |
| * the workbench. |
| */ |
| public class AboutFeaturesDialog extends ProductInfoDialog { |
| |
| /** |
| * Table height in dialog units (value 150). |
| */ |
| private static final int TABLE_HEIGHT = 150; |
| |
| private static final int INFO_HEIGHT = 100; |
| |
| private final static int MORE_ID = IDialogConstants.CLIENT_ID + 1; |
| |
| private final static int PLUGINS_ID = IDialogConstants.CLIENT_ID + 2; |
| |
| private Table table; |
| |
| private Label imageLabel; |
| |
| private StyledText text; |
| |
| private Composite infoArea; |
| |
| private Map cachedImages = new HashMap(); |
| |
| private String columnTitles[] = { |
| WorkbenchMessages.AboutFeaturesDialog_provider, |
| WorkbenchMessages.AboutFeaturesDialog_featureName, |
| WorkbenchMessages.AboutFeaturesDialog_version, |
| WorkbenchMessages.AboutFeaturesDialog_featureId, |
| }; |
| |
| private String productName; |
| |
| private AboutBundleGroupData[] bundleGroupInfos; |
| |
| private int lastColumnChosen = 0; // initially sort by provider |
| |
| private boolean reverseSort = false; // initially sort ascending |
| |
| private AboutBundleGroupData lastSelection = null; |
| |
| private Button moreButton; |
| |
| private Button pluginsButton; |
| |
| private static Map featuresMap; |
| |
| /** |
| * Constructor for AboutFeaturesDialog. |
| * |
| * @param parentShell the parent shell |
| * @param productName the product name |
| * @param bundleGroupInfos the bundle info |
| */ |
| public AboutFeaturesDialog(Shell parentShell, String productName, |
| AboutBundleGroupData[] bundleGroupInfos) { |
| super(parentShell); |
| setShellStyle(getShellStyle() | SWT.RESIZE | SWT.MAX); |
| |
| this.productName = productName; |
| |
| // the order of the array may be changed due to sorting, so create a |
| // copy |
| this.bundleGroupInfos = new AboutBundleGroupData[bundleGroupInfos.length]; |
| System.arraycopy(bundleGroupInfos, 0, this.bundleGroupInfos, 0, |
| bundleGroupInfos.length); |
| |
| AboutData.sortByProvider(reverseSort, this.bundleGroupInfos); |
| } |
| |
| /** |
| * The More Info button was pressed. Open a browser with the license for the |
| * selected item or an information dialog if there is no license, or the browser |
| * cannot be opened. |
| */ |
| private void handleMoreInfoPressed() { |
| TableItem[] items = table.getSelection(); |
| if (items.length <= 0) |
| return; |
| |
| AboutBundleGroupData info = (AboutBundleGroupData) items[0].getData(); |
| if (info == null || !openBrowser(info.getLicenseUrl())) { |
| MessageDialog.openInformation(getShell(), WorkbenchMessages.AboutFeaturesDialog_noInfoTitle, |
| WorkbenchMessages.AboutFeaturesDialog_noInformation); |
| } |
| } |
| |
| /** |
| * The Plugins button was pressed. Open an about dialog on the plugins for |
| * the selected feature. |
| */ |
| private void handlePluginInfoPressed() { |
| TableItem[] items = table.getSelection(); |
| if (items.length <= 0) |
| return; |
| |
| AboutBundleGroupData info = (AboutBundleGroupData) items[0].getData(); |
| IBundleGroup bundleGroup = info.getBundleGroup(); |
| Bundle[] bundles = bundleGroup == null ? new Bundle[0] : bundleGroup |
| .getBundles(); |
| |
| AboutPluginsDialog d = new AboutPluginsDialog(getShell(), productName, |
| bundles, WorkbenchMessages.AboutFeaturesDialog_pluginInfoTitle, |
| NLS.bind(WorkbenchMessages.AboutFeaturesDialog_pluginInfoMessage, bundleGroup.getIdentifier()), |
| IWorkbenchHelpContextIds.ABOUT_FEATURES_PLUGINS_DIALOG); |
| d.open(); |
| } |
| |
| /* |
| * (non-Javadoc) Method declared on Dialog. |
| */ |
| protected void buttonPressed(int buttonId) { |
| switch (buttonId) { |
| case MORE_ID: |
| handleMoreInfoPressed(); |
| break; |
| case PLUGINS_ID: |
| handlePluginInfoPressed(); |
| break; |
| default: |
| super.buttonPressed(buttonId); |
| break; |
| } |
| } |
| |
| /* |
| * (non-Javadoc) Method declared on Window. |
| */ |
| protected void configureShell(Shell newShell) { |
| super.configureShell(newShell); |
| if (productName != null) |
| newShell.setText(NLS.bind(WorkbenchMessages.AboutFeaturesDialog_shellTitle,productName)); |
| |
| PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell, |
| IWorkbenchHelpContextIds.ABOUT_FEATURES_DIALOG); |
| } |
| |
| /** |
| * Add buttons to the dialog's button bar. |
| * |
| * Subclasses should override. |
| * |
| * @param parent |
| * the button bar composite |
| */ |
| protected void createButtonsForButtonBar(Composite parent) { |
| parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| |
| moreButton = createButton(parent, MORE_ID, WorkbenchMessages.AboutFeaturesDialog_moreInfo, false); |
| pluginsButton = createButton(parent, PLUGINS_ID, WorkbenchMessages.AboutFeaturesDialog_pluginsInfo, false); |
| Label l = new Label(parent, SWT.NONE); |
| l.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| GridLayout layout = (GridLayout) parent.getLayout(); |
| layout.numColumns++; |
| layout.makeColumnsEqualWidth = false; |
| |
| Button b = createButton(parent, IDialogConstants.OK_ID, |
| IDialogConstants.OK_LABEL, true); |
| b.setFocus(); |
| |
| TableItem[] items = table.getSelection(); |
| if (items.length > 0) |
| updateButtons((AboutBundleGroupData) items[0].getData()); |
| } |
| |
| /** |
| * Create the contents of the dialog (above the button bar). |
| * |
| * Subclasses should overide. |
| * |
| * @param parent the parent composite to contain the dialog area |
| * @return the dialog area control |
| */ |
| protected Control createDialogArea(Composite parent) { |
| setHandCursor(new Cursor(parent.getDisplay(), SWT.CURSOR_HAND)); |
| setBusyCursor(new Cursor(parent.getDisplay(), SWT.CURSOR_WAIT)); |
| getShell().addDisposeListener(new DisposeListener() { |
| public void widgetDisposed(DisposeEvent e) { |
| if (getHandCursor() != null) |
| getHandCursor().dispose(); |
| if (getBusyCursor() != null) |
| getBusyCursor().dispose(); |
| } |
| }); |
| |
| Composite outer = (Composite) super.createDialogArea(parent); |
| |
| createTable(outer); |
| createInfoArea(outer); |
| |
| return outer; |
| } |
| |
| /** |
| * Create the info area containing the image and text |
| */ |
| protected void createInfoArea(Composite parent) { |
| Font font = parent.getFont(); |
| |
| infoArea = new Composite(parent, SWT.NULL); |
| GridData data = new GridData(GridData.FILL, GridData.FILL, true, true); |
| // need to provide space for arbitrary feature infos, not just the |
| // one selected by default |
| data.heightHint = convertVerticalDLUsToPixels(INFO_HEIGHT); |
| infoArea.setLayoutData(data); |
| |
| GridLayout layout = new GridLayout(); |
| layout.numColumns = 2; |
| infoArea.setLayout(layout); |
| |
| imageLabel = new Label(infoArea, SWT.NONE); |
| data = new GridData(GridData.FILL, GridData.BEGINNING, false, false); |
| data.widthHint = 32; |
| data.heightHint = 32; |
| imageLabel.setLayoutData(data); |
| imageLabel.setFont(font); |
| |
| // text on the right |
| text = new StyledText(infoArea, SWT.MULTI | SWT.READ_ONLY); |
| text.setCaret(null); |
| text.setFont(parent.getFont()); |
| data = new GridData(GridData.FILL, GridData.FILL, true, true); |
| text.setLayoutData(data); |
| text.setFont(font); |
| text.setCursor(null); |
| text.setBackground(infoArea.getBackground()); |
| addListeners(text); |
| |
| TableItem[] items = table.getSelection(); |
| if (items.length > 0) |
| updateInfoArea((AboutBundleGroupData) items[0].getData()); |
| } |
| |
| /** |
| * Create the table part of the dialog. |
| * |
| * @param parent the parent composite to contain the dialog area |
| */ |
| protected void createTable(Composite parent) { |
| table = new Table(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE |
| | SWT.FULL_SELECTION | SWT.BORDER); |
| |
| GridData gridData = new GridData(GridData.FILL, GridData.FILL, true, |
| true); |
| gridData.heightHint = convertVerticalDLUsToPixels(TABLE_HEIGHT); |
| table.setLayoutData(gridData); |
| table.setHeaderVisible(true); |
| |
| table.setLinesVisible(true); |
| table.setFont(parent.getFont()); |
| table.addSelectionListener(new SelectionAdapter() { |
| public void widgetSelected(SelectionEvent e) { |
| AboutBundleGroupData info = (AboutBundleGroupData) e.item |
| .getData(); |
| updateInfoArea(info); |
| updateButtons(info); |
| } |
| }); |
| |
| int[] columnWidths = { convertHorizontalDLUsToPixels(120), |
| convertHorizontalDLUsToPixels(120), |
| convertHorizontalDLUsToPixels(70), |
| convertHorizontalDLUsToPixels(130) }; |
| |
| for (int i = 0; i < columnTitles.length; i++) { |
| TableColumn tableColumn = new TableColumn(table, SWT.NULL); |
| tableColumn.setWidth(columnWidths[i]); |
| tableColumn.setText(columnTitles[i]); |
| final int columnIndex = i; |
| tableColumn.addSelectionListener(new SelectionAdapter() { |
| public void widgetSelected(SelectionEvent e) { |
| sort(columnIndex); |
| } |
| }); |
| } |
| |
| // create a table row for each bundle group |
| String selId = lastSelection == null ? null : lastSelection.getId(); |
| int sel = 0; |
| for (int i = 0; i < bundleGroupInfos.length; i++) { |
| if (bundleGroupInfos[i].getId().equals(selId)) |
| sel = i; |
| |
| TableItem item = new TableItem(table, SWT.NULL); |
| item.setText(createRow(bundleGroupInfos[i])); |
| item.setData(bundleGroupInfos[i]); |
| } |
| |
| // if an item was specified during construction, it should be |
| // selected when the table is created |
| if (bundleGroupInfos.length > 0) { |
| table.setSelection(sel); |
| table.showSelection(); |
| } |
| } |
| |
| /** |
| * @see Window#close() |
| */ |
| public boolean close() { |
| boolean ret = super.close(); |
| |
| Iterator iter = cachedImages.values().iterator(); |
| while (iter.hasNext()) { |
| Image image = (Image) iter.next(); |
| image.dispose(); |
| } |
| |
| return ret; |
| } |
| |
| /** |
| * Update the button enablement |
| */ |
| private void updateButtons(AboutBundleGroupData info) { |
| if (info == null) { |
| moreButton.setEnabled(false); |
| pluginsButton.setEnabled(false); |
| return; |
| } |
| |
| // Creating the feature map is too much just to determine enablement, so if |
| // it doesn't already exist, just enable the buttons. If this was the wrong |
| // choice, then when the button is actually pressed an dialog will be opened. |
| if (featuresMap == null) { |
| moreButton.setEnabled(true); |
| pluginsButton.setEnabled(true); |
| return; |
| } |
| |
| moreButton.setEnabled(info.getLicenseUrl() != null); |
| pluginsButton.setEnabled(true); |
| } |
| |
| /** |
| * Update the info area |
| */ |
| private void updateInfoArea(AboutBundleGroupData info) { |
| if (info == null) { |
| imageLabel.setImage(null); |
| text.setText(""); //$NON-NLS-1$ |
| return; |
| } |
| |
| ImageDescriptor desc = info.getFeatureImage(); |
| Image image = (Image) cachedImages.get(desc); |
| if (image == null && desc != null) { |
| image = desc.createImage(); |
| cachedImages.put(desc, image); |
| } |
| imageLabel.setImage(image); |
| |
| String aboutText = info.getAboutText(); |
| setItem(null); |
| if (aboutText != null) |
| setItem(scan(aboutText)); |
| |
| if (getItem() == null) |
| text.setText(WorkbenchMessages.AboutFeaturesDialog_noInformation); |
| else { |
| text.setText(getItem().getText()); |
| text.setCursor(null); |
| setLinkRanges(text, getItem().getLinkRanges()); |
| } |
| } |
| |
| /** |
| * Select the initial selection |
| * |
| * @param info the info |
| */ |
| public void setInitialSelection(AboutBundleGroupData info) { |
| lastSelection = info; |
| } |
| |
| /** |
| * Sort the rows of the table based on the selected column. |
| * |
| * @param column |
| * index of table column selected as sort criteria |
| */ |
| private void sort(int column) { |
| if (lastColumnChosen == column) |
| reverseSort = !reverseSort; |
| else { |
| reverseSort = false; |
| lastColumnChosen = column; |
| } |
| |
| if (table.getItemCount() <= 1) |
| return; |
| |
| // Remember the last selection |
| int sel = table.getSelectionIndex(); |
| if (sel != -1) |
| lastSelection = bundleGroupInfos[sel]; |
| |
| switch (column) { |
| case 0: |
| AboutData.sortByProvider(reverseSort, bundleGroupInfos); |
| break; |
| case 1: |
| AboutData.sortByName(reverseSort, bundleGroupInfos); |
| break; |
| case 2: |
| AboutData.sortByVersion(reverseSort, bundleGroupInfos); |
| break; |
| case 3: |
| AboutData.sortById(reverseSort, bundleGroupInfos); |
| break; |
| } |
| |
| refreshTable(); |
| } |
| |
| /** |
| * Refresh the rows of the table based on the selected column. Maintain |
| * selection from before sort action request. |
| */ |
| private void refreshTable() { |
| TableItem[] items = table.getItems(); |
| |
| // create new order of table items |
| for (int i = 0; i < items.length; i++) { |
| items[i].setText(createRow(bundleGroupInfos[i])); |
| items[i].setData(bundleGroupInfos[i]); |
| } |
| |
| // Maintain the original selection |
| int sel = -1; |
| if (lastSelection != null) { |
| String oldId = lastSelection.getId(); |
| for (int k = 0; k < bundleGroupInfos.length; k++) |
| if (oldId.equalsIgnoreCase(bundleGroupInfos[k].getId())) |
| sel = k; |
| |
| table.setSelection(sel); |
| table.showSelection(); |
| } |
| |
| updateInfoArea(lastSelection); |
| } |
| |
| /** |
| * Return an array of strings containing the argument's information in the |
| * proper order for this table's columns. |
| * |
| * @param info |
| * the source information for the new row, must not be null |
| */ |
| private static String[] createRow(AboutBundleGroupData info) { |
| return new String[] { info.getProviderName(), info.getName(), |
| info.getVersion(), info.getId() }; |
| } |
| } |