All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jface.preference.PreferencePage Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 * Copyright (c) 2000, 2015 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  - Fix for bug 38729 - [Preferences]
 * 			 NPE PreferencePage isValid.
 *******************************************************************************/
package org.eclipse.jface.preference;

import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.DialogPage;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogPage;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Point;
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.Event;
import org.eclipse.swt.widgets.Label;

/**
 * Abstract base implementation for all preference page implementations.
 * 

* Subclasses must implement the createContents framework * method to supply the page's main control. *

*

* Subclasses should extend the doComputeSize framework * method to compute the size of the page's control. *

*

* Subclasses may override the performOk, performApply, * performDefaults, performCancel, and performHelp * framework methods to react to the standard button events. *

*

* Subclasses may call the noDefaultAndApplyButton framework * method before the page's control has been created to suppress * the standard Apply and Defaults buttons. *

*/ public abstract class PreferencePage extends DialogPage implements IPreferencePage { /** * Preference store, or null. */ private IPreferenceStore preferenceStore; /** * Valid state for this page; true by default. * * @see #isValid */ private boolean isValid = true; /** * Body of page. */ private Control body; /** * Whether this page has the standard Apply button; true by * default. * * @see #noDefaultAndApplyButton */ private boolean createApplyButton = true; /** * Whether this page has the standard Default button; true by * default. * * @see #noDefaultButton */ private boolean createDefaultButton = true; /** * Standard Defaults button, or null if none. * This button has id DEFAULTS_ID. */ private Button defaultsButton = null; /** * The container this preference page belongs to; null * if none. */ private IPreferencePageContainer container = null; /** * Standard Apply button, or null if none. * This button has id APPLY_ID. */ private Button applyButton = null; /** * Description label. * * @see #createDescriptionLabel(Composite) */ private Label descriptionLabel; /** * Caches size of page. */ private Point size = null; /** * Creates a new preference page with an empty title and no image. */ protected PreferencePage() { this(""); //$NON-NLS-1$ } /** * Creates a new preference page with the given title and no image. * * @param title the title of this preference page */ protected PreferencePage(String title) { super(title); } /** * Creates a new abstract preference page with the given title and image. * * @param title the title of this preference page * @param image the image for this preference page, * or null if none */ protected PreferencePage(String title, ImageDescriptor image) { super(title, image); } /** * Computes the size for this page's UI control. *

* The default implementation of this IPreferencePage * method returns the size set by setSize; if no size * has been set, but the page has a UI control, the framework * method doComputeSize is called to compute the size. *

* * @return the size of the preference page encoded as * new Point(width,height), or * (0,0) if the page doesn't currently have any UI component */ @Override public Point computeSize() { if (size != null) { return size; } Control control = getControl(); if (control != null) { size = doComputeSize(); return size; } return new Point(0, 0); } /** * Contributes additional buttons to the given composite. *

* The default implementation of this framework hook method does nothing. * Subclasses should override this method to contribute buttons to this page's * button bar. For each button a subclass contributes, it must also increase the * parent's grid layout number of columns by one; that is, *

* *
	 * ((GridLayout) parent.getLayout()).numColumns++);
	 * 
* * @param parent the button bar */ protected void contributeButtons(Composite parent) { } /** * Creates and returns the SWT control for the customized body * of this preference page under the given parent composite. *

* This framework method must be implemented by concrete subclasses. Any * subclass returning a Composite object whose Layout * has default margins (for example, a GridLayout) is expected to * set the margins of this Layout to 0 pixels. *

* * @param parent the parent composite * @return the new control */ protected abstract Control createContents(Composite parent); /** * The PreferencePage implementation of this * IDialogPage method creates a description label * and button bar for the page. It calls createContents * to create the custom contents of the page. *

* If a subclass that overrides this method creates a Composite * that has a layout with default margins (for example, a GridLayout) * it is expected to set the margins of this Layout to 0 pixels. * @see IDialogPage#createControl(Composite) */ @Override public void createControl(Composite parent){ GridData gd; Composite content = new Composite(parent, SWT.NONE); setControl(content); GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; content.setLayout(layout); //Apply the font on creation for backward compatibility applyDialogFont(content); // initialize the dialog units initializeDialogUnits(content); descriptionLabel = createDescriptionLabel(content); if (descriptionLabel != null) { descriptionLabel.setLayoutData(new GridData( GridData.FILL_HORIZONTAL)); } body = createContents(content); if (body != null) { // null is not a valid return value but support graceful failure body.setLayoutData(new GridData(GridData.FILL_BOTH)); } Composite buttonBar = new Composite(content, SWT.NONE); layout = new GridLayout(); layout.numColumns = 0; layout.marginHeight = 0; layout.marginWidth = 0; layout.makeColumnsEqualWidth = false; buttonBar.setLayout(layout); gd = new GridData(GridData.HORIZONTAL_ALIGN_END); buttonBar.setLayoutData(gd); contributeButtons(buttonBar); if (createApplyButton || createDefaultButton) { layout.numColumns += 1 + (createApplyButton && createDefaultButton ? 1 : 0); int widthHint = convertHorizontalDLUsToPixels(IDialogConstants.BUTTON_WIDTH); if (createDefaultButton) { String label = JFaceResources.getString("defaults"); //$NON-NLS-1$ defaultsButton = new Button(buttonBar, SWT.PUSH); defaultsButton.setText(label); Dialog.applyDialogFont(defaultsButton); Point minButtonSize = defaultsButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); data.widthHint = Math.max(widthHint, minButtonSize.x); defaultsButton.setLayoutData(data); defaultsButton.addSelectionListener(widgetSelectedAdapter(e -> performDefaults())); } if (createApplyButton) { String label = JFaceResources.getString("apply"); //$NON-NLS-1$ applyButton = new Button(buttonBar, SWT.PUSH); applyButton.setText(label); Dialog.applyDialogFont(applyButton); Point minButtonSize = applyButton.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); data.widthHint = Math.max(widthHint, minButtonSize.x); applyButton.setLayoutData(data); applyButton.addSelectionListener(widgetSelectedAdapter(e -> performApply())); applyButton.setEnabled(isValid()); } applyDialogFont(buttonBar); } else /* Check if there are any other buttons on the button bar. * If not, throw away the button bar composite. Otherwise * there is an unusually large button bar. */ if (buttonBar.getChildren().length < 1) { buttonBar.dispose(); } } /** * Apply the dialog font to the composite and it's children if it is set. * Subclasses may override if they wish to set the font themselves. * * @param composite the composite to apply the font to. Font will also be * applied to its children. If the control is null * nothing happens. */ protected void applyDialogFont(Composite composite) { Dialog.applyDialogFont(composite); } /** * Creates and returns an SWT label under the given composite. * * @param parent the parent composite * @return the new label */ protected Label createDescriptionLabel(Composite parent) { Label result = null; String description = getDescription(); if (description != null) { result = new Label(parent, SWT.WRAP); result.setFont(parent.getFont()); result.setText(description); } return result; } /** * Computes the size needed by this page's UI control. *

* All pages should override this method and set the appropriate sizes * of their widgets, and then call super.doComputeSize. *

* * @return the size of the preference page encoded as * new Point(width,height) */ protected Point doComputeSize() { if (descriptionLabel != null && body != null) { Point bodySize = body.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); GridData gd = (GridData) descriptionLabel.getLayoutData(); gd.widthHint = bodySize.x; } return getControl().computeSize(SWT.DEFAULT, SWT.DEFAULT, true); } /** * Returns the preference store of this preference page. *

* This is a framework hook method for subclasses to return a * page-specific preference store. The default implementation * returns null. *

* * @return the preference store, or null if none */ protected IPreferenceStore doGetPreferenceStore() { return null; } /** * Returns the container of this page. * * @return the preference page container, or null if this * page has yet to be added to a container */ public IPreferencePageContainer getContainer() { return container; } /** * Returns the preference store of this preference page. * * @return the preference store , or null if none */ public IPreferenceStore getPreferenceStore() { if (preferenceStore == null) { preferenceStore = doGetPreferenceStore(); } if (preferenceStore != null) { return preferenceStore; } else if (container != null) { return container.getPreferenceStore(); } return null; } /** * The preference page implementation of an IPreferencePage * method returns whether this preference page is valid. Preference * pages are considered valid by default; call setValid(false) * to make a page invalid. * @see IPreferencePage#isValid() */ @Override public boolean isValid() { return isValid; } /** * Suppresses creation of the standard Default and Apply buttons * for this page. *

* Subclasses wishing a preference page without these buttons * should call this framework method before the page's control * has been created. *

*/ protected void noDefaultAndApplyButton() { createApplyButton = false; createDefaultButton = false; } /** * Suppress creation of the standard Default button for this page. *

* Subclasses wishing a preference page with this button should call this * framework method before the page's control has been created. *

* * @since 3.11 */ protected void noDefaultButton() { createDefaultButton = false; } /** * The PreferencePage implementation of this * IPreferencePage method returns true if the page * is valid. * * @see IPreferencePage#okToLeave() */ @Override public boolean okToLeave() { return isValid(); } /** * Performs special processing when this page's Apply button has been pressed. *

* This is a framework hook method for subclasses to do special things when * the Apply button has been pressed. * The default implementation of this framework method simply calls * performOk to simulate the pressing of the page's OK button. *

* * @see #performOk() * @see #performCancel() */ protected void performApply() { performOk(); } /** * The preference page implementation of an IPreferencePage method * performs special processing when this page's Cancel button has been pressed. *

* This is a framework hook method for subclasses to do special things when the * Cancel button has been pressed. The default implementation of this framework * method does nothing and returns true. *

*

* Note that UI guidelines on different platforms disagree on whether Cancel * should revert changes that have been applied with the Apply button. Windows * wants applied changes to persist on Cancel, whereas Mac * and GTK * consider Apply a preview that should not be saved on Cancel. Eclipse * applications typically adhere to the Windows guidelines and just override * {@link #performOk()} and save preferences there. *

* * @see IPreferencePage#performCancel() */ @Override public boolean performCancel() { return true; } /** * Performs special processing when this page's Defaults button has been pressed. *

* This is a framework hook method for subclasses to do special things when * the Defaults button has been pressed. * Subclasses may override, but should call super.performDefaults. *

*/ protected void performDefaults() { updateApplyButton(); } @Override public boolean performOk() { return true; } @Override public void setContainer(IPreferencePageContainer container) { this.container = container; } /** * Sets the preference store for this preference page. *

* If preferenceStore is set to null, getPreferenceStore * will invoke doGetPreferenceStore the next time it is called. *

* * @param store the preference store, or null * @see #getPreferenceStore */ public void setPreferenceStore(IPreferenceStore store) { preferenceStore = store; } @Override public void setSize(Point uiSize) { Control control = getControl(); if (control != null) { control.setSize(uiSize); size = uiSize; } } /** * The PreferencePage implementation of this IDialogPage * method extends the DialogPage implementation to update * the preference page container title. Subclasses may extend. * @see IDialogPage#setTitle(String) */ @Override public void setTitle(String title) { super.setTitle(title); if (getContainer() != null) { getContainer().updateTitle(); } } /** * Sets whether this page is valid. * The enable state of the container buttons and the * apply button is updated when a page's valid state * changes. * * @param b the new valid state */ public void setValid(boolean b) { boolean oldValue = isValid; isValid = b; if (oldValue != isValid) { // update container state if (getContainer() != null) { getContainer().updateButtons(); } // update page state updateApplyButton(); } } @Override public String toString() { return getTitle(); } /** * Updates the enabled state of the Apply button to reflect whether * this page is valid. */ protected void updateApplyButton() { if (applyButton != null) { applyButton.setEnabled(isValid()); } } /** * Creates a composite with a highlighted Note entry and a message text. * This is designed to take up the full width of the page. * * @param font the font to use * @param composite the parent composite * @param title the title of the note * @param message the message for the note * @return the composite for the note */ protected Composite createNoteComposite(Font font, Composite composite, String title, String message) { Composite messageComposite = new Composite(composite, SWT.NONE); GridLayout messageLayout = new GridLayout(); messageLayout.numColumns = 2; messageLayout.marginWidth = 0; messageLayout.marginHeight = 0; messageComposite.setLayout(messageLayout); messageComposite.setLayoutData(new GridData( GridData.HORIZONTAL_ALIGN_FILL)); messageComposite.setFont(font); final Label noteLabel = new Label(messageComposite, SWT.BOLD); noteLabel.setText(title); noteLabel.setFont(JFaceResources.getFontRegistry().getBold( JFaceResources.DIALOG_FONT)); noteLabel .setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); Label messageLabel = new Label(messageComposite, SWT.WRAP); messageLabel.setText(message); messageLabel.setFont(font); return messageComposite; } /** * Returns the Apply button. * * @return the Apply button */ protected Button getApplyButton() { return applyButton; } /** * Returns the Restore Defaults button. * * @return the Restore Defaults button */ protected Button getDefaultsButton() { return defaultsButton; } @Override public void performHelp() { getControl().notifyListeners(SWT.Help, new Event()); } /** * Applies the given data to this page. *

* It is up to the subclasses to specify the contract and the data format. The contract is not * guaranteed if the subclass is in an internal package. *

*

* Note: The implementation must silently ignore all unknown data. *

*

* The default implementation does nothing. *

* * @param data the data as specified by the subclass * @since 3.1 */ public void applyData(Object data) { } @Override public void setErrorMessage(String newMessage) { super.setErrorMessage(newMessage); if (getContainer() != null) { getContainer().updateMessage(); } } @Override public void setMessage(String newMessage, int newType) { super.setMessage(newMessage, newType); if (getContainer() != null) { getContainer().updateMessage(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy