| /******************************************************************************* |
| * Copyright (c) 2000, 2017 IBM Corporation and others. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * Sebastian Davids <sdavids@gmx.de> - bug 75886 |
| * RĂ¼diger Herrmann <ruediger.herrmann@gmx.de> - bug 516228 |
| *******************************************************************************/ |
| package org.eclipse.team.internal.ui.dialogs; |
| |
| import java.io.IOException; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.eclipse.core.runtime.ListenerList; |
| import org.eclipse.jface.dialogs.Dialog; |
| import org.eclipse.jface.dialogs.IDialogConstants; |
| import org.eclipse.jface.dialogs.IPageChangeProvider; |
| import org.eclipse.jface.dialogs.IPageChangedListener; |
| import org.eclipse.jface.dialogs.PageChangedEvent; |
| import org.eclipse.jface.dialogs.TrayDialog; |
| import org.eclipse.jface.preference.IPersistentPreferenceStore; |
| import org.eclipse.jface.preference.IPreferencePageContainer; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.preference.PreferenceDialog; |
| import org.eclipse.jface.preference.PreferencePage; |
| import org.eclipse.jface.resource.ImageDescriptor; |
| import org.eclipse.jface.resource.ImageRegistry; |
| import org.eclipse.jface.resource.JFaceColors; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.SafeRunnable; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.CLabel; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.layout.FillLayout; |
| 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.Display; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Shell; |
| import org.eclipse.swt.widgets.TabFolder; |
| import org.eclipse.swt.widgets.TabItem; |
| import org.eclipse.team.internal.ui.TeamUIMessages; |
| import org.eclipse.team.internal.ui.TeamUIPlugin; |
| import org.eclipse.team.internal.ui.Utils; |
| |
| public class PreferencePageContainerDialog extends TrayDialog |
| implements IPreferencePageContainer, IPageChangeProvider { |
| |
| private PreferencePage[] pages; |
| private PreferencePage currentPage; |
| |
| private Composite fTitleArea; |
| private Label fTitleImage; |
| private CLabel fMessageLabel; |
| |
| private String fMessage; |
| private Color fNormalMsgAreaBackground; |
| private Image fErrorMsgImage; |
| |
| private Button fOkButton; |
| |
| private ListenerList<IPageChangedListener> pageChangedListeners = new ListenerList<IPageChangedListener>(); |
| |
| /** |
| * The Composite in which a page is shown. |
| */ |
| private Composite fPageContainer; |
| |
| /** |
| * The minimum page size; 200 by 200 by default. |
| * |
| * @see #setMinimumPageSize(Point) |
| */ |
| private Point fMinimumPageSize = new Point(200,200); |
| private TabFolder tabFolder; |
| private Map<TabItem, PreferencePage> pageMap = new HashMap<>(); |
| |
| /** |
| * Must declare our own images as the JFaceResource images will not be created unless |
| * a property/preference dialog has been shown |
| */ |
| protected static final String PREF_DLG_TITLE_IMG = "preference_page_container_image";//$NON-NLS-1$ |
| protected static final String PREF_DLG_IMG_TITLE_ERROR = "preference_page_container_title_error_image";//$NON-NLS-1$ |
| static { |
| ImageRegistry reg = TeamUIPlugin.getPlugin().getImageRegistry(); |
| reg.put(PREF_DLG_TITLE_IMG, ImageDescriptor.createFromFile(PreferenceDialog.class, "images/pref_dialog_title.png"));//$NON-NLS-1$ |
| reg.put(PREF_DLG_IMG_TITLE_ERROR, ImageDescriptor.createFromFile(Dialog.class, "images/message_error.png"));//$NON-NLS-1$ |
| } |
| |
| public PreferencePageContainerDialog(Shell shell, PreferencePage[] pages) { |
| super(shell); |
| this.pages = pages; |
| } |
| |
| @Override |
| protected void okPressed() { |
| for (int i = 0; i < pages.length; i++) { |
| PreferencePage page = pages[i]; |
| page.performOk(); |
| } |
| |
| handleSave(); |
| |
| super.okPressed(); |
| } |
| |
| /** |
| * Sets the title for this dialog. |
| * @param title the title. |
| */ |
| public void setTitle(String title) { |
| Shell shell= getShell(); |
| if ((shell != null) && !shell.isDisposed()) { |
| shell.setText(title); |
| } |
| } |
| |
| @Override |
| protected Control createDialogArea(Composite parent) { |
| Composite composite = (Composite)super.createDialogArea(parent); |
| ((GridLayout) composite.getLayout()).numColumns = 1; |
| |
| createDescriptionArea(composite); |
| |
| if (isSinglePage()) { |
| createSinglePageArea(composite, pages[0]); |
| } else { |
| createMultiplePageArea(composite); |
| } |
| |
| // Build the separator line |
| Label separator = new Label(composite, SWT.HORIZONTAL | SWT.SEPARATOR); |
| GridData gd = new GridData(GridData.FILL_HORIZONTAL); |
| gd.horizontalSpan = 2; |
| separator.setLayoutData(gd); |
| |
| setTitle(TeamUIMessages.PreferencePageContainerDialog_6); |
| applyDialogFont(parent); |
| |
| composite.addHelpListener(e -> currentPage.performHelp()); |
| |
| return composite; |
| } |
| |
| private void createMultiplePageArea(Composite composite) { |
| // create a tab folder for the page |
| tabFolder = new TabFolder(composite, SWT.NONE); |
| tabFolder.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| |
| for (int i = 0; i < pages.length; i++) { |
| PreferencePage page = pages[i]; |
| // text decoration options |
| TabItem tabItem = new TabItem(tabFolder, SWT.NONE); |
| tabItem.setText(page.getTitle());// |
| tabItem.setControl(createPageArea(tabFolder, page)); |
| pageMap.put(tabItem, page); |
| } |
| |
| tabFolder.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(SelectionEvent e) { |
| updatePageSelection(); |
| } |
| }); |
| updatePageSelection(); |
| } |
| |
| protected void updatePageSelection() { |
| TabItem[] items = tabFolder.getSelection(); |
| if (items.length == 1) { |
| currentPage = pageMap.get(items[0]); |
| updateMessage(); |
| } |
| firePageChanged(new PageChangedEvent(this, currentPage)); |
| } |
| |
| private boolean isSinglePage() { |
| return pages.length == 1; |
| } |
| |
| /* |
| * Create the page contents for a single preferences page |
| */ |
| private void createSinglePageArea(Composite composite, PreferencePage page) { |
| createPageArea(composite, page); |
| currentPage = page; |
| updateMessage(); |
| } |
| |
| private Control createPageArea(Composite composite, PreferencePage page) { |
| // Build the Page container |
| fPageContainer = createPageContainer(composite); |
| fPageContainer.setLayoutData(new GridData(GridData.FILL_BOTH)); |
| |
| page.setContainer(this); |
| page.createControl(fPageContainer); |
| return fPageContainer; |
| } |
| |
| private void createDescriptionArea(Composite composite) { |
| // Build the title area and separator line |
| Composite titleComposite = new Composite(composite, SWT.NONE); |
| GridLayout layout = new GridLayout(); |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| layout.verticalSpacing = 0; |
| layout.horizontalSpacing = 0; |
| titleComposite.setLayout(layout); |
| titleComposite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
| |
| createMessageArea(titleComposite); |
| |
| Label titleBarSeparator = new Label(titleComposite, SWT.HORIZONTAL | SWT.SEPARATOR); |
| GridData gd = new GridData(GridData.FILL_HORIZONTAL); |
| titleBarSeparator.setLayoutData(gd); |
| } |
| |
| /** |
| * Creates the dialog's title area. |
| * |
| * @param parent the SWT parent for the title area composite |
| * @return the created title area composite |
| */ |
| private Composite createMessageArea(Composite parent) { |
| |
| // Create the title area which will contain |
| // a title, message, and image. |
| fTitleArea = new Composite(parent, SWT.NONE); |
| GridLayout layout = new GridLayout(); |
| layout.marginHeight = 0; |
| layout.marginWidth = 0; |
| layout.verticalSpacing = 0; |
| layout.horizontalSpacing = 0; |
| layout.numColumns = 2; |
| |
| // Get the colors for the title area |
| Display display = parent.getDisplay(); |
| Color bg = JFaceColors.getBannerBackground(display); |
| Color fg = JFaceColors.getBannerForeground(display); |
| |
| GridData layoutData = new GridData(GridData.FILL_BOTH); |
| fTitleArea.setLayout(layout); |
| fTitleArea.setLayoutData(layoutData); |
| fTitleArea.setBackground(bg); |
| |
| // Message label |
| fMessageLabel = new CLabel(fTitleArea, SWT.LEFT); |
| fMessageLabel.setBackground(bg); |
| fMessageLabel.setForeground(fg); |
| fMessageLabel.setText(" ");//$NON-NLS-1$ |
| fMessageLabel.setFont(JFaceResources.getBannerFont()); |
| |
| final IPropertyChangeListener fontListener = event -> { |
| if(JFaceResources.BANNER_FONT.equals(event.getProperty()) || |
| JFaceResources.DIALOG_FONT.equals(event.getProperty())) { |
| updateMessage(); |
| } |
| }; |
| |
| fMessageLabel.addDisposeListener(event -> JFaceResources.getFontRegistry().removeListener(fontListener)); |
| |
| JFaceResources.getFontRegistry().addListener(fontListener); |
| |
| GridData gd = new GridData(GridData.FILL_BOTH); |
| fMessageLabel.setLayoutData(gd); |
| |
| // Title image |
| fTitleImage = new Label(fTitleArea, SWT.LEFT); |
| fTitleImage.setBackground(bg); |
| fTitleImage.setImage(TeamUIPlugin.getPlugin().getImageRegistry().get(PREF_DLG_TITLE_IMG)); |
| gd = new GridData(); |
| gd.horizontalAlignment = GridData.END; |
| fTitleImage.setLayoutData(gd); |
| updateMessage(); |
| return fTitleArea; |
| } |
| |
| /** |
| * Creates the inner page container. |
| */ |
| private Composite createPageContainer(Composite parent) { |
| Composite result = new Composite(parent, SWT.NULL); |
| FillLayout layout = new FillLayout(); |
| layout.marginHeight = 5; |
| layout.marginWidth = 5; |
| result.setLayout(layout); |
| return result; |
| } |
| |
| /** |
| * Sets the minimum page size. |
| * |
| * @param size the page size encoded as |
| * <code>new Point(width,height)</code> |
| */ |
| public void setMinimumPageSize(Point size) { |
| fMinimumPageSize.x = size.x; |
| fMinimumPageSize.y = size.y; |
| } |
| |
| /** |
| * Display the given error message. The currently displayed message |
| * is saved and will be redisplayed when the error message is set |
| * to <code>null</code>. |
| * |
| * @param errorMessage the errorMessage to display or <code>null</code> |
| */ |
| public void setErrorMessage(String errorMessage) { |
| if (errorMessage == null) { |
| if (fMessageLabel.getImage() != null) { |
| // we were previously showing an error |
| fMessageLabel.setBackground(fNormalMsgAreaBackground); |
| fMessageLabel.setImage(null); |
| fTitleImage.setImage(TeamUIPlugin.getPlugin().getImageRegistry().get(PREF_DLG_TITLE_IMG)); |
| fTitleArea.layout(true); |
| } |
| |
| // show the message |
| setMessage(fMessage); |
| |
| } else { |
| fMessageLabel.setText(errorMessage); |
| if (fMessageLabel.getImage() == null) { |
| // we were not previously showing an error |
| |
| // lazy initialize the error background color and image |
| if (fErrorMsgImage == null) { |
| fErrorMsgImage = TeamUIPlugin.getPlugin().getImageRegistry().get(PREF_DLG_IMG_TITLE_ERROR); |
| } |
| |
| // show the error |
| fNormalMsgAreaBackground = fMessageLabel.getBackground(); |
| fMessageLabel.setBackground(JFaceColors.getErrorBackground(fMessageLabel.getDisplay())); |
| fMessageLabel.setImage(fErrorMsgImage); |
| fTitleImage.setImage(null); |
| fTitleArea.layout(true); |
| } |
| } |
| } |
| /** |
| * Set the message text. If the message line currently displays an error, |
| * the message is stored and will be shown after a call to clearErrorMessage |
| * @param newMessage |
| */ |
| public void setMessage(String newMessage) { |
| fMessage = newMessage; |
| if (fMessage == null) { |
| fMessage = "";//$NON-NLS-1$ |
| } |
| if (fMessageLabel.getImage() == null) { |
| // we are not showing an error |
| fMessageLabel.setText(fMessage); |
| } |
| } |
| |
| @Override |
| public void updateMessage() { |
| if (currentPage != null) { |
| String pageMessage = currentPage.getMessage(); |
| String pageErrorMessage = currentPage.getErrorMessage(); |
| |
| // Adjust the font |
| if (pageMessage == null && pageErrorMessage == null) |
| fMessageLabel.setFont(JFaceResources.getBannerFont()); |
| else |
| fMessageLabel.setFont(JFaceResources.getDialogFont()); |
| |
| // Set the message and error message |
| if (pageMessage == null) { |
| if (isSinglePage()) { |
| setMessage(TeamUIMessages.PreferencePageContainerDialog_6); |
| } else { |
| //remove mnemonic see bug 75886 |
| String title = currentPage.getTitle(); |
| title = title.replaceAll("&", "");//$NON-NLS-1$ //$NON-NLS-2$ |
| setMessage(title); |
| } |
| } else { |
| setMessage(pageMessage); |
| } |
| setErrorMessage(pageErrorMessage); |
| } |
| } |
| |
| @Override |
| public IPreferenceStore getPreferenceStore() { |
| return null; |
| } |
| |
| @Override |
| public void updateButtons() { |
| if (fOkButton != null) { |
| boolean isValid = true; |
| for (int i = 0; i < pages.length; i++) { |
| PreferencePage page = pages[i]; |
| if (!page.isValid()) { |
| isValid = false; |
| break; |
| } |
| } |
| fOkButton.setEnabled(isValid); |
| } |
| } |
| |
| @Override |
| public void updateTitle() { |
| updateMessage(); |
| } |
| |
| @Override |
| protected void createButtonsForButtonBar(Composite parent) { |
| fOkButton= createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); |
| createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); |
| } |
| |
| /** |
| * Save the values specified in the pages. |
| * <p> |
| * The default implementation of this framework method saves all |
| * pages of type <code>PreferencePage</code> (if their store needs saving |
| * and is a <code>PreferenceStore</code>). |
| * </p> |
| * <p> |
| * Subclasses may override. |
| * </p> |
| */ |
| protected void handleSave() { |
| // Save now in case tbe workbench does not shutdown cleanly |
| for (int i = 0; i < pages.length; i++) { |
| PreferencePage page = pages[i]; |
| IPreferenceStore store = page.getPreferenceStore(); |
| if (store != null |
| && store.needsSaving() |
| && store instanceof IPersistentPreferenceStore) { |
| try { |
| ((IPersistentPreferenceStore) store).save(); |
| } catch (IOException e) { |
| Utils.handle(e); |
| } |
| } |
| } |
| } |
| |
| |
| @Override |
| public void addPageChangedListener(final IPageChangedListener listener) { |
| pageChangedListeners.add(listener); |
| } |
| |
| @Override |
| public Object getSelectedPage() { |
| return currentPage; |
| } |
| |
| @Override |
| public void removePageChangedListener(IPageChangedListener listener) { |
| pageChangedListeners.remove(listener); |
| } |
| |
| private void firePageChanged(final PageChangedEvent event) { |
| Object[] listeners = pageChangedListeners.getListeners(); |
| for (int i = 0; i < listeners.length; i++) { |
| final IPageChangedListener l = (IPageChangedListener) listeners[i]; |
| SafeRunnable.run(new SafeRunnable() { |
| @Override |
| public void run() { |
| l.pageChanged(event); |
| } |
| }); |
| } |
| } |
| |
| |
| } |