# HG changeset patch
# User Frank Benoit
+ * Dialogs are usually modal. Consequently, it is generally bad practice to open
+ * a dialog without a parent. A modal dialog without a parent is not prevented
+ * from disappearing behind the application's other windows, making it very
+ * confusing for the user.
+ *
+ * If there is more than one modal dialog is open the second one should be
+ * parented off of the shell of the first one otherwise it is possible that the
+ * OS will give focus to the first dialog potentially blocking the UI.
+ *
+ * The required
+ * The required
+ * The required
+ * The required
+ * The
+ * The
+ * This method may only be called after
+ * Clients may call this framework method, but should not override it.
+ *
+ * This method may only be called after
+ * Clients may call this framework method, but should not override it.
+ *
+ * This method may only be called after
+ * Clients may call this framework method, but should not override it.
+ *
+ * This method may only be called after
+ * Clients may call this framework method, but should not override it.
+ *
+ * The
+ * The
+ * The returned control's layout data must be an instance of
+ *
+ * The
+ * The
+ * The returned control's layout data must be an instance of
+ *
+ * Subclasses must override this method but may call
+ * Clients may call this framework method, but should not override it.
+ *
+ * Clients may call this framework method, but should not override it.
+ *
+ * This method must be called before any of the dialog unit based conversion
+ * methods are called.
+ *
+ * The
+ * Within the dialog framework, all buttons are referred to by a button id.
+ * Various common buttons, like "OK", "Cancel", and "Finish", have pre-assigned
+ * button ids for convenience. If an application requires other dialog buttons,
+ * they should be assigned application-specific button ids counting up from
+ *
+ * Button label constants are also provided for the common buttons. JFace
+ * automatically localizes these strings to the current locale; that is,
+ *
+ * All margins, spacings, and sizes are given in "dialog units" (DLUs), where
+ * "dialog_error_image"
).
+ *
+ * @deprecated use
+ * dwt.widgets.Display.getSystemImage(DWT.ICON_ERROR)
+ */
+ public static const String DLG_IMG_ERROR = "dialog_error_image"; //$NON-NLS-1$
+
+ /**
+ * Image registry key for info image (value "dialog_info_image"
).
+ *
+ * @deprecated use
+ * dwt.widgets.Display.getSystemImage(DWT.ICON_INFORMATION)
+ */
+ public static const String DLG_IMG_INFO = "dialog_info_imageg"; //$NON-NLS-1$
+
+ /**
+ * Image registry key for question image (value
+ * "dialog_question_image"
).
+ *
+ * @deprecated dwt.widgets.Display.getSystemImage(DWT.ICON_QUESTION)
+ */
+ public static const String DLG_IMG_QUESTION = "dialog_question_image"; //$NON-NLS-1$
+
+ /**
+ * Image registry key for warning image (value
+ * "dialog_warning_image"
).
+ *
+ * @deprecated use
+ * dwt.widgets.Display.getSystemImage(DWT.ICON_WARNING)
+ */
+ public static const String DLG_IMG_WARNING = "dialog_warning_image"; //$NON-NLS-1$
+
+ /**
+ * Image registry key for info message image (value
+ * "dialog_messasge_info_image"
).
+ *
+ * @since 2.0
+ */
+ public static const String DLG_IMG_MESSAGE_INFO = "dialog_messasge_info_image"; //$NON-NLS-1$
+
+ /**
+ * Image registry key for info message image (value
+ * "dialog_messasge_warning_image"
).
+ *
+ * @since 2.0
+ */
+ public static const String DLG_IMG_MESSAGE_WARNING = "dialog_messasge_warning_image"; //$NON-NLS-1$
+
+ /**
+ * Image registry key for info message image (value
+ * "dialog_message_error_image"
).
+ *
+ * @since 2.0
+ */
+ public static const String DLG_IMG_MESSAGE_ERROR = "dialog_message_error_image"; //$NON-NLS-1$
+
+ /**
+ * Image registry key for help image (value
+ * "dialog_help_image"
).
+ *
+ * @since 3.2
+ */
+ public static const String DLG_IMG_HELP = "dialog_help_image"; //$NON-NLS-1$
+
+ /**
+ * The ellipsis is the string that is used to represent shortened text.
+ *
+ * @since 3.0
+ */
+ public static const String ELLIPSIS = "..."; //$NON-NLS-1$
+
+ /**
+ * The dialog settings key name for stored dialog x location.
+ *
+ * @since 3.2
+ */
+ private static const String DIALOG_ORIGIN_X = "DIALOG_X_ORIGIN"; //$NON-NLS-1$
+
+ /**
+ * The dialog settings key name for stored dialog y location.
+ *
+ * @since 3.2
+ */
+ private static const String DIALOG_ORIGIN_Y = "DIALOG_Y_ORIGIN"; //$NON-NLS-1$
+
+ /**
+ * The dialog settings key name for stored dialog width.
+ *
+ * @since 3.2
+ */
+ private static const String DIALOG_WIDTH = "DIALOG_WIDTH"; //$NON-NLS-1$
+
+ /**
+ * The dialog settings key name for stored dialog height.
+ *
+ * @since 3.2
+ */
+ private static const String DIALOG_HEIGHT = "DIALOG_HEIGHT"; //$NON-NLS-1$
+
+ /**
+ * The dialog settings key name for the font used when the dialog
+ * height and width was stored.
+ *
+ *@since 3.2
+ */
+ private static const String DIALOG_FONT_DATA = "DIALOG_FONT_NAME"; //$NON-NLS-1$
+
+ /**
+ * A value that can be used for stored dialog width or height that
+ * indicates that the default bounds should be used.
+ *
+ * @since 3.2
+ */
+ public static const int DIALOG_DEFAULT_BOUNDS = -1;
+
+ /**
+ * Constants that can be used for specifying the strategy for persisting
+ * dialog bounds. These constants represent bit masks that can be used
+ * together.
+ *
+ *@since 3.2
+ */
+
+ /**
+ * Persist the last location of the dialog.
+ * @since 3.2
+ */
+ public static const int DIALOG_PERSISTLOCATION = 0x0001;
+ /**
+ * Persist the last known size of the dialog.
+ * @since 3.2
+ */
+ public static const int DIALOG_PERSISTSIZE = 0x0002;
+
+ /**
+ * The dialog area; null
until dialog is layed out.
+ */
+ protected Control dialogArea;
+
+ /**
+ * The button bar; null
until dialog is layed out.
+ */
+ public Control buttonBar;
+
+ /**
+ * Collection of buttons created by the createButton
method.
+ */
+ private Button[int] buttons;
+
+ /**
+ * Font metrics to use for determining pixel sizes.
+ */
+ private FontMetrics fontMetrics;
+
+ /**
+ * Number of horizontal dialog units per character, value 4
.
+ */
+ private static const int HORIZONTAL_DIALOG_UNIT_PER_CHAR = 4;
+
+ /**
+ * Number of vertical dialog units per character, value 8
.
+ */
+ private static const int VERTICAL_DIALOG_UNITS_PER_CHAR = 8;
+
+ /**
+ * Returns the number of pixels corresponding to the height of the given
+ * number of characters.
+ * FontMetrics
parameter may be created in the
+ * following way:
+ * GC gc = new GC(control);
+ * gc.setFont(control.getFont());
+ * fontMetrics = gc.getFontMetrics();
+ * gc.dispose();
+ *
+ * FontMetrics
parameter may be created in the
+ * following way:
+ * GC gc = new GC(control);
+ * gc.setFont(control.getFont());
+ * fontMetrics = gc.getFontMetrics();
+ * gc.dispose();
+ *
+ * FontMetrics
parameter may be created in the
+ * following way:
+ * GC gc = new GC(control);
+ * gc.setFont(control.getFont());
+ * fontMetrics = gc.getFontMetrics();
+ * gc.dispose();
+ *
+ * FontMetrics
parameter may be created in the
+ * following way:
+ * GC gc = new GC(control);
+ * gc.setFont(control.getFont());
+ * fontMetrics = gc.getFontMetrics();
+ * gc.dispose();
+ *
+ * textValue
so that its width in
+ * pixels does not exceed the width of the given control. Overrides
+ * characters in the center of the original string with an ellipsis ("...")
+ * if necessary. If a null
value is given, null
+ * is returned.
+ *
+ * @param textValue
+ * the original string or null
+ * @param control
+ * the control the string will be displayed on
+ * @return the string to display, or null
if null was passed
+ * in
+ *
+ * @since 3.0
+ */
+ public static String shortenText(String textValue, Control control) {
+ if (textValue is null) {
+ return null;
+ }
+ GC gc = new GC(control);
+ int maxWidth = control.getBounds().width - 5;
+ int maxExtent = gc.textExtent(textValue).x;
+ if (maxExtent < maxWidth) {
+ gc.dispose();
+ return textValue;
+ }
+ int length = textValue.length;
+ int charsToClip = cast(int) Math.round(0.95f*length * (1 - (cast(float)maxWidth/maxExtent)));
+ int pivot = length / 2;
+ int start = pivot - (charsToClip/2);
+ int end = pivot + (charsToClip/2) + 1;
+ while (start >= 0 && end < length) {
+ String s1 = textValue.substring(0, start);
+ String s2 = textValue.substring(end, length);
+ String s = s1 ~ ELLIPSIS ~ s2;
+ int l = gc.textExtent(s).x;
+ if (l < maxWidth) {
+ gc.dispose();
+ return s;
+ }
+ start--;
+ end++;
+ }
+ gc.dispose();
+ return textValue;
+ }
+
+ /**
+ * Create a default instance of the blocked handler which does not do
+ * anything.
+ */
+ public static IDialogBlockedHandler blockedHandler;
+ static this(){
+ blockedHandler = new class IDialogBlockedHandler {
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.dialogs.IDialogBlockedHandler#clearBlocked()
+ */
+ public void clearBlocked() {
+ // No default behaviour
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.dialogs.IDialogBlockedHandler#showBlocked(dwtx.core.runtime.IProgressMonitor,
+ * dwtx.core.runtime.IStatus, java.lang.String)
+ */
+ public void showBlocked(IProgressMonitor blocking,
+ IStatus blockingStatus, String blockedName) {
+ // No default behaviour
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.dialogs.IDialogBlockedHandler#showBlocked(dwt.widgets.Shell,
+ * dwtx.core.runtime.IProgressMonitor,
+ * dwtx.core.runtime.IStatus, java.lang.String)
+ */
+ public void showBlocked(Shell parentShell, IProgressMonitor blocking,
+ IStatus blockingStatus, String blockedName) {
+ // No default behaviour
+ }
+ };
+ }
+
+ /**
+ * Creates a dialog instance. Note that the window will have no visual
+ * representation (no widgets) until it is told to open. By default,
+ * open
blocks for dialogs.
+ *
+ * @param parentShell
+ * the parent shell, or null
to create a top-level
+ * shell
+ */
+ protected this(Shell parentShell) {
+ this(new SameShellProvider(parentShell));
+ if (parentShell is null && Policy.DEBUG_DIALOG_NO_PARENT) {
+ Policy.getLog().log(
+ new Status(IStatus.INFO, Policy.JFACE, IStatus.INFO, this
+ .classinfo.name
+ ~ " created with no shell",//$NON-NLS-1$
+ new Exception( null, null )));
+ }
+ }
+
+ /**
+ * Creates a dialog with the given parent.
+ *
+ * @param parentShell
+ * object that returns the current parent shell
+ *
+ * @since 3.1
+ */
+ protected this(IShellProvider parentShell) {
+ super(parentShell);
+ setShellStyle(DWT.DIALOG_TRIM | DWT.APPLICATION_MODAL
+ | getDefaultOrientation());
+ setBlockOnOpen(true);
+ }
+
+ /**
+ * Notifies that this dialog's button with the given id has been pressed.
+ * Dialog
implementation of this framework method calls
+ * okPressed
if the ok button is the pressed, and
+ * cancelPressed
if the cancel button is the pressed. All
+ * other button presses are ignored. Subclasses may override to handle other
+ * buttons, but should call super.buttonPressed
if the
+ * default handling of the ok and cancel buttons is desired.
+ * IDialogConstants.*_ID
constants)
+ */
+ protected void buttonPressed(int buttonId) {
+ if (IDialogConstants.OK_ID is buttonId) {
+ okPressed();
+ } else if (IDialogConstants.CANCEL_ID is buttonId) {
+ cancelPressed();
+ }
+ }
+
+ /**
+ * Notifies that the cancel button of this dialog has been pressed.
+ * Dialog
implementation of this framework method sets
+ * this dialog's return code to Window.CANCEL
and closes the
+ * dialog. Subclasses may override if desired.
+ * initializeDialogUnits
+ * has been called.
+ * initializeDialogUnits
+ * has been called.
+ * initializeDialogUnits
+ * has been called.
+ * initializeDialogUnits
+ * has been called.
+ * Dialog
implementation of this framework method creates
+ * a standard push button, registers it for selection events including
+ * button presses, and registers default buttons with its shell. The button
+ * id is stored as the button's client data. If the button id is
+ * IDialogConstants.CANCEL_ID
, the new button will be
+ * accessible from getCancelButton()
. If the button id is
+ * IDialogConstants.OK_ID
, the new button will be accesible
+ * from getOKButton()
. Note that the parent's layout is
+ * assumed to be a GridLayout
and the number of columns in
+ * this layout is incremented. Subclasses may override.
+ * IDialogConstants.*_ID
+ * constants for standard dialog button ids)
+ * @param label
+ * the label from the button
+ * @param defaultButton
+ * true
if the button is to be the default button,
+ * and false
otherwise
+ *
+ * @return the new button
+ *
+ * @see #getCancelButton
+ * @see #getOKButton()
+ */
+ protected Button createButton(Composite parent, int id, String label,
+ bool defaultButton) {
+ // increment the number of columns in the button bar
+ (cast(GridLayout) parent.getLayout()).numColumns++;
+ Button button = new Button(parent, DWT.PUSH);
+ button.setText(label);
+ button.setFont(JFaceResources.getDialogFont());
+ button.setData(new ValueWrapperInt(id));
+ button.addSelectionListener(new class SelectionAdapter {
+ public void widgetSelected(SelectionEvent event) {
+ buttonPressed((cast(ValueWrapperInt) event.widget.getData()).value);
+ }
+ });
+ if (defaultButton) {
+ Shell shell = parent.getShell();
+ if (shell !is null) {
+ shell.setDefaultButton(button);
+ }
+ }
+ buttons[id] = button;
+ setButtonLayoutData(button);
+ return button;
+ }
+
+ /**
+ * Creates and returns the contents of this dialog's button bar.
+ * Dialog
implementation of this framework method lays
+ * out a button bar and calls the createButtonsForButtonBar
+ * framework method to populate it. Subclasses may override.
+ * GridData
.
+ * Dialog
implementation of this framework method adds
+ * standard ok and cancel buttons using the createButton
+ * framework method. These standard buttons will be accessible from
+ * getCancelButton
, and getOKButton
.
+ * Subclasses may override.
+ * true
if control is a child of container
+ */
+ private bool isContained(Control container, Control control) {
+ Composite parent;
+ while ((parent = control.getParent()) !is null) {
+ if (parent is container) {
+ return true;
+ }
+ control = parent;
+ }
+ return false;
+ }
+
+ /**
+ * The Dialog
implementation of this Window
+ * method creates and lays out the top level composite for the dialog, and
+ * determines the appropriate horizontal and vertical dialog units based on
+ * the font size. It then calls the createDialogArea
and
+ * createButtonBar
methods to create the dialog area and
+ * button bar, respectively. Overriding createDialogArea
and
+ * createButtonBar
are recommended rather than overriding
+ * this method.
+ */
+ protected Control createContents(Composite parent) {
+ // create the top level composite for the dialog
+ Composite composite = new Composite(parent, 0);
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ layout.verticalSpacing = 0;
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ applyDialogFont(composite);
+ // initialize the dialog units
+ initializeDialogUnits(composite);
+ // create the dialog area and button bar
+ dialogArea = createDialogArea(composite);
+ buttonBar = createButtonBar(composite);
+
+ return composite;
+ }
+
+ /**
+ * Creates and returns the contents of the upper part of this dialog (above
+ * the button bar).
+ * Dialog
implementation of this framework method creates
+ * and returns a new Composite
with standard margins and
+ * spacing.
+ * GridData
. This method must not modify the parent's
+ * layout.
+ * super
as
+ * in the following example:
+ *
+ * Composite composite = (Composite) super.createDialogArea(parent);
+ * //add controls to composite as necessary
+ * return composite;
+ *
+ *
+ * @param parent
+ * the parent composite to contain the dialog area
+ * @return the dialog area control
+ */
+ protected Control createDialogArea(Composite parent) {
+ // create a composite with standard margins and spacing
+ Composite composite = new Composite(parent, DWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
+ layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
+ layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
+ layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(GridData.FILL_BOTH));
+ applyDialogFont(composite);
+ return composite;
+ }
+
+ /**
+ * Returns the button created by the method createButton
for
+ * the specified ID as defined on IDialogConstants
. If
+ * createButton
was never called with this ID, or if
+ * createButton
is overridden, this method will return
+ * null
.
+ *
+ * @param id
+ * the id of the button to look for
+ *
+ * @return the button for the ID or null
+ *
+ * @see #createButton(Composite, int, String, bool)
+ * @since 2.0
+ */
+ protected Button getButton(int id) {
+ return buttons[id];
+ }
+
+ /**
+ * Returns the button bar control.
+ * null
if the button bar has not
+ * been created yet
+ */
+ protected Control getButtonBar() {
+ return buttonBar;
+ }
+
+ /**
+ * Returns the button created when createButton
is called
+ * with an ID of IDialogConstants.CANCEL_ID
. If
+ * createButton
was never called with this parameter, or if
+ * createButton
is overridden, getCancelButton
+ * will return null
.
+ *
+ * @return the cancel button or null
+ *
+ * @see #createButton(Composite, int, String, bool)
+ * @since 2.0
+ * @deprecated Use getButton(IDialogConstants.CANCEL_ID)
+ * instead. This method will be removed soon.
+ */
+ protected Button getCancelButton() {
+ return getButton(IDialogConstants.CANCEL_ID);
+ }
+
+ /**
+ * Returns the dialog area control.
+ * null
if the dialog area has
+ * not been created yet
+ */
+ protected Control getDialogArea() {
+ return dialogArea;
+ }
+
+ /**
+ * Returns the standard dialog image with the given key. Note that these
+ * images are managed by the dialog framework, and must not be disposed by
+ * another party.
+ *
+ * @param key
+ * one of the Dialog.DLG_IMG_*
constants
+ * @return the standard dialog image
+ *
+ * NOTE: Dialog does not use the following images in the registry
+ * DLG_IMG_ERROR DLG_IMG_INFO DLG_IMG_QUESTION DLG_IMG_WARNING
+ *
+ * They are now coming directly from DWT, see ImageRegistry. For backwards
+ * compatibility they are still supported, however new code should use DWT
+ * for these.
+ *
+ * @see Display#getSystemImage(int)
+ */
+ public static Image getImage(String key) {
+ return JFaceResources.getImageRegistry().get(key);
+ }
+
+ /**
+ * Returns the button created when createButton
is called
+ * with an ID of IDialogConstants.OK_ID
. If
+ * createButton
was never called with this parameter, or if
+ * createButton
is overridden, getOKButton
+ * will return null
.
+ *
+ * @return the OK button or null
+ *
+ * @see #createButton(Composite, int, String, bool)
+ * @since 2.0
+ * @deprecated Use getButton(IDialogConstants.OK_ID)
instead.
+ * This method will be removed soon.
+ */
+ protected Button getOKButton() {
+ return getButton(IDialogConstants.OK_ID);
+ }
+
+ /**
+ * Initializes the computation of horizontal and vertical dialog units based
+ * on the size of current font.
+ * Dialog
implementation of this framework method sets
+ * this dialog's return code to Window.OK
and closes the
+ * dialog. Subclasses may override.
+ * null
nothing
+ * happens.
+ */
+ public static void applyDialogFont(Control control) {
+ if (control is null || dialogFontIsDefault()) {
+ return;
+ }
+ Font dialogFont = JFaceResources.getDialogFont();
+ applyDialogFont(control, dialogFont);
+ }
+
+ /**
+ * Sets the dialog font on the control and any of its children if thier font
+ * is not otherwise set.
+ *
+ * @param control
+ * the control to apply the font to. Font will also be applied to
+ * its children.
+ * @param dialogFont
+ * the dialog font to set
+ */
+ private static void applyDialogFont(Control control, Font dialogFont) {
+ if (hasDefaultFont(control)) {
+ control.setFont(dialogFont);
+ }
+ if ( auto comp = cast(Composite)control ) {
+ Control[] children = comp.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ applyDialogFont(children[i], dialogFont);
+ }
+ }
+ }
+
+ /**
+ * Return whether or not this control has the same font as it's default.
+ *
+ * @param control
+ * Control
+ * @return bool
+ */
+ private static bool hasDefaultFont(Control control) {
+ FontData[] controlFontData = control.getFont().getFontData();
+ FontData[] defaultFontData = getDefaultFont(control).getFontData();
+ if (controlFontData.length is defaultFontData.length) {
+ for (int i = 0; i < controlFontData.length; i++) {
+ if (controlFontData[i].opEquals(defaultFontData[i])) {
+ continue;
+ }
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Get the default font for this type of control.
+ *
+ * @param control
+ * @return the default font
+ */
+ private static Font getDefaultFont(Control control) {
+ String fontName = "DEFAULT_FONT_" ~ control.classinfo.name; //$NON-NLS-1$
+ if (JFaceResources.getFontRegistry().hasValueFor(fontName)) {
+ return JFaceResources.getFontRegistry().get(fontName);
+ }
+ Font cached = control.getFont();
+ control.setFont(null);
+ Font defaultFont = control.getFont();
+ control.setFont(cached);
+ JFaceResources.getFontRegistry().put(fontName,
+ defaultFont.getFontData());
+ return defaultFont;
+ }
+
+ /**
+ * Return whether or not the dialog font is currently the same as the
+ * default font.
+ *
+ * @return bool if the two are the same
+ */
+ protected static bool dialogFontIsDefault() {
+ FontData[] dialogFontData = JFaceResources.getFontRegistry()
+ .getFontData(JFaceResources.DIALOG_FONT);
+ FontData[] defaultFontData = JFaceResources.getFontRegistry()
+ .getFontData(JFaceResources.DEFAULT_FONT);
+ return ArrayEquals(dialogFontData, defaultFontData);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.window.Window#create()
+ */
+ public void create() {
+ super.create();
+ applyDialogFont(buttonBar);
+ }
+
+ /**
+ * Get the IDialogBlockedHandler to be used by WizardDialogs and
+ * ModalContexts.
+ *
+ * @return Returns the blockedHandler.
+ */
+ public static IDialogBlockedHandler getBlockedHandler() {
+ return blockedHandler;
+ }
+
+ /**
+ * Set the IDialogBlockedHandler to be used by WizardDialogs and
+ * ModalContexts.
+ *
+ * @param blockedHandler
+ * The blockedHandler for the dialogs.
+ */
+ public static void setBlockedHandler(IDialogBlockedHandler blockedHandler) {
+ Dialog.blockedHandler = blockedHandler;
+ }
+
+ /**
+ * Gets the dialog settings that should be used for remembering the bounds of
+ * of the dialog, according to the dialog bounds strategy.
+ *
+ * @return settings the dialog settings used to store the dialog's location
+ * and/or size, or null
if the dialog's bounds should
+ * never be stored.
+ *
+ * @since 3.2
+ * @see Dialog#getDialogBoundsStrategy()
+ */
+ protected IDialogSettings getDialogBoundsSettings() {
+ return null;
+ }
+
+ /**
+ * Get the integer constant that describes the strategy for persisting the
+ * dialog bounds. This strategy is ignored if the implementer does not also
+ * specify the dialog settings for storing the bounds in
+ * Dialog.getDialogBoundsSettings().
+ *
+ * @return the constant describing the strategy for persisting the dialog
+ * bounds.
+ *
+ * @since 3.2
+ * @see Dialog#DIALOG_PERSISTLOCATION
+ * @see Dialog#DIALOG_PERSISTSIZE
+ * @see Dialog#getDialogBoundsSettings()
+ */
+ protected int getDialogBoundsStrategy() {
+ return DIALOG_PERSISTLOCATION | DIALOG_PERSISTSIZE;
+ }
+
+ /**
+ * Saves the bounds of the shell in the appropriate dialog settings. The
+ * bounds are recorded relative to the parent shell, if there is one, or
+ * display coordinates if there is no parent shell.
+ *
+ * @param shell
+ * The shell whose bounds are to be stored
+ *
+ * @since 3.2
+ */
+ private void saveDialogBounds(Shell shell) {
+ IDialogSettings settings = getDialogBoundsSettings();
+ if (settings !is null) {
+ Point shellLocation = shell.getLocation();
+ Point shellSize = shell.getSize();
+ Shell parent = getParentShell();
+ if (parent !is null) {
+ Point parentLocation = parent.getLocation();
+ shellLocation.x -= parentLocation.x;
+ shellLocation.y -= parentLocation.y;
+ }
+ int strategy = getDialogBoundsStrategy();
+ if ((strategy & DIALOG_PERSISTLOCATION) !is 0) {
+ settings.put(DIALOG_ORIGIN_X, shellLocation.x);
+ settings.put(DIALOG_ORIGIN_Y, shellLocation.y);
+ }
+ if ((strategy & DIALOG_PERSISTSIZE) !is 0) {
+ settings.put(DIALOG_WIDTH, shellSize.x);
+ settings.put(DIALOG_HEIGHT, shellSize.y);
+ FontData [] fontDatas = JFaceResources.getDialogFont().getFontData();
+ if (fontDatas.length > 0) {
+ settings.put(DIALOG_FONT_DATA, fontDatas[0].toString());
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the initial size to use for the shell. Overridden
+ * to check whether a size has been stored in dialog settings.
+ * If a size has been stored, it is returned.
+ *
+ * @return the initial size of the shell
+ *
+ * @since 3.2
+ * @see #getDialogBoundsSettings()
+ * @see #getDialogBoundsStrategy()
+ */
+ protected Point getInitialSize() {
+ Point result = super.getInitialSize();
+
+ // Check the dialog settings for a stored size.
+ if ((getDialogBoundsStrategy() & DIALOG_PERSISTSIZE)!is 0) {
+ IDialogSettings settings = getDialogBoundsSettings();
+ if (settings !is null) {
+ // Check that the dialog font matches the font used
+ // when the bounds was stored. If the font has changed,
+ // we do not honor the stored settings.
+ // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=132821
+ bool useStoredBounds = true;
+ String previousDialogFontData = settings.get(DIALOG_FONT_DATA);
+ // There is a previously stored font, so we will check it.
+ // Note that if we haven't stored the font before, then we will
+ // use the stored bounds. This allows restoring of dialog bounds
+ // that were stored before we started storing the fontdata.
+ if (previousDialogFontData !is null && previousDialogFontData.length > 0) {
+ FontData [] fontDatas = JFaceResources.getDialogFont().getFontData();
+ if (fontDatas.length > 0) {
+ String currentDialogFontData = fontDatas[0].toString();
+ useStoredBounds = currentDialogFontData.equalsIgnoreCase(previousDialogFontData);
+ }
+ }
+ if (useStoredBounds) {
+ try {
+ // Get the stored width and height.
+ int width = settings.getInt(DIALOG_WIDTH);
+ if (width !is DIALOG_DEFAULT_BOUNDS) {
+ result.x = width;
+ }
+ int height = settings.getInt(DIALOG_HEIGHT);
+ if (height !is DIALOG_DEFAULT_BOUNDS) {
+ result.y = height;
+ }
+
+ } catch (NumberFormatException e) {
+ }
+ }
+ }
+ }
+ // No attempt is made to constrain the bounds. The default
+ // constraining behavior in Window will be used.
+ return result;
+ }
+
+ /**
+ * Returns the initial location to use for the shell. Overridden
+ * to check whether the bounds of the dialog have been stored in
+ * dialog settings. If a location has been stored, it is returned.
+ *
+ * @param initialSize
+ * the initial size of the shell, as returned by
+ * getInitialSize
.
+ * @return the initial location of the shell
+ *
+ * @since 3.2
+ * @see #getDialogBoundsSettings()
+ * @see #getDialogBoundsStrategy()
+ */
+ protected Point getInitialLocation(Point initialSize) {
+ Point result = super.getInitialLocation(initialSize);
+ if ((getDialogBoundsStrategy() & DIALOG_PERSISTLOCATION)!is 0) {
+ IDialogSettings settings = getDialogBoundsSettings();
+ if (settings !is null) {
+ try {
+ int x = settings.getInt(DIALOG_ORIGIN_X);
+ int y = settings.getInt(DIALOG_ORIGIN_Y);
+ result = new Point(x, y);
+ // The coordinates were stored relative to the parent shell.
+ // Convert to display coordinates.
+ Shell parent = getParentShell();
+ if (parent !is null) {
+ Point parentLocation = parent.getLocation();
+ result.x += parentLocation.x;
+ result.y += parentLocation.y;
+ }
+ } catch (NumberFormatException e) {
+ }
+ }
+ }
+ // No attempt is made to constrain the bounds. The default
+ // constraining behavior in Window will be used.
+ return result;
+ }
+
+}
diff -r 8a302fdb4140 -r a3ff22a98bef dwtx/jface/dialogs/IDialogBlockedHandler.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/dialogs/IDialogBlockedHandler.d Sat Mar 29 01:25:27 2008 +0100
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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
+ * Port to the D programming language:
+ * Frank Benoit null
the behavior will be the same as
+ * IDialogBlockedHandler#showBlocked(IProgressMonitor, IStatus, String)
+ *
+ * @param blocking The monitor to forward to. This is most
+ * important for calls to cancel()
.
+ * @param blockingStatus The status that describes the blockage
+ * @param blockedName The name of the locked operation.
+ * @see IDialogBlockedHandler#showBlocked(IProgressMonitor, IStatus, String)
+ */
+ public void showBlocked(Shell parentShell, IProgressMonitor blocking,
+ IStatus blockingStatus, String blockedName);
+
+ /**
+ * A blockage has occured. Show the blockage when there is
+ * no longer any modal shells in the UI and forward any actions
+ * to blockingMonitor.
+ *
+ * NOTE: As no shell has been specified this method will
+ * not open any blocked notification until all other modal shells
+ * have been closed.
+ *
+ * @param blocking The monitor to forward to. This is most
+ * important for calls to cancel()
.
+ * @param blockingStatus The status that describes the blockage
+ * @param blockedName The name of the locked operation.
+ */
+ public void showBlocked(IProgressMonitor blocking, IStatus blockingStatus,
+ String blockedName);
+}
diff -r 8a302fdb4140 -r a3ff22a98bef dwtx/jface/dialogs/IDialogConstants.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/dialogs/IDialogConstants.d Sat Mar 29 01:25:27 2008 +0100
@@ -0,0 +1,371 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2006 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
+ * Port to the D programming language:
+ * Frank Benoit CLIENT_ID
.
+ * YES_LABEL
would be bound to the string "Si"
in
+ * a Spanish locale, but to "Oui"
in a French one.
+ *
+ *
+ *
null
if none
+ */
+ public String get(String key);
+
+ /**
+ * Returns the value, an array of strings, of the given key in this dialog
+ * settings.
+ *
+ * @param key
+ * the key
+ * @return the array of string, or null
if none
+ */
+ public String[] getArray(String key);
+
+ /**
+ * Convenience API. Convert the value of the given key in this dialog
+ * settings to a bool and return it.
+ *
+ * @param key
+ * the key
+ * @return the bool value, or false
if none
+ */
+ public bool getBoolean(String key);
+
+ /**
+ * Convenience API. Convert the value of the given key in this dialog
+ * settings to a double and return it.
+ *
+ * @param key
+ * the key
+ * @return the value coverted to double, or throws
+ * NumberFormatException
if none
+ *
+ * @exception NumberFormatException
+ * if the string value does not contain a parsable number.
+ * @see java.lang.Double#valueOf(java.lang.String)
+ */
+ public double getDouble(String key);
+
+ /**
+ * Convenience API. Convert the value of the given key in this dialog
+ * settings to a float and return it.
+ *
+ * @param key
+ * the key
+ * @return the value coverted to float, or throws
+ * NumberFormatException
if none
+ *
+ * @exception NumberFormatException
+ * if the string value does not contain a parsable number.
+ * @see java.lang.Float#valueOf(java.lang.String)
+ */
+ public float getFloat(String key);
+
+ /**
+ * Convenience API. Convert the value of the given key in this dialog
+ * settings to a int and return it.
+ *
+ * @param key
+ * the key
+ * @return the value coverted to int, or throws
+ * NumberFormatException
if none
+ *
+ * @exception NumberFormatException
+ * if the string value does not contain a parsable number.
+ * @see java.lang.Integer#valueOf(java.lang.String)
+ */
+ public int getInt(String key);
+
+ /**
+ * Convenience API. Convert the value of the given key in this dialog
+ * settings to a long and return it.
+ *
+ * @param key
+ * the key
+ * @return the value coverted to long, or throws
+ * NumberFormatException
if none
+ *
+ * @exception NumberFormatException
+ * if the string value does not contain a parsable number.
+ * @see java.lang.Long#valueOf(java.lang.String)
+ */
+ public long getLong(String key);
+
+ /**
+ * Returns the IDialogSettings name.
+ *
+ * @return the name
+ */
+ public String getName();
+
+ /**
+ * Returns the section with the given name in this dialog settings.
+ *
+ * @param sectionName
+ * the key
+ * @return IDialogSettings (the section), or null
if none
+ */
+ public IDialogSettings getSection(String sectionName);
+
+ /**
+ * Returns all the sections in this dialog settings.
+ *
+ * @return the section, or null
if none
+ */
+ public IDialogSettings[] getSections();
+
+ /**
+ * Load a dialog settings from a stream and fill the receiver with its
+ * content.
+ *
+ * @param reader
+ * a Reader specifying the stream where the settings are read
+ * from.
+ * @throws IOException
+ */
+ public void load(Reader reader);
+
+ /**
+ * Load a dialog settings from a file and fill the receiver with its
+ * content.
+ *
+ * @param fileName
+ * the name of the file the settings are read from.
+ * @throws IOException
+ */
+ public void load(String fileName);
+
+ /**
+ * Adds the pair key/value
to this dialog settings.
+ *
+ * @param key
+ * the key.
+ * @param value
+ * the value to be associated with the key
+ */
+ public void put(String key, String[] value);
+
+ /**
+ * Convenience API. Converts the double value
to a string and
+ * adds the pair key/value
to this dialog settings.
+ *
+ * @param key
+ * the key.
+ * @param value
+ * the value to be associated with the key
+ */
+ public void put(String key, double value);
+
+ /**
+ * Convenience API. Converts the float value
to a string and
+ * adds the pair key/value
to this dialog settings.
+ *
+ * @param key
+ * the key.
+ * @param value
+ * the value to be associated with the key
+ */
+ public void put(String key, float value);
+
+ /**
+ * Convenience API. Converts the int value
to a string and
+ * adds the pair key/value
to this dialog settings.
+ *
+ * @param key
+ * the key.
+ * @param value
+ * the value to be associated with the key
+ */
+ public void put(String key, int value);
+
+ /**
+ * Convenience API. Converts the long value
to a string and
+ * adds the pair key/value
to this dialog settings.
+ *
+ * @param key
+ * the key.
+ * @param value
+ * the value to be associated with the key
+ */
+ public void put(String key, long value);
+
+ /**
+ * Adds the pair key/value
to this dialog settings.
+ *
+ * @param key
+ * the key.
+ * @param value
+ * the value to be associated with the key
+ */
+ public void put(String key, String value);
+
+ /**
+ * Convenience API. Converts the bool value
to a string
+ * and adds the pair key/value
to this dialog settings.
+ *
+ * @param key
+ * the key.
+ * @param value
+ * the value to be associated with the key
+ */
+ public void put(String key, bool value);
+
+ /**
+ * Save a dialog settings to a stream
+ *
+ * @param writer
+ * a Writer specifying the stream the settings are written in.
+ * @throws IOException
+ */
+ public void save(Writer writer);
+
+ /**
+ * Save a dialog settings to a file.
+ *
+ * @param fileName
+ * the name of the file the settings are written in.
+ * @throws IOException
+ */
+ public void save(String fileName);
+}
diff -r 8a302fdb4140 -r a3ff22a98bef dwtx/jface/resource/ColorDescriptor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/resource/ColorDescriptor.d Sat Mar 29 01:25:27 2008 +0100
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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
+ * Port to the D programming language:
+ * Frank Benoit + * An image registry owns all of the image objects registered + * with it, and automatically disposes of them when the DWT Display + * that creates the images is disposed. Because of this, clients do not + * need to (indeed, must not attempt to) dispose of these images themselves. + *
+ *+ * Clients may instantiate this class (it was not designed to be subclassed). + *
+ *+ * Unlike the FontRegistry, it is an error to replace images. As a result + * there are no events that fire when values are changed in the registry + *
+ */ +public class ImageRegistry { + /** + * display used when getting images + */ + private Display display; + + private ResourceManager manager; + + private Map!(String,Entry) table; + + private Runnable disposeRunnable; + private void init_disposeRunnable(){ + disposeRunnable = new class Runnable { + public void run() { + dispose(); + } + }; + } + + /** + * Contains the data for an entry in the registry. + */ + private static class Entry { + /** the image */ + protected Image image; + + /** the descriptor */ + protected ImageDescriptor descriptor; + } + + private static class OriginalImageDescriptor : ImageDescriptor { + private Image original; + private int refCount = 0; + private Device originalDisplay; + + /** + * @param original the original image + * @param originalDisplay the device the image is part of + */ + public this(Image original, Device originalDisplay) { + this.original = original; + this.originalDisplay = originalDisplay; + } + + public Object createResource(Device device) { + if (device is originalDisplay) { + refCount++; + return original; + } + return super.createResource(device); + } + + public void destroyResource(Object toDispose) { + if (original is toDispose) { + refCount--; + if (refCount is 0) { + original.dispose(); + original = null; + } + } else { + super.destroyResource(toDispose); + } + } + + /* (non-Javadoc) + * @see dwtx.jface.resource.ImageDescriptor#getImageData() + */ + public ImageData getImageData() { + return original.getImageData(); + } + } + + /** + * Creates an empty image registry. + *+ * There must be an DWT Display created in the current + * thread before calling this method. + *
+ */ + public this() { + this(Display.getCurrent()); + } + + /** + * Creates an empty image registry using the given resource manager to allocate images. + * + * @param manager the resource manager used to allocate images + * + * @since 3.1 + */ + public this(ResourceManager manager) { + init_disposeRunnable(); + Assert.isNotNull(manager); + Device dev = manager.getDevice(); + if ( auto disp = cast(Display)dev ) { + this.display = disp; + } + this.manager = manager; + manager.disposeExec(disposeRunnable); + } + + /** + * Creates an empty image registry. + * + * @param display thisDisplay
must not be
+ * null
and must not be disposed in order
+ * to use this registry
+ */
+ public this(Display display) {
+ this(JFaceResources.getResources(display));
+ }
+
+ /**
+ * Returns the image associated with the given key in this registry,
+ * or null
if none.
+ *
+ * @param key the key
+ * @return the image, or null
if none
+ */
+ public Image get(String key) {
+
+ // can be null
+ if (key is null) {
+ return null;
+ }
+
+ if (display !is null) {
+ /**
+ * NOTE, for backwards compatibility the following images are supported
+ * here, they should never be disposed, hence we explicitly return them
+ * rather then registering images that DWT will dispose.
+ *
+ * Applications should go direclty to DWT for these icons.
+ *
+ * @see Display.getSystemIcon(int ID)
+ */
+ int swtKey = -1;
+ if (key.equals(Dialog.DLG_IMG_INFO)) {
+ swtKey = DWT.ICON_INFORMATION;
+ }
+ if (key.equals(Dialog.DLG_IMG_QUESTION)) {
+ swtKey = DWT.ICON_QUESTION;
+ }
+ if (key.equals(Dialog.DLG_IMG_WARNING)) {
+ swtKey = DWT.ICON_WARNING;
+ }
+ if (key.equals(Dialog.DLG_IMG_ERROR)) {
+ swtKey = DWT.ICON_ERROR;
+ }
+ // if we actually just want to return an DWT image do so without
+ // looking in the registry
+ if (swtKey !is -1) {
+ Image[1] image;
+ int id = swtKey;
+ display.syncExec(new class Runnable {
+ public void run() {
+ image[0] = display.getSystemImage(id);
+ }
+ });
+ return image[0];
+ }
+ }
+
+ Entry entry = getEntry(key);
+ if (entry is null) {
+ return null;
+ }
+
+ if (entry.image is null) {
+ entry.image = manager.createImageWithDefault(entry.descriptor);
+ }
+
+ return entry.image;
+ }
+
+ /**
+ * Returns the descriptor associated with the given key in this registry,
+ * or null
if none.
+ *
+ * @param key the key
+ * @return the descriptor, or null
if none
+ * @since 2.1
+ */
+ public ImageDescriptor getDescriptor(String key) {
+ Entry entry = getEntry(key);
+ if (entry is null) {
+ return null;
+ }
+
+ return entry.descriptor;
+ }
+
+ /**
+ * Adds (or replaces) an image descriptor to this registry. The first time
+ * this new entry is retrieved, the image descriptor's image will be computed
+ * (via ImageDescriptor.createImage) and remembered.
+ * This method replaces an existing image descriptor associated with the
+ * given key, but fails if there is a real image associated with it.
+ *
+ * @param key the key
+ * @param descriptor the ImageDescriptor
+ * @exception IllegalArgumentException if the key already exists
+ */
+ public void put(String key, ImageDescriptor descriptor) {
+ Entry entry = getEntry(key);
+ if (entry is null) {
+ entry = new Entry();
+ getTable().add(key, entry);
+ }
+
+ if (entry.image !is null) {
+ throw new IllegalArgumentException(
+ "ImageRegistry key already in use: " ~ key); //$NON-NLS-1$
+ }
+
+ entry.descriptor = descriptor;
+ }
+
+ /**
+ * Adds an image to this registry. This method fails if there
+ * is already an image or descriptor for the given key.
+ * + * Note that an image registry owns all of the image objects registered + * with it, and automatically disposes of them when the DWT Display is disposed. + * Because of this, clients must not register an image object + * that is managed by another object. + *
+ * + * @param key the key + * @param image the image, should not benull
+ * @exception IllegalArgumentException if the key already exists
+ */
+ public void put(String key, Image image) {
+ Entry entry = getEntry(key);
+
+ if (entry is null) {
+ entry = new Entry();
+ putEntry(key, entry);
+ }
+
+ if (entry.image !is null || entry.descriptor !is null) {
+ throw new IllegalArgumentException(
+ "ImageRegistry key already in use: " ~ key); //$NON-NLS-1$
+ }
+
+ // Should be checking for a null image here.
+ // Current behavior is that a null image won't be caught until dispose.
+ // See https://bugs.eclipse.org/bugs/show_bug.cgi?id=130315
+ entry.image = image;
+ entry.descriptor = new OriginalImageDescriptor(image, manager.getDevice());
+
+ try {
+ manager.create(entry.descriptor);
+ } catch (DeviceResourceException e) {
+ }
+ }
+
+ /**
+ * Removes an image from this registry.
+ * If an DWT image was allocated, it is disposed.
+ * This method has no effect if there is no image or descriptor for the given key.
+ * @param key the key
+ */
+ public void remove(String key) {
+ ImageDescriptor descriptor = getDescriptor(key);
+ if (descriptor !is null) {
+ manager.destroy(descriptor);
+ getTable().removeKey(key);
+ }
+ }
+
+ private Entry getEntry(String key) {
+ return cast(Entry) getTable().get(key);
+ }
+
+ private void putEntry(String key, Entry entry) {
+ getTable().add(key, entry);
+ }
+
+ private Map!(String,Entry) getTable() {
+ if (table is null) {
+ table = new HashMap!(String,Entry)/+(10)+/;
+ }
+ return table;
+ }
+
+ /**
+ * Disposes this image registry, disposing any images
+ * that were allocated for it, and clearing its entries.
+ *
+ * @since 3.1
+ */
+ public void dispose() {
+ manager.cancelDisposeExec(disposeRunnable);
+
+ if (table !is null) {
+ foreach( key,entry; table ){
+ if (entry.image !is null) {
+ manager.destroyImage(entry.descriptor);
+ }
+ }
+ table = null;
+ }
+ display = null;
+ }
+}
diff -r 8a302fdb4140 -r a3ff22a98bef dwtx/jface/resource/JFaceResources.d
--- a/dwtx/jface/resource/JFaceResources.d Fri Mar 28 23:32:40 2008 +0100
+++ b/dwtx/jface/resource/JFaceResources.d Sat Mar 29 01:25:27 2008 +0100
@@ -13,12 +13,21 @@
module dwtx.jface.resource.JFaceResources;
import dwtx.jface.resource.FontRegistry;
+import dwtx.jface.resource.ImageRegistry;
+import dwtx.jface.resource.ResourceManager;
+
+import dwt.graphics.Font;
+import dwt.widgets.Display;
import dwt.dwthelper.utils;
public class JFaceResources {
public static const String DEFAULT_FONT = "dwtx.jface.defaultfont"; //$NON-NLS-1$
+ public static final String DIALOG_FONT = "dwtx.jface.dialogfont"; //$NON-NLS-1$
public static FontRegistry getFontRegistry() ;
public static String getString(String key) ;
+ public static Font getDialogFont() ;
+ public static ImageRegistry getImageRegistry() ;
+ public static ResourceManager getResources(Display toQuery) ;
}
/++
import java.text.MessageFormat;
diff -r 8a302fdb4140 -r a3ff22a98bef dwtx/jface/resource/RGBColorDescriptor.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/resource/RGBColorDescriptor.d Sat Mar 29 01:25:27 2008 +0100
@@ -0,0 +1,102 @@
+/*******************************************************************************
+ * Copyright (c) 2004, 2006 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
+ * Port to the D programming language:
+ * Frank Benoit + * ResourceManager handles correct allocation and disposal of resources. It differs from + * the various JFace *Registry classes, which also map symbolic IDs onto resources. In + * general, you should use a *Registry class to map IDs onto descriptors, and use a + * ResourceManager to convert the descriptors into real Images/Fonts/etc. + *
+ * + * @since 3.1 + */ +public abstract class ResourceManager { + + /** + * List of Runnables scheduled to run when the ResourceManager is disposed. + * null if empty. + */ + private Seq!(Runnable) disposeExecs = null; + + /** + * Returns the Device for which this ResourceManager will create resources + * + * @since 3.1 + * + * @return the Device associated with this ResourceManager + */ + public abstract Device getDevice(); + + /** + * Returns the resource described by the given descriptor. If the resource already + * exists, the reference count is incremented and the exiting resource is returned. + * Otherwise, a new resource is allocated. Every call to this method should have + * a corresponding call to {@link #destroy(DeviceResourceDescriptor)}. + * + *If the resource is intended to live for entire lifetime of the resource manager, + * a subsequent call to {@link #destroy(DeviceResourceDescriptor)} may be omitted and the + * resource will be cleaned up when the resource manager is disposed. This pattern + * is useful for short-lived {@link LocalResourceManager}s, but should never be used + * with the global resource manager since doing so effectively leaks the resource.
+ * + *The resources returned from this method are reference counted and may be shared + * internally with other resource managers. They should never be disposed outside of the + * ResourceManager framework, or it will cause exceptions in other code that shares + * them. For example, never call {@link dwt.graphics.Resource#dispose()} + * on anything returned from this method.
+ * + *Callers may safely downcast the result to the resource type associated with + * the descriptor. For example, when given an ImageDescriptor, the return + * value of this method will always be an Image.
+ * + * @since 3.1 + * + * @param descriptor descriptor for the resource to allocate + * @return the newly allocated resource (not null) + * @throws DeviceResourceException if unable to allocate the resource + */ + public abstract Object create(DeviceResourceDescriptor descriptor); + + /** + * Deallocates a resource previously allocated by {@link #create(DeviceResourceDescriptor)}. + * Descriptors are compared by equality, not identity. If the same resource was + * created multiple times, this may decrement a reference count rather than + * disposing the actual resource. + * + * @since 3.1 + * + * @param descriptor identifier for the resource + */ + public abstract void destroy(DeviceResourceDescriptor descriptor); + + /** + *Returns a previously-allocated resource or allocates a new one if none + * exists yet. The resource will remain allocated for at least the lifetime + * of this resource manager. If necessary, the resource will be deallocated + * automatically when the resource manager is disposed.
+ * + *The resources returned from this method are reference counted and may be shared + * internally with other resource managers. They should never be disposed outside of the + * ResourceManager framework, or it will cause exceptions in other code that shares + * them. For example, never call {@link dwt.graphics.Resource#dispose()} + * on anything returned from this method.
+ * + *+ * Callers may safely downcast the result to the resource type associated with + * the descriptor. For example, when given an ImageDescriptor, the return + * value of this method may be downcast to Image. + *
+ * + *
+ * This method should only be used for resources that should remain
+ * allocated for the lifetime of the resource manager. To allocate shorter-lived
+ * resources, manage them with create
, and destroy
+ * rather than this method.
+ *
+ * This method should never be called on the global resource manager, + * since all resources will remain allocated for the lifetime of the app and + * will be effectively leaked. + *
+ * + * @param descriptor identifier for the requested resource + * @return the requested resource. Never null. + * @throws DeviceResourceException if the resource does not exist yet and cannot + * be created for any reason. + * + * @since 3.3 + */ + public final Object get(DeviceResourceDescriptor descriptor) { + Object result = find(descriptor); + + if (result is null) { + result = create(descriptor); + } + + return result; + } + + /** + *Creates an image, given an image descriptor. Images allocated in this manner must + * be disposed by {@link #destroyImage(ImageDescriptor)}, and never by calling + * {@link Image#dispose()}.
+ * + *+ * If the image is intended to remain allocated for the lifetime of the ResourceManager, + * the call to destroyImage may be omitted and the image will be cleaned up automatically + * when the ResourceManager is disposed. This should only be done with short-lived ResourceManagers, + * as doing so with the global manager effectively leaks the resource. + *
+ * + * @since 3.1 + * + * @param descriptor descriptor for the image to create + * @return the Image described by this descriptor (possibly shared by other equivalent + * ImageDescriptors) + * @throws DeviceResourceException if unable to allocate the Image + */ + public final Image createImage(ImageDescriptor descriptor) { + // Assertion added to help diagnose client bugs. See bug #83711 and bug #90454. + Assert.isNotNull(descriptor); + + return cast(Image)create(descriptor); + } + + /** + * Creates an image, given an image descriptor. Images allocated in this manner must + * be disposed by {@link #destroyImage(ImageDescriptor)}, and never by calling + * {@link Image#dispose()}. + * + * @since 3.1 + * + * @param descriptor descriptor for the image to create + * @return the Image described by this descriptor (possibly shared by other equivalent + * ImageDescriptors) + */ + public final Image createImageWithDefault(ImageDescriptor descriptor) { + if (descriptor is null) { + return getDefaultImage(); + } + + try { + return cast(Image) create(descriptor); + } catch (DeviceResourceException e) { + Policy.getLog().log( + new Status(IStatus.WARNING, "dwtx.jface", 0, //$NON-NLS-1$ + "The image could not be loaded: " ~ descriptor.toString, //$NON-NLS-1$ + e)); + return getDefaultImage(); + } catch (DWTException e) { + Policy.getLog().log( + new Status(IStatus.WARNING, "dwtx.jface", 0, //$NON-NLS-1$ + "The image could not be loaded: " ~ descriptor.toString, //$NON-NLS-1$ + e)); + return getDefaultImage(); + } + } + + /** + * Returns the default image that will be returned in the event that the intended + * image is missing. + * + * @since 3.1 + * + * @return a default image that will be returned in the event that the intended + * image is missing. + */ + protected abstract Image getDefaultImage(); + + /** + * Undoes everything that was done by {@link #createImage(ImageDescriptor)}. + * + * @since 3.1 + * + * @param descriptor identifier for the image to dispose + */ + public final void destroyImage(ImageDescriptor descriptor) { + destroy(descriptor); + } + + /** + * Allocates a color, given a color descriptor. Any color allocated in this + * manner must be disposed by calling {@link #destroyColor(ColorDescriptor)}, + * or by an eventual call to {@link #dispose()}. {@link Color#dispose()} must + * never been called directly on the returned color. + * + * @since 3.1 + * + * @param descriptor descriptor for the color to create + * @return the Color described by the given ColorDescriptor (not null) + * @throws DeviceResourceException if unable to create the color + */ + public final Color createColor(ColorDescriptor descriptor) { + return cast(Color)create(descriptor); + } + + /** + * Allocates a color, given its RGB value. Any color allocated in this + * manner must be disposed by calling {@link #destroyColor(RGB)}, + * or by an eventual call to {@link #dispose()}. {@link Color#dispose()} must + * never been called directly on the returned color. + * + * @since 3.1 + * + * @param descriptor descriptor for the color to create + * @return the Color described by the given ColorDescriptor (not null) + * @throws DeviceResourceException if unable to create the color + */ + public final Color createColor(RGB descriptor) { + return createColor(new RGBColorDescriptor(descriptor)); + } + + /** + * Undoes everything that was done by a call to {@link #createColor(RGB)}. + * + * @since 3.1 + * + * @param descriptor RGB value of the color to dispose + */ + public final void destroyColor(RGB descriptor) { + destroyColor(new RGBColorDescriptor(descriptor)); + } + + /** + * Undoes everything that was done by a call to {@link #createColor(ColorDescriptor)}. + * + * + * @since 3.1 + * + * @param descriptor identifier for the color to dispose + */ + public final void destroyColor(ColorDescriptor descriptor) { + destroy(descriptor); + } + + /** + * Returns the Font described by the given FontDescriptor. Any Font + * allocated in this manner must be deallocated by calling disposeFont(...), + * or by an eventual call to {@link #dispose()}. The method {@link Font#dispose()} + * must never be called directly on the returned font. + * + * @since 3.1 + * + * @param descriptor description of the font to create + * @return the Font described by the given descriptor + * @throws DeviceResourceException if unable to create the font + */ + public final Font createFont(FontDescriptor descriptor) { + return cast(Font)create(descriptor); + } + + /** + * Undoes everything that was done by a previous call to {@link #createFont(FontDescriptor)}. + * + * @since 3.1 + * + * @param descriptor description of the font to destroy + */ + public final void destroyFont(FontDescriptor descriptor) { + destroy(descriptor); + } + + /** + * Disposes any remaining resources allocated by this manager. + */ + public void dispose() { + if (disposeExecs is null) { + return; + } + + // If one of the runnables throws an exception, we need to propagate it. + // However, this should not prevent the remaining runnables from being + // notified. If any runnables throw an exception, we remember one of them + // here and throw it at the end of the method. + RuntimeException foundException = null; + + Runnable[] execs = disposeExecs.toArray(); + for (int i = 0; i < execs.length; i++) { + Runnable exec = execs[i]; + + try { + exec.run(); + } catch (RuntimeException e) { + // Ensure that we propagate an exception, but don't stop notifying + // the remaining runnables. + foundException = e; + } + } + + if (foundException !is null) { + // If any runnables threw an exception, propagate one of them. + throw foundException; + } + } + + /** + * Returns a previously allocated resource associated with the given descriptor, or + * null if none exists yet. + * + * @since 3.1 + * + * @param descriptor descriptor to find + * @return a previously allocated resource for the given descriptor or null if none. + */ + public abstract Object find(DeviceResourceDescriptor descriptor); + + /** + * Causes therun()
method of the runnable to
+ * be invoked just before the receiver is disposed. The runnable
+ * can be subsequently canceled by a call to cancelDisposeExec
.
+ *
+ * @param r runnable to execute.
+ */
+ public void disposeExec(Runnable r) {
+ Assert.isNotNull(cast(Object)r);
+
+ if (disposeExecs is null) {
+ disposeExecs = new ArraySeq!(Runnable);
+ }
+
+ disposeExecs.append(r);
+ }
+
+ /**
+ * Cancels a runnable that was previously scheduled with disposeExec
.
+ * Has no effect if the given runnable was not previously registered with
+ * disposeExec.
+ *
+ * @param r runnable to cancel
+ */
+ public void cancelDisposeExec(Runnable r) {
+ Assert.isNotNull(cast(Object)r);
+
+ if (disposeExecs is null) {
+ return;
+ }
+
+ disposeExecs.remove(r);
+
+ if (disposeExecs.drained()) {
+ disposeExecs = null;
+ }
+ }
+}
diff -r 8a302fdb4140 -r a3ff22a98bef dwtx/jface/wizard/WizardDialog.d
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/dwtx/jface/wizard/WizardDialog.d Sat Mar 29 01:25:27 2008 +0100
@@ -0,0 +1,1520 @@
+/*******************************************************************************
+ * Copyright (c) 2000, 2007 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
+ * Chris Gross (schtoo@schtoo.com) - patch for bug 16179
+ * Port to the D programming language:
+ * Frank Benoit + * In typical usage, the client instantiates this class with a particular + * wizard. The dialog serves as the wizard container and orchestrates the + * presentation of its pages. + *
+ * The standard layout is roughly as follows: it has an area at the top + * containing both the wizard's title, description, and image; the actual wizard + * page appears in the middle; below that is a progress indicator (which is made + * visible if needed); and at the bottom of the page is message line and a + * button bar containing Help, Next, Back, Finish, and Cancel buttons (or some + * subset). + *
+ *
+ * Clients may subclass WizardDialog
, although this is rarely
+ * required.
+ *
"dialog_title_error_image"
).
+ */
+ public static final String WIZ_IMG_ERROR = "dialog_title_error_image"; //$NON-NLS-1$
+
+ // The wizard the dialog is currently showing.
+ private IWizard wizard;
+
+ // Wizards to dispose
+ private ArrayList createdWizards = new ArrayList();
+
+ // Current nested wizards
+ private ArrayList nestedWizards = new ArrayList();
+
+ // The currently displayed page.
+ private IWizardPage currentPage = null;
+
+ // The number of long running operation executed from the dialog.
+ private long activeRunningOperations = 0;
+
+ // The current page message and description
+ private String pageMessage;
+
+ private int pageMessageType = IMessageProvider.NONE;
+
+ private String pageDescription;
+
+ // The progress monitor
+ private ProgressMonitorPart progressMonitorPart;
+
+ private Cursor waitCursor;
+
+ private Cursor arrowCursor;
+
+ private MessageDialog windowClosingDialog;
+
+ // Navigation buttons
+ private Button backButton;
+
+ private Button nextButton;
+
+ private Button finishButton;
+
+ private Button cancelButton;
+
+ private Button helpButton;
+
+ private SelectionAdapter cancelListener;
+
+ private bool isMovingToPreviousPage = false;
+
+ private Composite pageContainer;
+
+ private PageContainerFillLayout pageContainerLayout = new PageContainerFillLayout(
+ 5, 5, 300, 225);
+
+ private int pageWidth = DWT.DEFAULT;
+
+ private int pageHeight = DWT.DEFAULT;
+
+ private static final String FOCUS_CONTROL = "focusControl"; //$NON-NLS-1$
+
+ private bool lockedUI = false;
+
+ private ListenerList pageChangedListeners = new ListenerList();
+
+ private ListenerList pageChangingListeners = new ListenerList();
+
+ /**
+ * A layout for a container which includes several pages, like a notebook,
+ * wizard, or preference dialog. The size computed by this layout is the
+ * maximum width and height of all pages currently inserted into the
+ * container.
+ */
+ protected class PageContainerFillLayout extends Layout {
+ /**
+ * The margin width; 5
pixels by default.
+ */
+ public int marginWidth = 5;
+
+ /**
+ * The margin height; 5
pixels by default.
+ */
+ public int marginHeight = 5;
+
+ /**
+ * The minimum width; 0
pixels by default.
+ */
+ public int minimumWidth = 0;
+
+ /**
+ * The minimum height; 0
pixels by default.
+ */
+ public int minimumHeight = 0;
+
+ /**
+ * Creates new layout object.
+ *
+ * @param mw
+ * the margin width
+ * @param mh
+ * the margin height
+ * @param minW
+ * the minimum width
+ * @param minH
+ * the minimum height
+ */
+ public PageContainerFillLayout(int mw, int mh, int minW, int minH) {
+ marginWidth = mw;
+ marginHeight = mh;
+ minimumWidth = minW;
+ minimumHeight = minH;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on Layout.
+ */
+ public Point computeSize(Composite composite, int wHint, int hHint,
+ bool force) {
+ if (wHint !is DWT.DEFAULT && hHint !is DWT.DEFAULT) {
+ return new Point(wHint, hHint);
+ }
+ Point result = null;
+ Control[] children = composite.getChildren();
+ if (children.length > 0) {
+ result = new Point(0, 0);
+ for (int i = 0; i < children.length; i++) {
+ Point cp = children[i].computeSize(wHint, hHint, force);
+ result.x = Math.max(result.x, cp.x);
+ result.y = Math.max(result.y, cp.y);
+ }
+ result.x = result.x + 2 * marginWidth;
+ result.y = result.y + 2 * marginHeight;
+ } else {
+ Rectangle rect = composite.getClientArea();
+ result = new Point(rect.width, rect.height);
+ }
+ result.x = Math.max(result.x, minimumWidth);
+ result.y = Math.max(result.y, minimumHeight);
+ if (wHint !is DWT.DEFAULT) {
+ result.x = wHint;
+ }
+ if (hHint !is DWT.DEFAULT) {
+ result.y = hHint;
+ }
+ return result;
+ }
+
+ /**
+ * Returns the client area for the given composite according to this
+ * layout.
+ *
+ * @param c
+ * the composite
+ * @return the client area rectangle
+ */
+ public Rectangle getClientArea(Composite c) {
+ Rectangle rect = c.getClientArea();
+ rect.x = rect.x + marginWidth;
+ rect.y = rect.y + marginHeight;
+ rect.width = rect.width - 2 * marginWidth;
+ rect.height = rect.height - 2 * marginHeight;
+ return rect;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on Layout.
+ */
+ public void layout(Composite composite, bool force) {
+ Rectangle rect = getClientArea(composite);
+ Control[] children = composite.getChildren();
+ for (int i = 0; i < children.length; i++) {
+ children[i].setBounds(rect);
+ }
+ }
+
+ /**
+ * Lays outs the page according to this layout.
+ *
+ * @param w
+ * the control
+ */
+ public void layoutPage(Control w) {
+ w.setBounds(getClientArea(w.getParent()));
+ }
+
+ /**
+ * Sets the location of the page so that its origin is in the upper left
+ * corner.
+ *
+ * @param w
+ * the control
+ */
+ public void setPageLocation(Control w) {
+ w.setLocation(marginWidth, marginHeight);
+ }
+ }
+
+ /**
+ * Creates a new wizard dialog for the given wizard.
+ *
+ * @param parentShell
+ * the parent shell
+ * @param newWizard
+ * the wizard this dialog is working on
+ */
+ public WizardDialog(Shell parentShell, IWizard newWizard) {
+ super(parentShell);
+ setShellStyle(DWT.CLOSE | DWT.MAX | DWT.TITLE | DWT.BORDER
+ | DWT.APPLICATION_MODAL | DWT.RESIZE | getDefaultOrientation());
+ setWizard(newWizard);
+ // since VAJava can't initialize an instance var with an anonymous
+ // class outside a constructor we do it here:
+ cancelListener = new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ cancelPressed();
+ }
+ };
+ }
+
+ /**
+ * About to start a long running operation triggered through the wizard.
+ * Shows the progress monitor and disables the wizard's buttons and
+ * controls.
+ *
+ * @param enableCancelButton
+ * true
if the Cancel button should be enabled,
+ * and false
if it should be disabled
+ * @return the saved UI state
+ */
+ private Object aboutToStart(bool enableCancelButton) {
+ Map savedState = null;
+ if (getShell() !is null) {
+ // Save focus control
+ Control focusControl = getShell().getDisplay().getFocusControl();
+ if (focusControl !is null && focusControl.getShell() !is getShell()) {
+ focusControl = null;
+ }
+ bool needsProgressMonitor = wizard.needsProgressMonitor();
+ cancelButton.removeSelectionListener(cancelListener);
+ // Set the busy cursor to all shells.
+ Display d = getShell().getDisplay();
+ waitCursor = new Cursor(d, DWT.CURSOR_WAIT);
+ setDisplayCursor(waitCursor);
+ // Set the arrow cursor to the cancel component.
+ arrowCursor = new Cursor(d, DWT.CURSOR_ARROW);
+ cancelButton.setCursor(arrowCursor);
+ // Deactivate shell
+ savedState = saveUIState(needsProgressMonitor && enableCancelButton);
+ if (focusControl !is null) {
+ savedState.put(FOCUS_CONTROL, focusControl);
+ }
+ // Attach the progress monitor part to the cancel button
+ if (needsProgressMonitor) {
+ progressMonitorPart.attachToCancelComponent(cancelButton);
+ progressMonitorPart.setVisible(true);
+ }
+ }
+ return savedState;
+ }
+
+ /**
+ * The Back button has been pressed.
+ */
+ protected void backPressed() {
+ IWizardPage page = currentPage.getPreviousPage();
+ if (page is null) {
+ // should never happen since we have already visited the page
+ return;
+ }
+
+ // set flag to indicate that we are moving back
+ isMovingToPreviousPage = true;
+ // show the page
+ showPage(page);
+ }
+
+ /*
+ * (non-Javadoc) Method declared on Dialog.
+ */
+ protected void buttonPressed(int buttonId) {
+ switch (buttonId) {
+ case IDialogConstants.HELP_ID: {
+ helpPressed();
+ break;
+ }
+ case IDialogConstants.BACK_ID: {
+ backPressed();
+ break;
+ }
+ case IDialogConstants.NEXT_ID: {
+ nextPressed();
+ break;
+ }
+ case IDialogConstants.FINISH_ID: {
+ finishPressed();
+ break;
+ }
+ // The Cancel button has a listener which calls cancelPressed
+ // directly
+ }
+ }
+
+ /**
+ * Calculates the difference in size between the given page and the page
+ * container. A larger page results in a positive delta.
+ *
+ * @param page
+ * the page
+ * @return the size difference encoded as a
+ * new Point(deltaWidth,deltaHeight)
+ */
+ private Point calculatePageSizeDelta(IWizardPage page) {
+ Control pageControl = page.getControl();
+ if (pageControl is null) {
+ // control not created yet
+ return new Point(0, 0);
+ }
+ Point contentSize = pageControl.computeSize(DWT.DEFAULT, DWT.DEFAULT,
+ true);
+ Rectangle rect = pageContainerLayout.getClientArea(pageContainer);
+ Point containerSize = new Point(rect.width, rect.height);
+ return new Point(Math.max(0, contentSize.x - containerSize.x), Math
+ .max(0, contentSize.y - containerSize.y));
+ }
+
+ /*
+ * (non-Javadoc) Method declared on Dialog.
+ */
+ protected void cancelPressed() {
+ if (activeRunningOperations <= 0) {
+ // Close the dialog. The check whether the dialog can be
+ // closed or not is done in okToClose
.
+ // This ensures that the check is also evaluated when the user
+ // presses the window's close button.
+ setReturnCode(CANCEL);
+ close();
+ } else {
+ cancelButton.setEnabled(false);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.window.Window#close()
+ */
+ public bool close() {
+ if (okToClose()) {
+ return hardClose();
+ }
+ return false;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on Window.
+ */
+ protected void configureShell(Shell newShell) {
+ super.configureShell(newShell);
+ // Register help listener on the shell
+ newShell.addHelpListener(new HelpListener() {
+ public void helpRequested(HelpEvent event) {
+ // call perform help on the current page
+ if (currentPage !is null) {
+ currentPage.performHelp();
+ }
+ }
+ });
+ }
+
+ /**
+ * Creates the buttons for this dialog's button bar.
+ *
+ * The WizardDialog
implementation of this framework method
+ * prevents the parent composite's columns from being made equal width in
+ * order to remove the margin between the Back and Next buttons.
+ *
DWT.PUSH
)
+ * button and registers for its selection events. Note that the number of
+ * columns in the button bar composite is incremented. The Cancel button is
+ * created specially to give it a removeable listener.
+ *
+ * @param parent
+ * the parent button bar
+ * @return the new Cancel button
+ */
+ private Button createCancelButton(Composite parent) {
+ // increment the number of columns in the button bar
+ ((GridLayout) parent.getLayout()).numColumns++;
+ Button button = new Button(parent, DWT.PUSH);
+ button.setText(IDialogConstants.CANCEL_LABEL);
+ setButtonLayoutData(button);
+ button.setFont(parent.getFont());
+ button.setData(new Integer(IDialogConstants.CANCEL_ID));
+ button.addSelectionListener(cancelListener);
+ return button;
+ }
+
+ /**
+ * Return the cancel button if the id is a the cancel id.
+ *
+ * @param id
+ * the button id
+ * @return the button corresponding to the button id
+ */
+ protected Button getButton(int id) {
+ if (id is IDialogConstants.CANCEL_ID) {
+ return cancelButton;
+ }
+ return super.getButton(id);
+ }
+
+ /**
+ * The WizardDialog
implementation of this
+ * Window
method calls call IWizard.addPages
+ * to allow the current wizard to add extra pages, then
+ * super.createContents
to create the controls. It then calls
+ * IWizard.createPageControls
to allow the wizard to
+ * pre-create their page controls prior to opening, so that the wizard opens
+ * to the correct size. And finally it shows the first page.
+ */
+ protected Control createContents(Composite parent) {
+ // Allow the wizard to add pages to itself
+ // Need to call this now so page count is correct
+ // for determining if next/previous buttons are needed
+ wizard.addPages();
+ Control contents = super.createContents(parent);
+ // Allow the wizard pages to precreate their page controls
+ createPageControls();
+ // Show the first page
+ showStartingPage();
+ return contents;
+ }
+
+ /*
+ * (non-Javadoc) Method declared on Dialog.
+ */
+ protected Control createDialogArea(Composite parent) {
+ Composite composite = (Composite) super.createDialogArea(parent);
+ // Build the Page container
+ pageContainer = createPageContainer(composite);
+ GridData gd = new GridData(GridData.FILL_BOTH);
+ gd.widthHint = pageWidth;
+ gd.heightHint = pageHeight;
+ pageContainer.setLayoutData(gd);
+ pageContainer.setFont(parent.getFont());
+ // Insert a progress monitor
+ GridLayout pmlayout = new GridLayout();
+ pmlayout.numColumns = 1;
+ progressMonitorPart = createProgressMonitorPart(composite, pmlayout);
+ GridData gridData = new GridData(GridData.FILL_HORIZONTAL);
+ progressMonitorPart.setLayoutData(gridData);
+ progressMonitorPart.setVisible(false);
+ // Build the separator line
+ Label separator = new Label(composite, DWT.HORIZONTAL | DWT.SEPARATOR);
+ separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
+
+ applyDialogFont(progressMonitorPart);
+ return composite;
+ }
+
+ /**
+ * Create the progress monitor part in the receiver.
+ *
+ * @param composite
+ * @param pmlayout
+ * @return ProgressMonitorPart
+ */
+ protected ProgressMonitorPart createProgressMonitorPart(
+ Composite composite, GridLayout pmlayout) {
+ return new ProgressMonitorPart(composite, pmlayout, DWT.DEFAULT) {
+ String currentTask = null;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.wizard.ProgressMonitorPart#setBlocked(dwtx.core.runtime.IStatus)
+ */
+ public void setBlocked(IStatus reason) {
+ super.setBlocked(reason);
+ if (!lockedUI) {
+ getBlockedHandler().showBlocked(getShell(), this, reason,
+ currentTask);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.wizard.ProgressMonitorPart#clearBlocked()
+ */
+ public void clearBlocked() {
+ super.clearBlocked();
+ if (!lockedUI) {
+ getBlockedHandler().clearBlocked();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.wizard.ProgressMonitorPart#beginTask(java.lang.String,
+ * int)
+ */
+ public void beginTask(String name, int totalWork) {
+ super.beginTask(name, totalWork);
+ currentTask = name;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.wizard.ProgressMonitorPart#setTaskName(java.lang.String)
+ */
+ public void setTaskName(String name) {
+ super.setTaskName(name);
+ currentTask = name;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see dwtx.jface.wizard.ProgressMonitorPart#subTask(java.lang.String)
+ */
+ public void subTask(String name) {
+ super.subTask(name);
+ // If we haven't got anything yet use this value for more
+ // context
+ if (currentTask is null) {
+ currentTask = name;
+ }
+ }
+ };
+ }
+
+ /**
+ * Creates the container that holds all pages.
+ *
+ * @param parent
+ * @return Composite
+ */
+ private Composite createPageContainer(Composite parent) {
+ Composite result = new Composite(parent, DWT.NULL);
+ result.setLayout(pageContainerLayout);
+ return result;
+ }
+
+ /**
+ * Allow the wizard's pages to pre-create their page controls. This allows
+ * the wizard dialog to open to the correct size.
+ */
+ private void createPageControls() {
+ // Allow the wizard pages to precreate their page controls
+ // This allows the wizard to open to the correct size
+ wizard.createPageControls(pageContainer);
+ // Ensure that all of the created pages are initially not visible
+ IWizardPage[] pages = wizard.getPages();
+ for (int i = 0; i < pages.length; i++) {
+ IWizardPage page = pages[i];
+ if (page.getControl() !is null) {
+ page.getControl().setVisible(false);
+ }
+ }
+ }
+
+ /**
+ * Creates the Previous and Next buttons for this wizard dialog. Creates
+ * standard (DWT.PUSH
) buttons and registers for their
+ * selection events. Note that the number of columns in the button bar
+ * composite is incremented. These buttons are created specially to prevent
+ * any space between them.
+ *
+ * @param parent
+ * the parent button bar
+ * @return a composite containing the new buttons
+ */
+ private Composite createPreviousAndNextButtons(Composite parent) {
+ // increment the number of columns in the button bar
+ ((GridLayout) parent.getLayout()).numColumns++;
+ Composite composite = new Composite(parent, DWT.NONE);
+ // create a layout with spacing and margins appropriate for the font
+ // size.
+ GridLayout layout = new GridLayout();
+ layout.numColumns = 0; // will be incremented by createButton
+ layout.marginWidth = 0;
+ layout.marginHeight = 0;
+ layout.horizontalSpacing = 0;
+ layout.verticalSpacing = 0;
+ composite.setLayout(layout);
+ GridData data = new GridData(GridData.HORIZONTAL_ALIGN_CENTER
+ | GridData.VERTICAL_ALIGN_CENTER);
+ composite.setLayoutData(data);
+ composite.setFont(parent.getFont());
+ backButton = createButton(composite, IDialogConstants.BACK_ID,
+ IDialogConstants.BACK_LABEL, false);
+ nextButton = createButton(composite, IDialogConstants.NEXT_ID,
+ IDialogConstants.NEXT_LABEL, false);
+ return composite;
+ }
+
+ /**
+ * Creates and return a new wizard closing dialog without openiong it.
+ *
+ * @return MessageDalog
+ */
+ private MessageDialog createWizardClosingDialog() {
+ MessageDialog result = new MessageDialog(getShell(),
+ JFaceResources.getString("WizardClosingDialog.title"), //$NON-NLS-1$
+ null,
+ JFaceResources.getString("WizardClosingDialog.message"), //$NON-NLS-1$
+ MessageDialog.QUESTION,
+ new String[] { IDialogConstants.OK_LABEL }, 0);
+ return result;
+ }
+
+ /**
+ * The Finish button has been pressed.
+ */
+ protected void finishPressed() {
+ // Wizards are added to the nested wizards list in setWizard.
+ // This means that the current wizard is always the last wizard in the
+ // list.
+ // Note that we first call the current wizard directly (to give it a
+ // chance to
+ // abort, do work, and save state) then call the remaining n-1 wizards
+ // in the
+ // list (to save state).
+ if (wizard.performFinish()) {
+ // Call perform finish on outer wizards in the nested chain
+ // (to allow them to save state for example)
+ for (int i = 0; i < nestedWizards.size() - 1; i++) {
+ ((IWizard) nestedWizards.get(i)).performFinish();
+ }
+ // Hard close the dialog.
+ setReturnCode(OK);
+ hardClose();
+ }
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IWizardContainer.
+ */
+ public IWizardPage getCurrentPage() {
+ return currentPage;
+ }
+
+ /**
+ * Returns the progress monitor for this wizard dialog (if it has one).
+ *
+ * @return the progress monitor, or null
if this wizard
+ * dialog does not have one
+ */
+ protected IProgressMonitor getProgressMonitor() {
+ return progressMonitorPart;
+ }
+
+ /**
+ * Returns the wizard this dialog is currently displaying.
+ *
+ * @return the current wizard
+ */
+ protected IWizard getWizard() {
+ return wizard;
+ }
+
+ /**
+ * Closes this window.
+ *
+ * @return true
if the window is (or was already) closed, and
+ * false
if it is still open
+ */
+ private bool hardClose() {
+ // inform wizards
+ for (int i = 0; i < createdWizards.size(); i++) {
+ IWizard createdWizard = (IWizard) createdWizards.get(i);
+ createdWizard.dispose();
+ // Remove this dialog as a parent from the managed wizard.
+ // Note that we do this after calling dispose as the wizard or
+ // its pages may need access to the container during
+ // dispose code
+ createdWizard.setContainer(null);
+ }
+ return super.close();
+ }
+
+ /**
+ * The Help button has been pressed.
+ */
+ protected void helpPressed() {
+ if (currentPage !is null) {
+ currentPage.performHelp();
+ }
+ }
+
+ /**
+ * The Next button has been pressed.
+ */
+ protected void nextPressed() {
+ IWizardPage page = currentPage.getNextPage();
+ if (page is null) {
+ // something must have happend getting the next page
+ return;
+ }
+
+ // show the next page
+ showPage(page);
+ }
+
+ /**
+ * Notifies page changing listeners and returns result of page changing
+ * processing to the sender.
+ *
+ * @param eventType
+ * @return true
if page changing listener completes
+ * successfully, false
otherwise
+ */
+ private bool doPageChanging(IWizardPage targetPage) {
+ PageChangingEvent e = new PageChangingEvent(this, getCurrentPage(),
+ targetPage);
+ firePageChanging(e);
+ // Prevent navigation if necessary
+ return e.doit;
+ }
+
+ /**
+ * Checks whether it is alright to close this wizard dialog and performed
+ * standard cancel processing. If there is a long running operation in
+ * progress, this method posts an alert message saying that the wizard
+ * cannot be closed.
+ *
+ * @return true
if it is alright to close this dialog, and
+ * false
if it is not
+ */
+ private bool okToClose() {
+ if (activeRunningOperations > 0) {
+ synchronized (this) {
+ windowClosingDialog = createWizardClosingDialog();
+ }
+ windowClosingDialog.open();
+ synchronized (this) {
+ windowClosingDialog = null;
+ }
+ return false;
+ }
+ return wizard.performCancel();
+ }
+
+ /**
+ * Restores the enabled/disabled state of the given control.
+ *
+ * @param w
+ * the control
+ * @param h
+ * the map (key type: String
, element type:
+ * bool
)
+ * @param key
+ * the key
+ * @see #saveEnableStateAndSet
+ */
+ private void restoreEnableState(Control w, Map h, String key) {
+ if (w !is null) {
+ bool b = (bool) h.get(key);
+ if (b !is null) {
+ w.setEnabled(b.booleanValue());
+ }
+ }
+ }
+
+ /**
+ * Restores the enabled/disabled state of the wizard dialog's buttons and
+ * the tree of controls for the currently showing page.
+ *
+ * @param state
+ * a map containing the saved state as returned by
+ * saveUIState
+ * @see #saveUIState
+ */
+ private void restoreUIState(Map state) {
+ restoreEnableState(backButton, state, "back"); //$NON-NLS-1$
+ restoreEnableState(nextButton, state, "next"); //$NON-NLS-1$
+ restoreEnableState(finishButton, state, "finish"); //$NON-NLS-1$
+ restoreEnableState(cancelButton, state, "cancel"); //$NON-NLS-1$
+ restoreEnableState(helpButton, state, "help"); //$NON-NLS-1$
+ Object pageValue = state.get("page"); //$NON-NLS-1$
+ if (pageValue !is null) {
+ ((ControlEnableState) pageValue).restore();
+ }
+ }
+
+ /**
+ * This implementation of IRunnableContext#run(bool, bool,
+ * IRunnableWithProgress) blocks until the runnable has been run, regardless
+ * of the value of fork
. It is recommended that
+ * fork
is set to true in most cases. If fork
+ * is set to false
, the runnable will run in the UI thread
+ * and it is the runnable's responsibility to call
+ * Display.readAndDispatch()
to ensure UI responsiveness.
+ *
+ * UI state is saved prior to executing the long-running operation and is
+ * restored after the long-running operation completes executing. Any
+ * attempt to change the UI state of the wizard in the long-running
+ * operation will be nullified when original UI state is restored.
+ *
+ */
+ public void run(bool fork, bool cancelable,
+ IRunnableWithProgress runnable) throws InvocationTargetException,
+ InterruptedException {
+ // The operation can only be canceled if it is executed in a separate
+ // thread.
+ // Otherwise the UI is blocked anyway.
+ Object state = null;
+ if (activeRunningOperations is 0) {
+ state = aboutToStart(fork && cancelable);
+ }
+ activeRunningOperations++;
+ try {
+ if (!fork) {
+ lockedUI = true;
+ }
+ ModalContext.run(runnable, fork, getProgressMonitor(), getShell()
+ .getDisplay());
+ lockedUI = false;
+ } finally {
+ activeRunningOperations--;
+ // Stop if this is the last one
+ if (state !is null) {
+ stopped(state);
+ }
+ }
+ }
+
+ /**
+ * Saves the enabled/disabled state of the given control in the given map,
+ * which must be modifiable.
+ *
+ * @param w
+ * the control, or null
if none
+ * @param h
+ * the map (key type: String
, element type:
+ * bool
)
+ * @param key
+ * the key
+ * @param enabled
+ * true
to enable the control, and
+ * false
to disable it
+ * @see #restoreEnableState(Control, Map, String)
+ */
+ private void saveEnableStateAndSet(Control w, Map h, String key,
+ bool enabled) {
+ if (w !is null) {
+ h.put(key, w.getEnabled() ? bool.TRUE : bool.FALSE);
+ w.setEnabled(enabled);
+ }
+ }
+
+ /**
+ * Captures and returns the enabled/disabled state of the wizard dialog's
+ * buttons and the tree of controls for the currently showing page. All
+ * these controls are disabled in the process, with the possible exception
+ * of the Cancel button.
+ *
+ * @param keepCancelEnabled
+ * true
if the Cancel button should remain
+ * enabled, and false
if it should be disabled
+ * @return a map containing the saved state suitable for restoring later
+ * with restoreUIState
+ * @see #restoreUIState
+ */
+ private Map saveUIState(bool keepCancelEnabled) {
+ Map savedState = new HashMap(10);
+ saveEnableStateAndSet(backButton, savedState, "back", false); //$NON-NLS-1$
+ saveEnableStateAndSet(nextButton, savedState, "next", false); //$NON-NLS-1$
+ saveEnableStateAndSet(finishButton, savedState, "finish", false); //$NON-NLS-1$
+ saveEnableStateAndSet(cancelButton, savedState,
+ "cancel", keepCancelEnabled); //$NON-NLS-1$
+ saveEnableStateAndSet(helpButton, savedState, "help", false); //$NON-NLS-1$
+ if (currentPage !is null) {
+ savedState
+ .put(
+ "page", ControlEnableState.disable(currentPage.getControl())); //$NON-NLS-1$
+ }
+ return savedState;
+ }
+
+ /**
+ * Sets the given cursor for all shells currently active for this window's
+ * display.
+ *
+ * @param c
+ * the cursor
+ */
+ private void setDisplayCursor(Cursor c) {
+ Shell[] shells = getShell().getDisplay().getShells();
+ for (int i = 0; i < shells.length; i++) {
+ shells[i].setCursor(c);
+ }
+ }
+
+ /**
+ * Sets the minimum page size used for the pages.
+ *
+ * @param minWidth
+ * the minimum page width
+ * @param minHeight
+ * the minimum page height
+ * @see #setMinimumPageSize(Point)
+ */
+ public void setMinimumPageSize(int minWidth, int minHeight) {
+ Assert.isTrue(minWidth >= 0 && minHeight >= 0);
+ pageContainerLayout.minimumWidth = minWidth;
+ pageContainerLayout.minimumHeight = minHeight;
+ }
+
+ /**
+ * Sets the minimum page size used for the pages.
+ *
+ * @param size
+ * the page size encoded as new Point(width,height)
+ * @see #setMinimumPageSize(int,int)
+ */
+ public void setMinimumPageSize(Point size) {
+ setMinimumPageSize(size.x, size.y);
+ }
+
+ /**
+ * Sets the size of all pages. The given size takes precedence over computed
+ * sizes.
+ *
+ * @param width
+ * the page width
+ * @param height
+ * the page height
+ * @see #setPageSize(Point)
+ */
+ public void setPageSize(int width, int height) {
+ pageWidth = width;
+ pageHeight = height;
+ }
+
+ /**
+ * Sets the size of all pages. The given size takes precedence over computed
+ * sizes.
+ *
+ * @param size
+ * the page size encoded as new Point(width,height)
+ * @see #setPageSize(int,int)
+ */
+ public void setPageSize(Point size) {
+ setPageSize(size.x, size.y);
+ }
+
+ /**
+ * Sets the wizard this dialog is currently displaying.
+ *
+ * @param newWizard
+ * the wizard
+ */
+ protected void setWizard(IWizard newWizard) {
+ wizard = newWizard;
+ wizard.setContainer(this);
+ if (!createdWizards.contains(wizard)) {
+ createdWizards.add(wizard);
+ // New wizard so just add it to the end of our nested list
+ nestedWizards.add(wizard);
+ if (pageContainer !is null) {
+ // Dialog is already open
+ // Allow the wizard pages to precreate their page controls
+ // This allows the wizard to open to the correct size
+ createPageControls();
+ // Ensure the dialog is large enough for the wizard
+ updateSizeForWizard(wizard);
+ pageContainer.layout(true);
+ }
+ } else {
+ // We have already seen this wizard, if it is the previous wizard
+ // on the nested list then we assume we have gone back and remove
+ // the last wizard from the list
+ int size = nestedWizards.size();
+ if (size >= 2 && nestedWizards.get(size - 2) is wizard) {
+ nestedWizards.remove(size - 1);
+ } else {
+ // Assume we are going forward to revisit a wizard
+ nestedWizards.add(wizard);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IWizardContainer.
+ */
+ public void showPage(IWizardPage page) {
+ if (page is null || page is currentPage) {
+ return;
+ }
+
+ if (!isMovingToPreviousPage) {
+ // remember my previous page.
+ page.setPreviousPage(currentPage);
+ } else {
+ isMovingToPreviousPage = false;
+ }
+
+ // If page changing evaluation unsuccessful, do not change the page
+ if (!doPageChanging(page))
+ return;
+
+ // Update for the new page in a busy cursor if possible
+ if (getContents() is null) {
+ updateForPage(page);
+ } else {
+ final IWizardPage finalPage = page;
+ BusyIndicator.showWhile(getContents().getDisplay(), new Runnable() {
+ public void run() {
+ updateForPage(finalPage);
+ }
+ });
+ }
+ }
+
+ /**
+ * Update the receiver for the new page.
+ *
+ * @param page
+ */
+ private void updateForPage(IWizardPage page) {
+ // ensure this page belongs to the current wizard
+ if (wizard !is page.getWizard()) {
+ setWizard(page.getWizard());
+ }
+ // ensure that page control has been created
+ // (this allows lazy page control creation)
+ if (page.getControl() is null) {
+ page.createControl(pageContainer);
+ // the page is responsible for ensuring the created control is
+ // accessable
+ // via getControl.
+ Assert.isNotNull(page.getControl(), JFaceResources.format(
+ JFaceResources.getString("WizardDialog.missingSetControl"), //$NON-NLS-1$
+ new Object[] { page.getName() }));
+ // ensure the dialog is large enough for this page
+ updateSize(page);
+ }
+ // make the new page visible
+ IWizardPage oldPage = currentPage;
+ currentPage = page;
+
+ currentPage.setVisible(true);
+ if (oldPage !is null) {
+ oldPage.setVisible(false);
+ }
+ // update the dialog controls
+ update();
+ }
+
+ /**
+ * Shows the starting page of the wizard.
+ */
+ private void showStartingPage() {
+ currentPage = wizard.getStartingPage();
+ if (currentPage is null) {
+ // something must have happend getting the page
+ return;
+ }
+ // ensure the page control has been created
+ if (currentPage.getControl() is null) {
+ currentPage.createControl(pageContainer);
+ // the page is responsible for ensuring the created control is
+ // accessable
+ // via getControl.
+ Assert.isNotNull(currentPage.getControl());
+ // we do not need to update the size since the call
+ // to initialize bounds has not been made yet.
+ }
+ // make the new page visible
+ currentPage.setVisible(true);
+ // update the dialog controls
+ update();
+ }
+
+ /**
+ * A long running operation triggered through the wizard was stopped either
+ * by user input or by normal end. Hides the progress monitor and restores
+ * the enable state wizard's buttons and controls.
+ *
+ * @param savedState
+ * the saved UI state as returned by aboutToStart
+ * @see #aboutToStart
+ */
+ private void stopped(Object savedState) {
+ if (getShell() !is null) {
+ if (wizard.needsProgressMonitor()) {
+ progressMonitorPart.setVisible(false);
+ progressMonitorPart.removeFromCancelComponent(cancelButton);
+ }
+ Map state = (Map) savedState;
+ restoreUIState(state);
+ cancelButton.addSelectionListener(cancelListener);
+ setDisplayCursor(null);
+ cancelButton.setCursor(null);
+ waitCursor.dispose();
+ waitCursor = null;
+ arrowCursor.dispose();
+ arrowCursor = null;
+ Control focusControl = (Control) state.get(FOCUS_CONTROL);
+ if (focusControl !is null) {
+ focusControl.setFocus();
+ }
+ }
+ }
+
+ /**
+ * Updates this dialog's controls to reflect the current page.
+ */
+ protected void update() {
+ // Update the window title
+ updateWindowTitle();
+ // Update the title bar
+ updateTitleBar();
+ // Update the buttons
+ updateButtons();
+
+ // Fires the page change event
+ firePageChanged(new PageChangedEvent(this, getCurrentPage()));
+ }
+
+ /*
+ * (non-Javadoc) Method declared on IWizardContainer.
+ */
+ public void updateButtons() {
+ bool canFlipToNextPage = false;
+ bool canFinish = wizard.canFinish();
+ if (backButton !is null) {
+ backButton.setEnabled(currentPage.getPreviousPage() !is null);
+ }
+ if (nextButton !is null) {
+ canFlipToNextPage = currentPage.canFlipToNextPage();
+ nextButton.setEnabled(canFlipToNextPage);
+ }
+ finishButton.setEnabled(canFinish);
+ // finish is default unless it is diabled and next is enabled
+ if (canFlipToNextPage && !canFinish) {
+ getShell().setDefaultButton(nextButton);
+ } else {
+ getShell().setDefaultButton(finishButton);
+ }
+ }
+
+ /**
+ * Update the message line with the page's description.
+ * + * A discription is shown only if there is no message or error message. + *
+ */ + private void updateDescriptionMessage() { + pageDescription = currentPage.getDescription(); + setMessage(pageDescription); + } + + /* + * (non-Javadoc) Method declared on IWizardContainer. + */ + public void updateMessage() { + + if (currentPage is null) { + return; + } + + pageMessage = currentPage.getMessage(); + if (pageMessage !is null && currentPage instanceof IMessageProvider) { + pageMessageType = ((IMessageProvider) currentPage).getMessageType(); + } else { + pageMessageType = IMessageProvider.NONE; + } + if (pageMessage is null) { + setMessage(pageDescription); + } else { + setMessage(pageMessage, pageMessageType); + } + setErrorMessage(currentPage.getErrorMessage()); + } + + /** + * Changes the shell size to the given size, ensuring that it is no larger + * than the display bounds. + * + * @param width + * the shell width + * @param height + * the shell height + */ + private void setShellSize(int width, int height) { + Rectangle size = getShell().getBounds(); + size.height = height; + size.width = width; + getShell().setBounds(getConstrainedShellBounds(size)); + } + + /** + * Computes the correct dialog size for the current page and resizes its + * shell if nessessary. Also causes the container to refresh its layout. + * + * @param page + * the wizard page to use to resize the dialog + * @since 2.0 + */ + protected void updateSize(IWizardPage page) { + if (page is null || page.getControl() is null) { + return; + } + updateSizeForPage(page); + pageContainerLayout.layoutPage(page.getControl()); + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.wizard.IWizardContainer2#updateSize() + */ + public void updateSize() { + updateSize(currentPage); + } + + /** + * Computes the correct dialog size for the given page and resizes its shell + * if nessessary. + * + * @param page + * the wizard page + */ + private void updateSizeForPage(IWizardPage page) { + // ensure the page container is large enough + Point delta = calculatePageSizeDelta(page); + if (delta.x > 0 || delta.y > 0) { + // increase the size of the shell + Shell shell = getShell(); + Point shellSize = shell.getSize(); + setShellSize(shellSize.x + delta.x, shellSize.y + delta.y); + constrainShellSize(); + } + } + + /** + * Computes the correct dialog size for the given wizard and resizes its + * shell if nessessary. + * + * @param sizingWizard + * the wizard + */ + private void updateSizeForWizard(IWizard sizingWizard) { + Point delta = new Point(0, 0); + IWizardPage[] pages = sizingWizard.getPages(); + for (int i = 0; i < pages.length; i++) { + // ensure the page container is large enough + Point pageDelta = calculatePageSizeDelta(pages[i]); + delta.x = Math.max(delta.x, pageDelta.x); + delta.y = Math.max(delta.y, pageDelta.y); + } + if (delta.x > 0 || delta.y > 0) { + // increase the size of the shell + Shell shell = getShell(); + Point shellSize = shell.getSize(); + setShellSize(shellSize.x + delta.x, shellSize.y + delta.y); + } + } + + /* + * (non-Javadoc) Method declared on IWizardContainer. + */ + public void updateTitleBar() { + String s = null; + if (currentPage !is null) { + s = currentPage.getTitle(); + } + if (s is null) { + s = ""; //$NON-NLS-1$ + } + setTitle(s); + if (currentPage !is null) { + setTitleImage(currentPage.getImage()); + updateDescriptionMessage(); + } + updateMessage(); + } + + /* + * (non-Javadoc) Method declared on IWizardContainer. + */ + public void updateWindowTitle() { + if (getShell() is null) { + // Not created yet + return; + } + String title = wizard.getWindowTitle(); + if (title is null) { + title = ""; //$NON-NLS-1$ + } + getShell().setText(title); + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.dialogs.IPageChangeProvider#getSelectedPage() + */ + public Object getSelectedPage() { + return getCurrentPage(); + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.dialog.IPageChangeProvider#addPageChangedListener() + */ + public void addPageChangedListener(IPageChangedListener listener) { + pageChangedListeners.add(listener); + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.dialog.IPageChangeProvider#removePageChangedListener() + */ + public void removePageChangedListener(IPageChangedListener listener) { + pageChangedListeners.remove(listener); + } + + /** + * Notifies any selection changed listeners that the selected page has + * changed. Only listeners registered at the time this method is called are + * notified. + * + * @param event + * a selection changed event + * + * @see IPageChangedListener#pageChanged + * + * @since 3.1 + */ + protected 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() { + public void run() { + l.pageChanged(event); + } + }); + } + } + + /** + * Adds a listener for page changes to the list of page changing listeners + * registered for this dialog. Has no effect if an identical listener is + * already registered. + * + * @param listener + * a page changing listener + * @since 3.3 + */ + public void addPageChangingListener(IPageChangingListener listener) { + pageChangingListeners.add(listener); + } + + /** + * Removes the provided page changing listener from the list of page + * changing listeners registered for the dialog. + * + * @param listener + * a page changing listener + * @since 3.3 + */ + public void removePageChangingListener(IPageChangingListener listener) { + pageChangingListeners.remove(listener); + } + + /** + * Notifies any page changing listeners that the currently selected dialog + * page is changing. Only listeners registered at the time this method is + * called are notified. + * + * @param event + * a selection changing event + * + * @see IPageChangingListener#handlePageChanging(PageChangingEvent) + * @since 3.3 + */ + protected void firePageChanging(final PageChangingEvent event) { + Object[] listeners = pageChangingListeners.getListeners(); + for (int i = 0; i < listeners.length; ++i) { + final IPageChangingListener l = (IPageChangingListener) listeners[i]; + SafeRunnable.run(new SafeRunnable() { + public void run() { + l.handlePageChanging(event); + } + }); + } + } +} +++/ \ No newline at end of file