# HG changeset patch # User Frank Benoit # Date 1206753912 -3600 # Node ID 6c14e54dfc11528fbdf096a270d6143c15d5f27a # Parent a3ff22a98bef858d03e31c2dd0784a3125010f37 completed /jface/resource/ diff -r a3ff22a98bef -r 6c14e54dfc11 dwtx/jface/dialogs/TitleAreaDialog.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/dialogs/TitleAreaDialog.d Sat Mar 29 02:25:12 2008 +0100 @@ -0,0 +1,638 @@ +/******************************************************************************* + * 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 + * Konstantin Scheglov - Fix for bug 41172 + * [Dialogs] Bug with Image in TitleAreaDialog + * Sebastian Davids - Fix for bug 82064 + * [Dialogs] TitleAreaDialog#setTitleImage cannot be called before open() + * Port to the D programming language: + * Frank Benoit + *******************************************************************************/ +module dwtx.jface.dialogs.TitleAreaDialog; + +import dwt.dwthelper.utils; +pragma( msg, "FIXME dwtx.jface.dialogs.TitleAreaDialog" ); +class TitleAreaDialog{ + public static const String DLG_IMG_TITLE_BANNER = "dialog_title_banner_image";//$NON-NLS-1$ +} + + +/++ +import dwt.DWT; +import dwt.events.DisposeEvent; +import dwt.events.DisposeListener; +import dwt.graphics.Color; +import dwt.graphics.Image; +import dwt.graphics.Point; +import dwt.graphics.RGB; +import dwt.layout.FormAttachment; +import dwt.layout.FormData; +import dwt.layout.FormLayout; +import dwt.layout.GridData; +import dwt.layout.GridLayout; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Display; +import dwt.widgets.Label; +import dwt.widgets.Shell; +import dwt.widgets.Text; +import dwtx.jface.resource.JFaceColors; +import dwtx.jface.resource.JFaceResources; + +/** + * A dialog that has a title area for displaying a title and an image as well as + * a common area for displaying a description, a message, or an error message. + *

+ * This dialog class may be subclassed. + */ +public class TitleAreaDialog extends TrayDialog { + /** + * Image registry key for error message image. + */ + public static final String DLG_IMG_TITLE_ERROR = DLG_IMG_MESSAGE_ERROR; + + /** + * Image registry key for banner image (value + * "dialog_title_banner_image"). + */ + public static final String DLG_IMG_TITLE_BANNER = "dialog_title_banner_image";//$NON-NLS-1$ + + /** + * Message type constant used to display an info icon with the message. + * + * @since 2.0 + * @deprecated + */ + public final static String INFO_MESSAGE = "INFO_MESSAGE"; //$NON-NLS-1$ + + /** + * Message type constant used to display a warning icon with the message. + * + * @since 2.0 + * @deprecated + */ + public final static String WARNING_MESSAGE = "WARNING_MESSAGE"; //$NON-NLS-1$ + + // Space between an image and a label + private static final int H_GAP_IMAGE = 5; + + // Minimum dialog width (in dialog units) + private static final int MIN_DIALOG_WIDTH = 350; + + // Minimum dialog height (in dialog units) + private static final int MIN_DIALOG_HEIGHT = 150; + + private Label titleLabel; + + private Label titleImageLabel; + + private Label bottomFillerLabel; + + private Label leftFillerLabel; + + private RGB titleAreaRGB; + + Color titleAreaColor; + + private String message = ""; //$NON-NLS-1$ + + private String errorMessage; + + private Text messageLabel; + + private Composite workArea; + + private Label messageImageLabel; + + private Image messageImage; + + private bool showingError = false; + + private bool titleImageLargest = true; + + private int messageLabelHeight; + + private Image titleAreaImage; + + /** + * Instantiate a new title area dialog. + * + * @param parentShell + * the parent DWT shell + */ + public TitleAreaDialog(Shell parentShell) { + super(parentShell); + } + + /* + * @see Dialog.createContents(Composite) + */ + protected Control createContents(Composite parent) { + // create the overall composite + Composite contents = new Composite(parent, DWT.NONE); + contents.setLayoutData(new GridData(GridData.FILL_BOTH)); + // initialize the dialog units + initializeDialogUnits(contents); + FormLayout layout = new FormLayout(); + contents.setLayout(layout); + // Now create a work area for the rest of the dialog + workArea = new Composite(contents, DWT.NONE); + GridLayout childLayout = new GridLayout(); + childLayout.marginHeight = 0; + childLayout.marginWidth = 0; + childLayout.verticalSpacing = 0; + workArea.setLayout(childLayout); + Control top = createTitleArea(contents); + resetWorkAreaAttachments(top); + workArea.setFont(JFaceResources.getDialogFont()); + // initialize the dialog units + initializeDialogUnits(workArea); + // create the dialog area and button bar + dialogArea = createDialogArea(workArea); + buttonBar = createButtonBar(workArea); + return contents; + } + + /** + * Creates and returns the contents of the upper part of this dialog (above + * the button bar). + *

+ * The Dialog implementation of this framework method creates + * and returns a new Composite with no margins and spacing. + * Subclasses should override. + *

+ * + * @param parent + * The parent composite to contain the dialog area + * @return the dialog area control + */ + protected Control createDialogArea(Composite parent) { + // create the top level composite for the dialog area + Composite composite = new Composite(parent, DWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginHeight = 0; + layout.marginWidth = 0; + layout.verticalSpacing = 0; + layout.horizontalSpacing = 0; + composite.setLayout(layout); + composite.setLayoutData(new GridData(GridData.FILL_BOTH)); + composite.setFont(parent.getFont()); + // Build the separator line + Label titleBarSeparator = new Label(composite, DWT.HORIZONTAL + | DWT.SEPARATOR); + titleBarSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + return composite; + } + + /** + * Creates the dialog's title area. + * + * @param parent + * the DWT parent for the title area widgets + * @return Control with the highest x axis value. + */ + private Control createTitleArea(Composite parent) { + + // add a dispose listener + parent.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent e) { + if (titleAreaColor !is null) { + titleAreaColor.dispose(); + } + } + }); + // Determine the background color of the title bar + Display display = parent.getDisplay(); + Color background; + Color foreground; + if (titleAreaRGB !is null) { + titleAreaColor = new Color(display, titleAreaRGB); + background = titleAreaColor; + foreground = null; + } else { + background = JFaceColors.getBannerBackground(display); + foreground = JFaceColors.getBannerForeground(display); + } + + parent.setBackground(background); + int verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); + int horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); + // Dialog image @ right + titleImageLabel = new Label(parent, DWT.CENTER); + titleImageLabel.setBackground(background); + if (titleAreaImage is null) + titleImageLabel.setImage(JFaceResources + .getImage(DLG_IMG_TITLE_BANNER)); + else + titleImageLabel.setImage(titleAreaImage); + + FormData imageData = new FormData(); + imageData.top = new FormAttachment(0, 0); + // Note: do not use horizontalSpacing on the right as that would be a + // regression from + // the R2.x style where there was no margin on the right and images are + // flush to the right + // hand side. see reopened comments in 41172 + imageData.right = new FormAttachment(100, 0); // horizontalSpacing + titleImageLabel.setLayoutData(imageData); + // Title label @ top, left + titleLabel = new Label(parent, DWT.LEFT); + JFaceColors.setColors(titleLabel, foreground, background); + titleLabel.setFont(JFaceResources.getBannerFont()); + titleLabel.setText(" ");//$NON-NLS-1$ + FormData titleData = new FormData(); + titleData.top = new FormAttachment(0, verticalSpacing); + titleData.right = new FormAttachment(titleImageLabel); + titleData.left = new FormAttachment(0, horizontalSpacing); + titleLabel.setLayoutData(titleData); + // Message image @ bottom, left + messageImageLabel = new Label(parent, DWT.CENTER); + messageImageLabel.setBackground(background); + // Message label @ bottom, center + messageLabel = new Text(parent, DWT.WRAP | DWT.READ_ONLY); + JFaceColors.setColors(messageLabel, foreground, background); + messageLabel.setText(" \n "); // two lines//$NON-NLS-1$ + messageLabel.setFont(JFaceResources.getDialogFont()); + messageLabelHeight = messageLabel.computeSize(DWT.DEFAULT, DWT.DEFAULT).y; + // Filler labels + leftFillerLabel = new Label(parent, DWT.CENTER); + leftFillerLabel.setBackground(background); + bottomFillerLabel = new Label(parent, DWT.CENTER); + bottomFillerLabel.setBackground(background); + setLayoutsForNormalMessage(verticalSpacing, horizontalSpacing); + determineTitleImageLargest(); + if (titleImageLargest) + return titleImageLabel; + return messageLabel; + } + + /** + * Determine if the title image is larger than the title message and message + * area. This is used for layout decisions. + */ + private void determineTitleImageLargest() { + int titleY = titleImageLabel.computeSize(DWT.DEFAULT, DWT.DEFAULT).y; + int verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); + int labelY = titleLabel.computeSize(DWT.DEFAULT, DWT.DEFAULT).y; + labelY += verticalSpacing; + labelY += messageLabelHeight; + labelY += verticalSpacing; + titleImageLargest = titleY > labelY; + } + + /** + * Set the layout values for the messageLabel, messageImageLabel and + * fillerLabel for the case where there is a normal message. + * + * @param verticalSpacing + * int The spacing between widgets on the vertical axis. + * @param horizontalSpacing + * int The spacing between widgets on the horizontal axis. + */ + private void setLayoutsForNormalMessage(int verticalSpacing, + int horizontalSpacing) { + FormData messageImageData = new FormData(); + messageImageData.top = new FormAttachment(titleLabel, verticalSpacing); + messageImageData.left = new FormAttachment(0, H_GAP_IMAGE); + messageImageLabel.setLayoutData(messageImageData); + FormData messageLabelData = new FormData(); + messageLabelData.top = new FormAttachment(titleLabel, verticalSpacing); + messageLabelData.right = new FormAttachment(titleImageLabel); + messageLabelData.left = new FormAttachment(messageImageLabel, + horizontalSpacing); + messageLabelData.height = messageLabelHeight; + if (titleImageLargest) + messageLabelData.bottom = new FormAttachment(titleImageLabel, 0, + DWT.BOTTOM); + messageLabel.setLayoutData(messageLabelData); + FormData fillerData = new FormData(); + fillerData.left = new FormAttachment(0, horizontalSpacing); + fillerData.top = new FormAttachment(messageImageLabel, 0); + fillerData.bottom = new FormAttachment(messageLabel, 0, DWT.BOTTOM); + bottomFillerLabel.setLayoutData(fillerData); + FormData data = new FormData(); + data.top = new FormAttachment(messageImageLabel, 0, DWT.TOP); + data.left = new FormAttachment(0, 0); + data.bottom = new FormAttachment(messageImageLabel, 0, DWT.BOTTOM); + data.right = new FormAttachment(messageImageLabel, 0); + leftFillerLabel.setLayoutData(data); + } + + /** + * The TitleAreaDialog implementation of this + * Window methods returns an initial size which is at least + * some reasonable minimum. + * + * @return the initial size of the dialog + */ + protected Point getInitialSize() { + Point shellSize = super.getInitialSize(); + return new Point(Math.max( + convertHorizontalDLUsToPixels(MIN_DIALOG_WIDTH), shellSize.x), + Math.max(convertVerticalDLUsToPixels(MIN_DIALOG_HEIGHT), + shellSize.y)); + } + + /** + * Retained for backward compatibility. + * + * Returns the title area composite. There is no composite in this + * implementation so the shell is returned. + * + * @return Composite + * @deprecated + */ + protected Composite getTitleArea() { + return getShell(); + } + + /** + * Returns the title image label. + * + * @return the title image label + */ + protected Label getTitleImageLabel() { + return titleImageLabel; + } + + /** + * Display the given error message. The currently displayed message is saved + * and will be redisplayed when the error message is set to + * null. + * + * @param newErrorMessage + * the newErrorMessage to display or null + */ + public void setErrorMessage(String newErrorMessage) { + // Any change? + if (errorMessage is null ? newErrorMessage is null : errorMessage + .equals(newErrorMessage)) + return; + errorMessage = newErrorMessage; + + // Clear or set error message. + if (errorMessage is null) { + if (showingError) { + // we were previously showing an error + showingError = false; + } + // show the message + // avoid calling setMessage in case it is overridden to call + // setErrorMessage, + // which would result in a recursive infinite loop + if (message is null) // this should probably never happen since + // setMessage does this conversion.... + message = ""; //$NON-NLS-1$ + updateMessage(message); + messageImageLabel.setImage(messageImage); + setImageLabelVisible(messageImage !is null); + } else { + // Add in a space for layout purposes but do not + // change the instance variable + String displayedErrorMessage = " " + errorMessage; //$NON-NLS-1$ + updateMessage(displayedErrorMessage); + if (!showingError) { + // we were not previously showing an error + showingError = true; + messageImageLabel.setImage(JFaceResources + .getImage(DLG_IMG_TITLE_ERROR)); + setImageLabelVisible(true); + } + } + layoutForNewMessage(); + } + + /** + * Re-layout the labels for the new message. + */ + private void layoutForNewMessage() { + int verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING); + int horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING); + // If there are no images then layout as normal + if (errorMessage is null && messageImage is null) { + setImageLabelVisible(false); + setLayoutsForNormalMessage(verticalSpacing, horizontalSpacing); + } else { + messageImageLabel.setVisible(true); + bottomFillerLabel.setVisible(true); + leftFillerLabel.setVisible(true); + /** + * Note that we do not use horizontalSpacing here as when the + * background of the messages changes there will be gaps between the + * icon label and the message that are the background color of the + * shell. We add a leading space elsewhere to compendate for this. + */ + FormData data = new FormData(); + data.left = new FormAttachment(0, H_GAP_IMAGE); + data.top = new FormAttachment(titleLabel, verticalSpacing); + messageImageLabel.setLayoutData(data); + data = new FormData(); + data.top = new FormAttachment(messageImageLabel, 0); + data.left = new FormAttachment(0, 0); + data.bottom = new FormAttachment(messageLabel, 0, DWT.BOTTOM); + data.right = new FormAttachment(messageImageLabel, 0, DWT.RIGHT); + bottomFillerLabel.setLayoutData(data); + data = new FormData(); + data.top = new FormAttachment(messageImageLabel, 0, DWT.TOP); + data.left = new FormAttachment(0, 0); + data.bottom = new FormAttachment(messageImageLabel, 0, DWT.BOTTOM); + data.right = new FormAttachment(messageImageLabel, 0); + leftFillerLabel.setLayoutData(data); + FormData messageLabelData = new FormData(); + messageLabelData.top = new FormAttachment(titleLabel, + verticalSpacing); + messageLabelData.right = new FormAttachment(titleImageLabel); + messageLabelData.left = new FormAttachment(messageImageLabel, 0); + messageLabelData.height = messageLabelHeight; + if (titleImageLargest) + messageLabelData.bottom = new FormAttachment(titleImageLabel, + 0, DWT.BOTTOM); + messageLabel.setLayoutData(messageLabelData); + } + // Do not layout before the dialog area has been created + // to avoid incomplete calculations. + if (dialogArea !is null) + workArea.getParent().layout(true); + } + + /** + * Set the message text. If the message line currently displays an error, + * the message is saved and will be redisplayed when the error message is + * set to null. + *

+ * Shortcut for setMessage(newMessage, IMessageProvider.NONE) + *

+ * This method should be called after the dialog has been opened as it + * updates the message label immediately. + * + * @param newMessage + * the message, or null to clear the message + */ + public void setMessage(String newMessage) { + setMessage(newMessage, IMessageProvider.NONE); + } + + /** + * Sets the message for this dialog with an indication of what type of + * message it is. + *

+ * The valid message types are one of NONE, + * INFORMATION,WARNING, or + * ERROR. + *

+ *

+ * Note that for backward compatibility, a message of type + * ERROR is different than an error message (set using + * setErrorMessage). An error message overrides the current + * message until the error message is cleared. This method replaces the + * current message and does not affect the error message. + *

+ * + * @param newMessage + * the message, or null to clear the message + * @param newType + * the message type + * @since 2.0 + */ + public void setMessage(String newMessage, int newType) { + Image newImage = null; + if (newMessage !is null) { + switch (newType) { + case IMessageProvider.NONE: + break; + case IMessageProvider.INFORMATION: + newImage = JFaceResources.getImage(DLG_IMG_MESSAGE_INFO); + break; + case IMessageProvider.WARNING: + newImage = JFaceResources.getImage(DLG_IMG_MESSAGE_WARNING); + break; + case IMessageProvider.ERROR: + newImage = JFaceResources.getImage(DLG_IMG_MESSAGE_ERROR); + break; + } + } + showMessage(newMessage, newImage); + } + + /** + * Show the new message and image. + * + * @param newMessage + * @param newImage + */ + private void showMessage(String newMessage, Image newImage) { + // Any change? + if (message.equals(newMessage) && messageImage is newImage) { + return; + } + message = newMessage; + if (message is null) + message = "";//$NON-NLS-1$ + // Message string to be shown - if there is an image then add in + // a space to the message for layout purposes + String shownMessage = (newImage is null) ? message : " " + message; //$NON-NLS-1$ + messageImage = newImage; + if (!showingError) { + // we are not showing an error + updateMessage(shownMessage); + messageImageLabel.setImage(messageImage); + setImageLabelVisible(messageImage !is null); + layoutForNewMessage(); + } + } + + /** + * Update the contents of the messageLabel. + * + * @param newMessage + * the message to use + */ + private void updateMessage(String newMessage) { + messageLabel.setText(newMessage); + } + + /** + * Sets the title to be shown in the title area of this dialog. + * + * @param newTitle + * the title show + */ + public void setTitle(String newTitle) { + if (titleLabel is null) + return; + String title = newTitle; + if (title is null) + title = "";//$NON-NLS-1$ + titleLabel.setText(title); + } + + /** + * Sets the title bar color for this dialog. + * + * @param color + * the title bar color + */ + public void setTitleAreaColor(RGB color) { + titleAreaRGB = color; + } + + /** + * Sets the title image to be shown in the title area of this dialog. + * + * @param newTitleImage + * the title image to be shown + */ + public void setTitleImage(Image newTitleImage) { + + titleAreaImage = newTitleImage; + if (titleImageLabel !is null) { + titleImageLabel.setImage(newTitleImage); + titleImageLabel.setVisible(newTitleImage !is null); + if (newTitleImage !is null) { + determineTitleImageLargest(); + Control top; + if (titleImageLargest) + top = titleImageLabel; + else + top = messageLabel; + resetWorkAreaAttachments(top); + } + } + } + + /** + * Make the label used for displaying error images visible depending on + * bool. + * + * @param visible + * If true make the image visible, if not then + * make it not visible. + */ + private void setImageLabelVisible(bool visible) { + messageImageLabel.setVisible(visible); + bottomFillerLabel.setVisible(visible); + leftFillerLabel.setVisible(visible); + } + + /** + * Reset the attachment of the workArea to now attach to top as the top + * control. + * + * @param top + */ + private void resetWorkAreaAttachments(Control top) { + FormData childData = new FormData(); + childData.top = new FormAttachment(top); + childData.right = new FormAttachment(100, 0); + childData.left = new FormAttachment(0, 0); + childData.bottom = new FormAttachment(100, 0); + workArea.setLayoutData(childData); + } +} +++/ \ No newline at end of file diff -r a3ff22a98bef -r 6c14e54dfc11 dwtx/jface/preference/JFacePreferences.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/JFacePreferences.d Sat Mar 29 02:25:12 2008 +0100 @@ -0,0 +1,65 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +module dwtx.jface.preference.JFacePreferences; + +import dwtx.jface.preference.IPreferenceStore; + +import dwt.dwthelper.utils; + +/** + * + * JFacePreferences is a class used to administer the preferences + * used by JFace objects. + */ +public final class JFacePreferences { + + /** + * Identifier for the Error Color + */ + public static const String ERROR_COLOR = "ERROR_COLOR"; //$NON-NLS-1$ + + /** + * Identifier for the Hyperlink Color + */ + public static const String HYPERLINK_COLOR = "HYPERLINK_COLOR"; //$NON-NLS-1$ + + /** + * Identifier for the Active Hyperlink Colour + */ + public static const String ACTIVE_HYPERLINK_COLOR = "ACTIVE_HYPERLINK_COLOR"; //$NON-NLS-1$ + + private static IPreferenceStore preferenceStore; + + /** + * Prevent construction. + */ + private this() { + } + + /** + * Return the preference store for the receiver. + * @return IPreferenceStore or null + */ + public static IPreferenceStore getPreferenceStore() { + return preferenceStore; + } + + /** + * Set the preference store for the receiver. + * @param store IPreferenceStore + */ + public static void setPreferenceStore(IPreferenceStore store) { + preferenceStore = store; + } + +} diff -r a3ff22a98bef -r 6c14e54dfc11 dwtx/jface/preference/PreferenceDialog.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/PreferenceDialog.d Sat Mar 29 02:25:12 2008 +0100 @@ -0,0 +1,1518 @@ +/******************************************************************************* + * 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 + * Teddy Walker + * - Bug 188056 [Preferences] PreferencePages have to less indent in PreferenceDialog + * Port to the D programming language: + * Frank Benoit + *******************************************************************************/ +module dwtx.jface.preference.PreferenceDialog; + +import dwt.dwthelper.utils; + +pragma( msg, "FIXME dwtx.jface.preference.PreferenceDialog" ); +class PreferenceDialog{ + public static const String PREF_DLG_TITLE_IMG = "preference_dialog_title_image"; //$NON-NLS-1$ +} + +/++ +import java.io.IOException; +import java.util.Iterator; +import java.util.List; + +import dwt.DWT; +import dwt.custom.BusyIndicator; +import dwt.custom.ScrolledComposite; +import dwt.events.ControlAdapter; +import dwt.events.ControlEvent; +import dwt.events.DisposeEvent; +import dwt.events.DisposeListener; +import dwt.events.HelpEvent; +import dwt.events.HelpListener; +import dwt.events.SelectionAdapter; +import dwt.events.SelectionEvent; +import dwt.events.ShellAdapter; +import dwt.events.ShellEvent; +import dwt.graphics.Font; +import dwt.graphics.Point; +import dwt.graphics.Rectangle; +import dwt.layout.FormAttachment; +import dwt.layout.FormData; +import dwt.layout.FormLayout; +import dwt.layout.GridData; +import dwt.layout.GridLayout; +import dwt.widgets.Button; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Event; +import dwt.widgets.Label; +import dwt.widgets.Layout; +import dwt.widgets.Listener; +import dwt.widgets.Sash; +import dwt.widgets.Shell; +import dwt.widgets.Tree; +import dwtx.core.runtime.Assert; +import dwtx.core.runtime.ISafeRunnable; +import dwtx.core.runtime.IStatus; +import dwtx.core.runtime.ListenerList; +import dwtx.core.runtime.SafeRunner; +import dwtx.core.runtime.Status; +import dwtx.jface.dialogs.DialogMessageArea; +import dwtx.jface.dialogs.IDialogConstants; +import dwtx.jface.dialogs.IMessageProvider; +import dwtx.jface.dialogs.IPageChangeProvider; +import dwtx.jface.dialogs.IPageChangedListener; +import dwtx.jface.dialogs.MessageDialog; +import dwtx.jface.dialogs.PageChangedEvent; +import dwtx.jface.dialogs.TrayDialog; +import dwtx.jface.resource.JFaceResources; +import dwtx.jface.util.IPropertyChangeListener; +import dwtx.jface.util.Policy; +import dwtx.jface.util.PropertyChangeEvent; +import dwtx.jface.util.SafeRunnable; +import dwtx.jface.viewers.ISelection; +import dwtx.jface.viewers.ISelectionChangedListener; +import dwtx.jface.viewers.IStructuredSelection; +import dwtx.jface.viewers.SelectionChangedEvent; +import dwtx.jface.viewers.StructuredSelection; +import dwtx.jface.viewers.TreeViewer; +import dwtx.jface.viewers.ViewerFilter; + +/** + * A preference dialog is a hierarchical presentation of preference pages. Each + * page is represented by a node in the tree shown on the left hand side of the + * dialog; when a node is selected, the corresponding page is shown on the right + * hand side. + */ +public class PreferenceDialog extends TrayDialog implements IPreferencePageContainer, IPageChangeProvider { + /** + * Layout for the page container. + * + */ + private class PageLayout extends 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); + } + int x = minimumPageSize.x; + int y = minimumPageSize.y; + Control[] children = composite.getChildren(); + for (int i = 0; i < children.length; i++) { + Point size = children[i].computeSize(DWT.DEFAULT, DWT.DEFAULT, force); + x = Math.max(x, size.x); + y = Math.max(y, size.y); + } + + //As pages can implement thier own computeSize + //take it into account + if(currentPage !is null){ + Point size = currentPage.computeSize(); + x = Math.max(x, size.x); + y = Math.max(y, size.y); + } + + if (wHint !is DWT.DEFAULT) { + x = wHint; + } + if (hHint !is DWT.DEFAULT) { + y = hHint; + } + return new Point(x, y); + } + + public void layout(Composite composite, bool force) { + Rectangle rect = composite.getClientArea(); + Control[] children = composite.getChildren(); + for (int i = 0; i < children.length; i++) { + children[i].setSize(rect.width, rect.height); + } + } + } + + //The id of the last page that was selected + private static String lastPreferenceId = null; + + //The last known tree width + private static int lastTreeWidth = 180; + + /** + * Indentifier for the error image + */ + public static final String PREF_DLG_IMG_TITLE_ERROR = DLG_IMG_MESSAGE_ERROR; + + /** + * Title area fields + */ + public static final String PREF_DLG_TITLE_IMG = "preference_dialog_title_image"; //$NON-NLS-1$ + + /** + * Return code used when dialog failed + */ + protected static final int FAILED = 2; + + /** + * The current preference page, or null if there is none. + */ + private IPreferencePage currentPage; + + private DialogMessageArea messageArea; + + private Point lastShellSize; + + private IPreferenceNode lastSuccessfulNode; + + /** + * The minimum page size; 400 by 400 by default. + * + * @see #setMinimumPageSize(Point) + */ + private Point minimumPageSize = new Point(400, 400); + + /** + * The OK button. + */ + private Button okButton; + + /** + * The Composite in which a page is shown. + */ + private Composite pageContainer; + + /** + * The preference manager. + */ + private PreferenceManager preferenceManager; + + /** + * Flag for the presence of the error message. + */ + private bool showingError = false; + + /** + * Preference store, initially null meaning none. + * + * @see #setPreferenceStore + */ + private IPreferenceStore preferenceStore; + + private Composite titleArea; + + /** + * The tree viewer. + */ + private TreeViewer treeViewer; + + private ListenerList pageChangedListeners = new ListenerList(); + + /** + * Composite with a FormLayout to contain the title area + */ + Composite formTitleComposite; + + private ScrolledComposite scrolled; + + /** + * Creates a new preference dialog under the control of the given preference + * manager. + * + * @param parentShell + * the parent shell + * @param manager + * the preference manager + */ + public PreferenceDialog(Shell parentShell, PreferenceManager manager) { + super(parentShell); + setShellStyle(getShellStyle() | DWT.RESIZE | DWT.MAX); + preferenceManager = manager; + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.dialogs.Dialog#buttonPressed(int) + */ + protected void buttonPressed(int buttonId) { + switch (buttonId) { + case IDialogConstants.OK_ID: { + okPressed(); + return; + } + case IDialogConstants.CANCEL_ID: { + cancelPressed(); + return; + } + case IDialogConstants.HELP_ID: { + helpPressed(); + return; + } + } + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.dialogs.Dialog#cancelPressed() + */ + protected void cancelPressed() { + // Inform all pages that we are cancelling + Iterator nodes = preferenceManager.getElements(PreferenceManager.PRE_ORDER).iterator(); + while (nodes.hasNext()) { + final IPreferenceNode node = (IPreferenceNode) nodes.next(); + if (getPage(node) !is null) { + SafeRunnable.run(new SafeRunnable() { + public void run() { + if (!getPage(node).performCancel()) { + return; + } + } + }); + } + } + setReturnCode(CANCEL); + close(); + } + + /** + * Clear the last selected node. This is so that we not chache the last + * selection in case of an error. + */ + void clearSelectedNode() { + setSelectedNodePreference(null); + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.window.Window#close() + */ + public bool close() { + + //Do this is in a SafeRunnable as it may run client code + SafeRunnable runnable = new SafeRunnable(){ + /* (non-Javadoc) + * @see dwtx.core.runtime.ISafeRunnable#run() + */ + public void run() throws Exception { + List nodes = preferenceManager.getElements(PreferenceManager.PRE_ORDER); + for (int i = 0; i < nodes.size(); i++) { + IPreferenceNode node = (IPreferenceNode) nodes.get(i); + node.disposeResources(); + } + + } + + /* (non-Javadoc) + * @see dwtx.jface.util.SafeRunnable#handleException(java.lang.Throwable) + */ + public void handleException(Throwable e) { + super.handleException(e); + clearSelectedNode();//Do not cache a node with problems + } + }; + + SafeRunner.run(runnable); + + return super.close(); + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.window.Window#configureShell(dwt.widgets.Shell) + */ + protected void configureShell(Shell newShell) { + super.configureShell(newShell); + newShell.setText(JFaceResources.getString("PreferenceDialog.title")); //$NON-NLS-1$ + newShell.addShellListener(new ShellAdapter() { + public void shellActivated(ShellEvent e) { + if (lastShellSize is null) { + lastShellSize = getShell().getSize(); + } + } + + }); + + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.window.Window#constrainShellSize() + */ + protected void constrainShellSize() { + super.constrainShellSize(); + // record opening shell size + if (lastShellSize is null) { + lastShellSize = getShell().getSize(); + } + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.dialogs.Dialog#createButtonsForButtonBar(dwt.widgets.Composite) + */ + protected void createButtonsForButtonBar(Composite parent) { + // create OK and Cancel buttons by default + okButton = createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL, true); + getShell().setDefaultButton(okButton); + createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CANCEL_LABEL, false); + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.window.Window#createContents(dwt.widgets.Composite) + */ + protected Control createContents(final Composite parent) { + final Control[] control = new Control[1]; + BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() { + public void run() { + control[0] = PreferenceDialog.super.createContents(parent); + // Add the first page + selectSavedItem(); + } + }); + + return control[0]; + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.dialogs.Dialog#createDialogArea(dwt.widgets.Composite) + */ + protected Control createDialogArea(Composite parent) { + final Composite composite = (Composite) super.createDialogArea(parent); + GridLayout parentLayout = ((GridLayout) composite.getLayout()); + parentLayout.numColumns = 4; + parentLayout.marginHeight = 0; + parentLayout.marginWidth = 0; + parentLayout.verticalSpacing = 0; + parentLayout.horizontalSpacing = 0; + + composite.setBackground(parent.getDisplay().getSystemColor(DWT.COLOR_LIST_BACKGROUND)); + + Control treeControl = createTreeAreaContents(composite); + createSash(composite,treeControl); + + Label versep = new Label(composite, DWT.SEPARATOR | DWT.VERTICAL); + GridData verGd = new GridData(GridData.FILL_VERTICAL | GridData.GRAB_VERTICAL); + + versep.setLayoutData(verGd); + versep.setLayoutData(new GridData(DWT.LEFT, DWT.FILL, false, true)); + + Composite pageAreaComposite = new Composite(composite, DWT.NONE); + pageAreaComposite.setLayoutData(new GridData(GridData.FILL_BOTH)); + GridLayout layout = new GridLayout(1, true); + layout.marginHeight = 0; + layout.marginWidth = 0; + layout.verticalSpacing = 0; + pageAreaComposite.setLayout(layout); + + formTitleComposite = new Composite(pageAreaComposite, DWT.NONE); + FormLayout titleLayout = new FormLayout(); + titleLayout.marginWidth = 0; + titleLayout.marginHeight = 0; + formTitleComposite.setLayout(titleLayout); + + GridData titleGridData = new GridData(GridData.FILL_HORIZONTAL); + titleGridData.horizontalIndent = IDialogConstants.HORIZONTAL_MARGIN; + formTitleComposite.setLayoutData(titleGridData); + + // Build the title area and separator line + Composite titleComposite = new Composite(formTitleComposite, DWT.NONE); + layout = new GridLayout(); + layout.marginBottom = 5; + layout.marginHeight = 0; + layout.marginWidth = 0; + layout.horizontalSpacing = 0; + titleComposite.setLayout(layout); + + FormData titleFormData = new FormData(); + titleFormData.top = new FormAttachment(0,0); + titleFormData.left = new FormAttachment(0,0); + titleFormData.right = new FormAttachment(100,0); + titleFormData.bottom = new FormAttachment(100,0); + + titleComposite.setLayoutData(titleFormData); + createTitleArea(titleComposite); + + Label separator = new Label(pageAreaComposite, DWT.HORIZONTAL | DWT.SEPARATOR); + + separator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); + + + // Build the Page container + pageContainer = createPageContainer(pageAreaComposite); + GridData pageContainerData = new GridData(GridData.FILL_BOTH); + pageContainerData.horizontalIndent = IDialogConstants.HORIZONTAL_MARGIN; + pageContainer.setLayoutData(pageContainerData); + // Build the separator line + Label bottomSeparator = new Label(parent, DWT.HORIZONTAL | DWT.SEPARATOR); + bottomSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL | GridData.GRAB_HORIZONTAL)); + return composite; + } + + /** + * Create the sash with right control on the right. Note + * that this method assumes GridData for the layout data + * of the rightControl. + * @param composite + * @param rightControl + * @return Sash + * + * @since 3.1 + */ + protected Sash createSash(final Composite composite, final Control rightControl) { + final Sash sash = new Sash(composite, DWT.VERTICAL); + sash.setLayoutData(new GridData(GridData.FILL_VERTICAL)); + sash.setBackground(composite.getDisplay().getSystemColor(DWT.COLOR_LIST_BACKGROUND)); + // the following listener resizes the tree control based on sash deltas. + // If necessary, it will also grow/shrink the dialog. + sash.addListener(DWT.Selection, new Listener() { + /* + * (non-Javadoc) + * + * @see dwt.widgets.Listener#handleEvent(dwt.widgets.Event) + */ + public void handleEvent(Event event) { + if (event.detail is DWT.DRAG) { + return; + } + int shift = event.x - sash.getBounds().x; + GridData data = (GridData) rightControl.getLayoutData(); + int newWidthHint = data.widthHint + shift; + if (newWidthHint < 20) { + return; + } + Point computedSize = getShell().computeSize(DWT.DEFAULT, DWT.DEFAULT); + Point currentSize = getShell().getSize(); + // if the dialog wasn't of a custom size we know we can shrink + // it if necessary based on sash movement. + bool customSize = !computedSize.equals(currentSize); + data.widthHint = newWidthHint; + setLastTreeWidth(newWidthHint); + composite.layout(true); + // recompute based on new widget size + computedSize = getShell().computeSize(DWT.DEFAULT, DWT.DEFAULT); + // if the dialog was of a custom size then increase it only if + // necessary. + if (customSize) { + computedSize.x = Math.max(computedSize.x, currentSize.x); + } + computedSize.y = Math.max(computedSize.y, currentSize.y); + if (computedSize.equals(currentSize)) { + return; + } + setShellSize(computedSize.x, computedSize.y); + lastShellSize = getShell().getSize(); + } + }); + return sash; + } + + /** + * Creates the inner page container. + * + * @param parent + * @return Composite + */ + protected Composite createPageContainer(Composite parent) { + + Composite outer = new Composite(parent, DWT.NONE); + + GridData outerData = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL + | GridData.GRAB_VERTICAL); + outerData.horizontalIndent = IDialogConstants.HORIZONTAL_MARGIN; + + outer.setLayout(new GridLayout()); + outer.setLayoutData(outerData); + + //Create an outer composite for spacing + scrolled = new ScrolledComposite(outer, DWT.V_SCROLL | DWT.H_SCROLL); + + scrolled.setExpandHorizontal(true); + scrolled.setExpandVertical(true); + + GridData scrolledData = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL + | GridData.GRAB_VERTICAL); + + scrolled.setLayoutData(scrolledData); + + Composite result = new Composite(scrolled, DWT.NONE); + + GridData resultData = new GridData(GridData.FILL_BOTH | GridData.GRAB_HORIZONTAL + | GridData.GRAB_VERTICAL); + + result.setLayout(getPageLayout()); + result.setLayoutData(resultData); + + scrolled.setContent(result); + + return result; + } + + /** + * Return the layout for the composite that contains + * the pages. + * @return PageLayout + * + * @since 3.1 + */ + protected Layout getPageLayout() { + return new PageLayout(); + } + + /** + * Creates the wizard's title area. + * + * @param parent + * the DWT parent for the title area composite. + * @return the created title area composite. + */ + protected Composite createTitleArea(Composite parent) { + // Create the title area which will contain + // a title, message, and image. + int margins = 2; + titleArea = new Composite(parent, DWT.NONE); + FormLayout layout = new FormLayout(); + layout.marginHeight = 0; + layout.marginWidth = margins; + titleArea.setLayout(layout); + + + GridData layoutData = new GridData(GridData.FILL_HORIZONTAL); + layoutData.verticalAlignment = DWT.TOP; + titleArea.setLayoutData(layoutData); + + // Message label + messageArea = new DialogMessageArea(); + messageArea.createContents(titleArea); + + titleArea.addControlListener(new ControlAdapter() { + /* (non-Javadoc) + * @see dwt.events.ControlAdapter#controlResized(dwt.events.ControlEvent) + */ + public void controlResized(ControlEvent e) { + updateMessage(); + } + }); + + final IPropertyChangeListener fontListener = new IPropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + if (JFaceResources.BANNER_FONT.equals(event.getProperty())) { + updateMessage(); + } + if (JFaceResources.DIALOG_FONT.equals(event.getProperty())) { + updateMessage(); + Font dialogFont = JFaceResources.getDialogFont(); + updateTreeFont(dialogFont); + Control[] children = ((Composite) buttonBar).getChildren(); + for (int i = 0; i < children.length; i++) { + children[i].setFont(dialogFont); + } + } + } + }; + + titleArea.addDisposeListener(new DisposeListener() { + public void widgetDisposed(DisposeEvent event) { + JFaceResources.getFontRegistry().removeListener(fontListener); + } + }); + JFaceResources.getFontRegistry().addListener(fontListener); + messageArea.setTitleLayoutData(createMessageAreaData()); + messageArea.setMessageLayoutData(createMessageAreaData()); + return titleArea; + } + + /** + * Create the layout data for the message area. + * + * @return FormData for the message area. + */ + private FormData createMessageAreaData() { + FormData messageData = new FormData(); + messageData.top = new FormAttachment(0); + messageData.bottom = new FormAttachment(100); + messageData.right = new FormAttachment(100); + messageData.left = new FormAttachment(0); + return messageData; + } + + /** + * @param parent + * the DWT parent for the tree area controls. + * @return the new Control. + * @since 3.0 + */ + protected Control createTreeAreaContents(Composite parent) { + // Build the tree an put it into the composite. + treeViewer = createTreeViewer(parent); + treeViewer.setInput(getPreferenceManager()); + updateTreeFont(JFaceResources.getDialogFont()); + layoutTreeAreaControl(treeViewer.getControl()); + return treeViewer.getControl(); + } + + /** + * Create a new TreeViewer. + * + * @param parent + * the parent Composite. + * @return the TreeViewer. + * @since 3.0 + */ + protected TreeViewer createTreeViewer(Composite parent) { + final TreeViewer viewer = new TreeViewer(parent, DWT.NONE); + addListeners(viewer); + viewer.setLabelProvider(new PreferenceLabelProvider()); + viewer.setContentProvider(new PreferenceContentProvider()); + return viewer; + } + + /** + * Add the listeners to the tree viewer. + * @param viewer + * + * @since 3.1 + */ + protected void addListeners(final TreeViewer viewer) { + viewer.addPostSelectionChangedListener(new ISelectionChangedListener() { + private void handleError() { + try { + // remove the listener temporarily so that the events caused + // by the error handling dont further cause error handling + // to occur. + viewer.removePostSelectionChangedListener(this); + showPageFlippingAbortDialog(); + selectCurrentPageAgain(); + clearSelectedNode(); + } finally { + viewer.addPostSelectionChangedListener(this); + } + } + + public void selectionChanged(SelectionChangedEvent event) { + Object selection = getSingleSelection(event.getSelection()); + if (selection instanceof IPreferenceNode) { + if (!isCurrentPageValid()) { + handleError(); + } else if (!showPage((IPreferenceNode) selection)) { + // Page flipping wasn't successful + handleError(); + } else { + // Everything went well + lastSuccessfulNode = (IPreferenceNode) selection; + } + } + } + }); + ((Tree) viewer.getControl()).addSelectionListener(new SelectionAdapter() { + public void widgetDefaultSelected(final SelectionEvent event) { + ISelection selection = viewer.getSelection(); + if (selection.isEmpty()) { + return; + } + IPreferenceNode singleSelection = getSingleSelection(selection); + bool expanded = viewer.getExpandedState(singleSelection); + viewer.setExpandedState(singleSelection, !expanded); + } + }); + //Register help listener on the tree to use context sensitive help + viewer.getControl().addHelpListener(new HelpListener() { + public void helpRequested(HelpEvent event) { + // call perform help on the current page + if (currentPage !is null) { + currentPage.performHelp(); + } + } + }); + } + + /** + * Find the IPreferenceNode that has data the same id as the + * supplied value. + * + * @param nodeId + * the id to search for. + * @return IPreferenceNode or null if not + * found. + */ + protected IPreferenceNode findNodeMatching(String nodeId) { + List nodes = preferenceManager.getElements(PreferenceManager.POST_ORDER); + for (Iterator i = nodes.iterator(); i.hasNext();) { + IPreferenceNode node = (IPreferenceNode) i.next(); + if (node.getId().equals(nodeId)) { + return node; + } + } + return null; + } + + /** + * Get the last known right side width. + * + * @return the width. + */ + protected int getLastRightWidth() { + return lastTreeWidth; + } + + /** + * Returns the preference mananger used by this preference dialog. + * + * @return the preference mananger + */ + public PreferenceManager getPreferenceManager() { + return preferenceManager; + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.preference.IPreferencePageContainer#getPreferenceStore() + */ + public IPreferenceStore getPreferenceStore() { + return preferenceStore; + } + + /** + * Get the name of the selected item preference + * + * @return String + */ + protected String getSelectedNodePreference() { + return lastPreferenceId; + } + + /** + * @param selection + * the ISelection to examine. + * @return the first element, or null if empty. + */ + protected IPreferenceNode getSingleSelection(ISelection selection) { + if (!selection.isEmpty()) { + IStructuredSelection structured = (IStructuredSelection) selection; + if (structured.getFirstElement() instanceof IPreferenceNode) { + return (IPreferenceNode) structured.getFirstElement(); + } + } + return null; + } + + /** + * @return the TreeViewer for this dialog. + * @since 3.3 + */ + public TreeViewer getTreeViewer() { + return treeViewer; + } + + /** + * Save the values specified in the pages. + *

+ * The default implementation of this framework method saves all pages of + * type PreferencePage (if their store needs saving and is a + * PreferenceStore). + *

+ *

+ * Subclasses may override. + *

+ */ + protected void handleSave() { + Iterator nodes = preferenceManager.getElements(PreferenceManager.PRE_ORDER).iterator(); + while (nodes.hasNext()) { + IPreferenceNode node = (IPreferenceNode) nodes.next(); + IPreferencePage page = node.getPage(); + if (page instanceof PreferencePage) { + // Save now in case tbe workbench does not shutdown cleanly + IPreferenceStore store = ((PreferencePage) page).getPreferenceStore(); + if (store !is null && store.needsSaving() + && store instanceof IPersistentPreferenceStore) { + try { + ((IPersistentPreferenceStore) store).save(); + } catch (IOException e) { + MessageDialog + .openError( + getShell(), + JFaceResources.getString("PreferenceDialog.saveErrorTitle"), //$NON-NLS-1$ + JFaceResources + .format( + "PreferenceDialog.saveErrorMessage", new Object[] { page.getTitle(), e.getMessage() })); //$NON-NLS-1$ + } + } + } + } + } + + /** + * Notifies that the window's close button was pressed, the close menu was + * selected, or the ESCAPE key pressed. + *

+ * The default implementation of this framework method sets the window's + * return code to CANCEL and closes the window using + * close. Subclasses may extend or reimplement. + *

+ */ + protected void handleShellCloseEvent() { + // handle the same as pressing cancel + cancelPressed(); + } + + /** + * Notifies of the pressing of the Help button. + *

+ * The default implementation of this framework method calls + * performHelp on the currently active page. + *

+ */ + protected void helpPressed() { + if (currentPage !is null) { + currentPage.performHelp(); + } + } + + /** + * Returns whether the current page is valid. + * + * @return false if the current page is not valid, or or + * true if the current page is valid or there is no + * current page + */ + protected bool isCurrentPageValid() { + if (currentPage is null) { + return true; + } + return currentPage.isValid(); + } + + /** + * @param control + * the Control to lay out. + * @since 3.0 + */ + protected void layoutTreeAreaControl(Control control) { + GridData gd = new GridData(GridData.FILL_VERTICAL); + gd.widthHint = getLastRightWidth(); + gd.verticalSpan = 1; + control.setLayoutData(gd); + } + + /** + * The preference dialog implementation of this Dialog + * framework method sends performOk to all pages of the + * preference dialog, then calls handleSave on this dialog to + * save any state, and then calls close to close this dialog. + */ + protected void okPressed() { + SafeRunnable.run(new SafeRunnable() { + private bool errorOccurred; + + /* + * (non-Javadoc) + * + * @see dwtx.core.runtime.ISafeRunnable#run() + */ + public void run() { + getButton(IDialogConstants.OK_ID).setEnabled(false); + errorOccurred = false; + bool hasFailedOK = false; + try { + // Notify all the pages and give them a chance to abort + Iterator nodes = preferenceManager.getElements(PreferenceManager.PRE_ORDER) + .iterator(); + while (nodes.hasNext()) { + IPreferenceNode node = (IPreferenceNode) nodes.next(); + IPreferencePage page = node.getPage(); + if (page !is null) { + if (!page.performOk()){ + hasFailedOK = true; + return; + } + } + } + } catch (Exception e) { + handleException(e); + } finally { + //Don't bother closing if the OK failed + if(hasFailedOK){ + setReturnCode(FAILED); + getButton(IDialogConstants.OK_ID).setEnabled(true); + return; + } + + if (!errorOccurred) { + //Give subclasses the choice to save the state of the + //preference pages. + handleSave(); + } + setReturnCode(OK); + close(); + } + } + + /* + * (non-Javadoc) + * + * @see dwtx.core.runtime.ISafeRunnable#handleException(java.lang.Throwable) + */ + public void handleException(Throwable e) { + errorOccurred = true; + + Policy.getLog().log(new Status(IStatus.ERROR, Policy.JFACE, 0, e.toString(), e)); + + clearSelectedNode(); + String message = JFaceResources.getString("SafeRunnable.errorMessage"); //$NON-NLS-1$ + MessageDialog.openError(getShell(), JFaceResources.getString("Error"), message); //$NON-NLS-1$ + + } + }); + } + + /** + * Selects the page determined by lastSuccessfulNode in the + * page hierarchy. + */ + void selectCurrentPageAgain() { + if (lastSuccessfulNode is null) { + return; + } + getTreeViewer().setSelection(new StructuredSelection(lastSuccessfulNode)); + currentPage.setVisible(true); + } + + /** + * Selects the saved item in the tree of preference pages. If it cannot do + * this it saves the first one. + */ + protected void selectSavedItem() { + IPreferenceNode node = findNodeMatching(getSelectedNodePreference()); + if (node is null) { + IPreferenceNode[] nodes = preferenceManager.getRootSubNodes(); + ViewerFilter[] filters = getTreeViewer().getFilters(); + for (int i = 0; i < nodes.length; i++) { + IPreferenceNode selectedNode = nodes[i]; + // See if it passes all filters + for (int j = 0; j < filters.length; j++) { + if (!filters[j].select(this.treeViewer, preferenceManager + .getRoot(), selectedNode)) { + selectedNode = null; + break; + } + } + // if it passes all filters select it + if (selectedNode !is null) { + node = selectedNode; + break; + } + } + } + if (node !is null) { + getTreeViewer().setSelection(new StructuredSelection(node), true); + // Keep focus in tree. See bugs 2692, 2621, and 6775. + getTreeViewer().getControl().setFocus(); + } + } + + /** + * Display the given error message. The currently displayed message is saved + * and will be redisplayed when the error message is set to + * null. + * + * @param newErrorMessage + * the errorMessage to display or null + */ + public void setErrorMessage(String newErrorMessage) { + if (newErrorMessage is null) { + messageArea.clearErrorMessage(); + } else { + messageArea.updateText(newErrorMessage, IMessageProvider.ERROR); + } + } + + /** + * Save the last known tree width. + * + * @param width + * the width. + */ + private void setLastTreeWidth(int width) { + lastTreeWidth = width; + } + + /** + * Set the message text. If the message line currently displays an error, + * the message is stored and will be shown after a call to clearErrorMessage + *

+ * Shortcut for setMessage(newMessage, NONE) + *

+ * + * @param newMessage + * the message, or null to clear the message + */ + public void setMessage(String newMessage) { + setMessage(newMessage, IMessageProvider.NONE); + } + + /** + * Sets the message for this dialog with an indication of what type of + * message it is. + *

+ * The valid message types are one of NONE, + * INFORMATION,WARNING, or + * ERROR. + *

+ *

+ * Note that for backward compatibility, a message of type + * ERROR is different than an error message (set using + * setErrorMessage). An error message overrides the current + * message until the error message is cleared. This method replaces the + * current message and does not affect the error message. + *

+ * + * @param newMessage + * the message, or null to clear the message + * @param newType + * the message type + * @since 2.0 + */ + public void setMessage(String newMessage, int newType) { + messageArea.updateText(newMessage, newType); + } + + /** + * Sets the minimum page size. + * + * @param minWidth + * the minimum page width + * @param minHeight + * the minimum page height + * @see #setMinimumPageSize(Point) + */ + public void setMinimumPageSize(int minWidth, int minHeight) { + minimumPageSize.x = minWidth; + minimumPageSize.y = minHeight; + } + + /** + * Sets the minimum page size. + * + * @param size + * the page size encoded as new Point(width,height) + * @see #setMinimumPageSize(int,int) + */ + public void setMinimumPageSize(Point size) { + minimumPageSize.x = size.x; + minimumPageSize.y = size.y; + } + + /** + * Sets the preference store for this preference dialog. + * + * @param store + * the preference store + * @see #getPreferenceStore + */ + public void setPreferenceStore(IPreferenceStore store) { + Assert.isNotNull(store); + preferenceStore = store; + } + + /** + * Save the currently selected node. + */ + private void setSelectedNode() { + String storeValue = null; + IStructuredSelection selection = (IStructuredSelection) getTreeViewer().getSelection(); + if (selection.size() is 1) { + IPreferenceNode node = (IPreferenceNode) selection.getFirstElement(); + storeValue = node.getId(); + } + setSelectedNodePreference(storeValue); + } + + /** + * Sets the name of the selected item preference. Public equivalent to + * setSelectedNodePreference. + * + * @param pageId + * The identifier for the page + * @since 3.0 + */ + public void setSelectedNode(String pageId) { + setSelectedNodePreference(pageId); + } + + /** + * Sets the name of the selected item preference. + * + * @param pageId + * The identifier for the page + */ + protected void setSelectedNodePreference(String pageId) { + lastPreferenceId = pageId; + } + + /** + * 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 preferred = getShell().getBounds(); + preferred.width = width; + preferred.height = height; + getShell().setBounds(getConstrainedShellBounds(preferred)); + } + + /** + * Shows the preference page corresponding to the given preference node. + * Does nothing if that page is already current. + * + * @param node + * the preference node, or null if none + * @return true if the page flip was successful, and + * false is unsuccessful + */ + protected bool showPage(IPreferenceNode node) { + if (node is null) { + return false; + } + // Create the page if nessessary + if (node.getPage() is null) { + createPage(node); + } + if (node.getPage() is null) { + return false; + } + IPreferencePage newPage = getPage(node); + if (newPage is currentPage) { + return true; + } + if (currentPage !is null) { + if (!currentPage.okToLeave()) { + return false; + } + } + IPreferencePage oldPage = currentPage; + currentPage = newPage; + // Set the new page's container + currentPage.setContainer(this); + // Ensure that the page control has been created + // (this allows lazy page control creation) + if (currentPage.getControl() is null) { + final bool[] failed = { false }; + SafeRunnable.run(new ISafeRunnable() { + public void handleException(Throwable e) { + failed[0] = true; + } + + public void run() { + createPageControl(currentPage, pageContainer); + } + }); + if (failed[0]) { + return false; + } + // the page is responsible for ensuring the created control is + // accessable + // via getControl. + Assert.isNotNull(currentPage.getControl()); + } + // Force calculation of the page's description label because + // label can be wrapped. + final Point[] size = new Point[1]; + final Point failed = new Point(-1, -1); + SafeRunnable.run(new ISafeRunnable() { + public void handleException(Throwable e) { + size[0] = failed; + } + + public void run() { + size[0] = currentPage.computeSize(); + } + }); + if (size[0].equals(failed)) { + return false; + } + Point contentSize = size[0]; + // Do we need resizing. Computation not needed if the + // first page is inserted since computing the dialog's + // size is done by calling dialog.open(). + // Also prevent auto resize if the user has manually resized + Shell shell = getShell(); + Point shellSize = shell.getSize(); + if (oldPage !is null) { + Rectangle rect = pageContainer.getClientArea(); + Point containerSize = new Point(rect.width, rect.height); + int hdiff = contentSize.x - containerSize.x; + int vdiff = contentSize.y - containerSize.y; + if ((hdiff > 0 || vdiff > 0) && shellSize.equals(lastShellSize)) { + hdiff = Math.max(0, hdiff); + vdiff = Math.max(0, vdiff); + setShellSize(shellSize.x + hdiff, shellSize.y + vdiff); + lastShellSize = shell.getSize(); + if (currentPage.getControl().getSize().x is 0) { + currentPage.getControl().setSize(containerSize); + } + + } else { + currentPage.setSize(containerSize); + } + } + + scrolled.setMinSize(contentSize); + // Ensure that all other pages are invisible + // (including ones that triggered an exception during + // their creation). + Control[] children = pageContainer.getChildren(); + Control currentControl = currentPage.getControl(); + for (int i = 0; i < children.length; i++) { + if (children[i] !is currentControl) { + children[i].setVisible(false); + } + } + // Make the new page visible + currentPage.setVisible(true); + if (oldPage !is null) { + oldPage.setVisible(false); + } + // update the dialog controls + update(); + return true; + } + + /** + * Create the page for the node. + * @param node + * + * @since 3.1 + */ + protected void createPage(IPreferenceNode node) { + node.createPage(); + } + + /** + * Get the page for the node. + * @param node + * @return IPreferencePage + * + * @since 3.1 + */ + protected IPreferencePage getPage(IPreferenceNode node) { + return node.getPage(); + } + + /** + * Shows the "Page Flipping abort" dialog. + */ + void showPageFlippingAbortDialog() { + MessageDialog.openError(getShell(), JFaceResources + .getString("AbortPageFlippingDialog.title"), //$NON-NLS-1$ + JFaceResources.getString("AbortPageFlippingDialog.message")); //$NON-NLS-1$ + } + + /** + * Updates this dialog's controls to reflect the current page. + */ + protected void update() { + // Update the title bar + updateTitle(); + // Update the message line + updateMessage(); + // Update the buttons + updateButtons(); + //Saved the selected node in the preferences + setSelectedNode(); + firePageChanged(new PageChangedEvent(this, getCurrentPage())); + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.preference.IPreferencePageContainer#updateButtons() + */ + public void updateButtons() { + okButton.setEnabled(isCurrentPageValid()); + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.preference.IPreferencePageContainer#updateMessage() + */ + public void updateMessage() { + String message = null; + String errorMessage = null; + if(currentPage !is null){ + message = currentPage.getMessage(); + errorMessage = currentPage.getErrorMessage(); + } + int messageType = IMessageProvider.NONE; + if (message !is null && currentPage instanceof IMessageProvider) { + messageType = ((IMessageProvider) currentPage).getMessageType(); + } + + if (errorMessage is null){ + if (showingError) { + // we were previously showing an error + showingError = false; + } + } + else { + message = errorMessage; + messageType = IMessageProvider.ERROR; + if (!showingError) { + // we were not previously showing an error + showingError = true; + } + } + messageArea.updateText(message,messageType); + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.preference.IPreferencePageContainer#updateTitle() + */ + public void updateTitle() { + if(currentPage is null) { + return; + } + messageArea.showTitle(currentPage.getTitle(), currentPage.getImage()); + } + + /** + * Update the tree to use the specified Font. + * + * @param dialogFont + * the Font to use. + * @since 3.0 + */ + protected void updateTreeFont(Font dialogFont) { + getTreeViewer().getControl().setFont(dialogFont); + } + + /** + * Returns the currentPage. + * @return IPreferencePage + * @since 3.1 + */ + protected IPreferencePage getCurrentPage() { + return currentPage; + } + + /** + * Sets the current page. + * @param currentPage + * + * @since 3.1 + */ + protected void setCurrentPage(IPreferencePage currentPage) { + this.currentPage = currentPage; + } + + /** + * Set the treeViewer. + * @param treeViewer + * + * @since 3.1 + */ + protected void setTreeViewer(TreeViewer treeViewer) { + this.treeViewer = treeViewer; + } + + /** + * Get the composite that is showing the page. + * + * @return Composite. + * + * @since 3.1 + */ + protected Composite getPageContainer() { + return this.pageContainer; + } + + /** + * Set the composite that is showing the page. + * @param pageContainer Composite + * + * @since 3.1 + */ + protected void setPageContainer(Composite pageContainer) { + this.pageContainer = pageContainer; + } + /** + * Create the page control for the supplied page. + * + * @param page - the preference page to be shown + * @param parent - the composite to parent the page + * + * @since 3.1 + */ + protected void createPageControl(IPreferencePage page, Composite parent) { + page.createControl(parent); + } + + /** + * @see dwtx.jface.dialogs.IPageChangeProvider#getSelectedPage() + * + * @since 3.1 + */ + public Object getSelectedPage() { + return getCurrentPage(); + } + + /** + * @see dwtx.jface.dialogs.IPageChangeProvider#addPageChangedListener(dwtx.jface.dialogs.IPageChangedListener) + * @since 3.1 + */ + public void addPageChangedListener(IPageChangedListener listener) { + pageChangedListeners.add(listener); + } + + /** + * @see dwtx.jface.dialogs.IPageChangeProvider#removePageChangedListener(dwtx.jface.dialogs.IPageChangedListener) + * @since 3.1 + */ + 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); + } + }); + } + } +} +++/ \ No newline at end of file diff -r a3ff22a98bef -r 6c14e54dfc11 dwtx/jface/resource/AbstractResourceManager.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/resource/AbstractResourceManager.d Sat Mar 29 02:25:12 2008 +0100 @@ -0,0 +1,160 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +module dwtx.jface.resource.AbstractResourceManager; + +import dwtx.jface.resource.ResourceManager; +import dwtx.jface.resource.DeviceResourceDescriptor; + +import tango.util.collection.HashMap; +import tango.util.collection.model.Map; + +import dwt.dwthelper.utils; + +/** + * Abstract implementation of ResourceManager. Maintains reference counts for all previously + * allocated DWT resources. Delegates to the abstract method allocate(...) the first time a resource + * is referenced and delegates to the abstract method deallocate(...) the last time a reference is + * removed. + * + * @since 3.1 + */ +abstract class AbstractResourceManager : ResourceManager { + + /** + * Map of ResourceDescriptor onto RefCount. (null when empty) + */ + private HashMap!(DeviceResourceDescriptor,RefCount) map = null; + + /** + * Holds a reference count for a previously-allocated resource + */ + private static class RefCount { + Object resource; + int count = 1; + + this(Object resource) { + this.resource = resource; + } + } + + /** + * Called the first time a resource is requested. Should allocate and return a resource + * of the correct type. + * + * @since 3.1 + * + * @param descriptor identifier for the resource to allocate + * @return the newly allocated resource + * @throws DeviceResourceException Thrown when allocation of an DWT device resource fails + */ + protected abstract Object allocate(DeviceResourceDescriptor descriptor); + + /** + * Called the last time a resource is dereferenced. Should release any resources reserved by + * allocate(...). + * + * @since 3.1 + * + * @param resource resource being deallocated + * @param descriptor identifier for the resource + */ + protected abstract void deallocate(Object resource, DeviceResourceDescriptor descriptor); + + /* (non-Javadoc) + * @see ResourceManager#create(DeviceResourceDescriptor) + */ + public final Object create(DeviceResourceDescriptor descriptor){ + + // Lazily allocate the map + if (map is null) { + map = new HashMap!(DeviceResourceDescriptor,RefCount); + } + + // Get the current reference count + RefCount count = map.get(descriptor); + if (count !is null) { + // If this resource already exists, increment the reference count and return + // the existing resource. + count.count++; + return count.resource; + } + + // Allocate and return a new resource (with ref count = 1) + Object resource = allocate(descriptor); + + count = new RefCount(resource); + map.add(descriptor, count); + + return resource; + } + + /* (non-Javadoc) + * @see ResourceManager#destroy(DeviceResourceDescriptor) + */ + public final void destroy(DeviceResourceDescriptor descriptor) { + // If the map is empty (null) then there are no resources to dispose + if (map is null) { + return; + } + + // Find the existing resource + RefCount count = map.get(descriptor); + if (count !is null) { + // If the resource exists, decrement the reference count. + count.count--; + if (count.count is 0) { + // If this was the last reference, deallocate it. + deallocate(count.resource, descriptor); + map.removeKey(descriptor); + } + } + + // Null out the map when empty to save a small amount of memory + if (map.drained()) { + map = null; + } + } + + /** + * Deallocates any resources allocated by this registry that have not yet been + * deallocated. + * + * @since 3.1 + */ + public void dispose() { + super.dispose(); + + if (map is null) { + return; + } + + foreach( key, val; map ){ + deallocate(val.resource, key); + } + + map = null; + } + + /* (non-Javadoc) + * @see dwtx.jface.resource.ResourceManager#find(dwtx.jface.resource.DeviceResourceDescriptor) + */ + public Object find(DeviceResourceDescriptor descriptor) { + if (map is null) { + return null; + } + RefCount refCount = cast(RefCount)map.get(descriptor); + if (refCount is null) + return null; + return refCount.resource; + } +} diff -r a3ff22a98bef -r 6c14e54dfc11 dwtx/jface/resource/ColorRegistry.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/resource/ColorRegistry.d Sat Mar 29 02:25:12 2008 +0100 @@ -0,0 +1,302 @@ +/******************************************************************************* + * Copyright (c) 2003, 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 + *******************************************************************************/ +module dwtx.jface.resource.ColorRegistry; + +import dwtx.jface.resource.ResourceRegistry; +import dwtx.jface.resource.ColorDescriptor; + +import tango.util.collection.ArraySeq; +import tango.util.collection.HashMap; +import tango.util.collection.HashSet; +import tango.util.collection.model.Map; +import tango.util.collection.model.Set; +import tango.util.collection.model.SetView; +import tango.util.collection.model.Seq; + +import dwt.graphics.Color; +import dwt.graphics.RGB; +import dwt.widgets.Display; +import dwtx.core.runtime.Assert; + +import dwt.dwthelper.utils; +import dwt.dwthelper.Runnable; + +/** + * A color registry maintains a mapping between symbolic color names and DWT + * Colors. + *

+ * A color registry owns all of the Color objects registered with + * it, and automatically disposes of them when the DWT Display that creates the + * Colors is disposed. Because of this, clients do not need to + * (indeed, must not attempt to) dispose of Color objects + * themselves. + *

+ *

+ * Methods are provided for registering listeners that will be kept + * apprised of changes to list of registed colors. + *

+ *

+ * Clients may instantiate this class (it was not designed to be subclassed). + *

+ * + * @since 3.0 + */ +public class ColorRegistry : ResourceRegistry { + + /** + * This registries Display. All colors will be allocated using + * it. + */ + protected Display display; + + /** + * Collection of Color that are now stale to be disposed when + * it is safe to do so (i.e. on shutdown). + */ + private Seq!(Color) staleColors; + + /** + * Table of known colors, keyed by symbolic color name (key type: String, + * value type: dwt.graphics.Color. + */ + private Map!(String,Color) stringToColor; + + /** + * Table of known color data, keyed by symbolic color name (key type: + * String, value type: dwt.graphics.RGB). + */ + private Map!(String,RGB) stringToRGB; + + /** + * Runnable that cleans up the manager on disposal of the display. + */ + protected Runnable displayRunnable; + private void init_displayRunnable(){ + displayRunnable = new class Runnable { + public void run() { + clearCaches(); + } + }; + } + + /** + * Create a new instance of the receiver that is hooked to the current + * display. + * + * @see dwt.widgets.Display#getCurrent() + */ + public this() { + this(Display.getCurrent(), true); + } + + /** + * Create a new instance of the receiver. + * + * @param display the Display to hook into. + */ + public this(Display display) { + this (display, true); + } + + /** + * Create a new instance of the receiver. + * + * @param display the Display to hook into + * @param cleanOnDisplayDisposal + * whether all fonts allocated by this ColorRegistry + * should be disposed when the display is disposed + * @since 3.1 + */ + public this(Display display, bool cleanOnDisplayDisposal) { + staleColors = new ArraySeq!(Color); + stringToColor = new HashMap!(String,Color); + stringToRGB = new HashMap!(String,RGB); + init_displayRunnable(); + Assert.isNotNull(display); + this.display = display; + if (cleanOnDisplayDisposal) { + hookDisplayDispose(); + } + } + + /** + * Create a new Color on the receivers Display. + * + * @param rgb the RGB data for the color. + * @return the new Color object. + * + * @since 3.1 + */ + private Color createColor(RGB rgb) { + return new Color(display, rgb); + } + + /** + * Dispose of all of the Colors in this iterator. + * + * @param iterator over Collection of Color + */ + /+ + private void disposeColors(Iterator iterator) { + while (iterator.hasNext()) { + Object next = iterator.next(); + ((Color) next).dispose(); + } + } + +/ + + /** + * Returns the color associated with the given symbolic color + * name, or null if no such definition exists. + * + * @param symbolicName symbolic color name + * @return the Color or null + */ + public Color get(String symbolicName) { + + Assert.isNotNull(symbolicName); + auto result1 = stringToColor.get(symbolicName); + if (result1 !is null) { + return result1; + } + + Color color = null; + + auto result = stringToRGB.get(symbolicName); + if (result is null) { + return null; + } + + color = createColor(result); + + stringToColor.add(symbolicName, color); + + return color; + } + + /* (non-Javadoc) + * @see dwtx.jface.resource.ResourceRegistry#getKeySet() + */ + public SetView!(String) getKeySet() { + auto res = new HashSet!(String); + foreach( k,v; stringToRGB ){ + res.add(k); + } + return res; + } + + /** + * Returns the color data associated with the given symbolic color name. + * + * @param symbolicName symbolic color name. + * @return the RGB data. + */ + public RGB getRGB(String symbolicName) { + Assert.isNotNull(symbolicName); + return stringToRGB.get(symbolicName); + } + + /** + * Returns the color descriptor associated with the given symbolic color name. + * @since 3.1 + * + * @param symbolicName + * @return the color descriptor associated with the given symbolic color name. + */ + public ColorDescriptor getColorDescriptor(String symbolicName) { + return ColorDescriptor.createFrom(getRGB(symbolicName)); + } + + /* (non-Javadoc) + * @see dwtx.jface.resource.ResourceRegistry#clearCaches() + */ + protected void clearCaches() { + foreach( k, v; stringToColor ){ + v.dispose(); + } + foreach( v; staleColors ){ + v.dispose(); + } +// disposeColors(stringToColor.values().iterator()); +// disposeColors(staleColors.iterator()); + stringToColor.clear(); + staleColors.clear(); + } + + /* (non-Javadoc) + * @see dwtx.jface.resource.ResourceRegistry#hasValueFor(java.lang.String) + */ + public bool hasValueFor(String colorKey) { + return stringToRGB.containsKey(colorKey); + } + + /** + * Hook a dispose listener on the DWT display. + */ + private void hookDisplayDispose() { + display.disposeExec(displayRunnable); + } + + /** + * Adds (or replaces) a color to this color registry under the given + * symbolic name. + *

+ * A property change event is reported whenever the mapping from a symbolic + * name to a color changes. The source of the event is this registry; the + * property name is the symbolic color name. + *

+ * + * @param symbolicName the symbolic color name + * @param colorData an RGB object + */ + public void put(String symbolicName, RGB colorData) { + put(symbolicName, colorData, true); + } + + /** + * Adds (or replaces) a color to this color registry under the given + * symbolic name. + *

+ * A property change event is reported whenever the mapping from a symbolic + * name to a color changes. The source of the event is this registry; the + * property name is the symbolic color name. + *

+ * + * @param symbolicName the symbolic color name + * @param colorData an RGB object + * @param update - fire a color mapping changed if true. False if this + * method is called from the get method as no setting has + * changed. + */ + private void put(String symbolicName, RGB colorData, bool update) { + + Assert.isNotNull(symbolicName); + Assert.isNotNull(colorData); + + RGB existing = stringToRGB.get(symbolicName); + if (colorData.opEquals(existing)) { + return; + } + + Color oldColor = stringToColor.get(symbolicName); + stringToColor.removeKey(symbolicName); + stringToRGB.add(symbolicName, colorData); + if (update) { + fireMappingChanged(symbolicName, existing, colorData); + } + + if (oldColor !is null) { + staleColors.append(oldColor); + } + } +} diff -r a3ff22a98bef -r 6c14e54dfc11 dwtx/jface/resource/CompositeImageDescriptor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/resource/CompositeImageDescriptor.d Sat Mar 29 02:25:12 2008 +0100 @@ -0,0 +1,218 @@ +/******************************************************************************* + * 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 + * Port to the D programming language: + * Frank Benoit + *******************************************************************************/ +module dwtx.jface.resource.CompositeImageDescriptor; + +import dwtx.jface.resource.ImageDescriptor; + +import dwt.graphics.ImageData; +import dwt.graphics.PaletteData; +import dwt.graphics.Point; +import dwt.graphics.RGB; + +import dwt.dwthelper.utils; + +/** + * Abstract base class for image descriptors that synthesize an image from other + * images in order to simulate the effect of custom drawing. For example, this + * could be used to superimpose a red bar dexter symbol across an image to + * indicate that something was disallowed. + *

+ * Subclasses must implement the getSize and fill + * methods. Little or no work happens until the image descriptor's image is + * actually requested by a call to createImage (or to + * getImageData directly). + *

+ */ +public abstract class CompositeImageDescriptor : ImageDescriptor { + + /** + * The image data for this composite image. + */ + private ImageData imageData; + + /** + * Constructs an uninitialized composite image. + */ + protected this() { + } + + /** + * Draw the composite images. + *

+ * Subclasses must implement this framework method to paint images within + * the given bounds using one or more calls to the drawImage + * framework method. + *

+ * + * @param width + * the width + * @param height + * the height + */ + protected abstract void drawCompositeImage(int width, int height); + + /** + * Draws the given source image data into this composite image at the given + * position. + *

+ * Call this internal framework method to superimpose another image atop + * this composite image. + *

+ * + * @param src + * the source image data + * @param ox + * the x position + * @param oy + * the y position + */ + final protected void drawImage(ImageData src, int ox, int oy) { + ImageData dst = imageData; + PaletteData srcPalette = src.palette; + ImageData srcMask = null; + int alphaMask = 0, alphaShift = 0; + if (src.maskData !is null) { + srcMask = src.getTransparencyMask (); + if (src.depth is 32) { + alphaMask = ~(srcPalette.redMask | srcPalette.greenMask | srcPalette.blueMask); + while (alphaMask !is 0 && ((alphaMask >>> alphaShift) & 1) is 0) alphaShift++; + } + } + for (int srcY = 0, dstY = srcY + oy; srcY < src.height; srcY++, dstY++) { + for (int srcX = 0, dstX = srcX + ox; srcX < src.width; srcX++, dstX++) { + if (!(0 <= dstX && dstX < dst.width && 0 <= dstY && dstY < dst.height)) continue; + int srcPixel = src.getPixel(srcX, srcY); + int srcAlpha = 255; + if (src.maskData !is null) { + if (src.depth is 32) { + srcAlpha = (srcPixel & alphaMask) >>> alphaShift; + if (srcAlpha is 0) { + srcAlpha = srcMask.getPixel(srcX, srcY) !is 0 ? 255 : 0; + } + } else { + if (srcMask.getPixel(srcX, srcY) is 0) srcAlpha = 0; + } + } else if (src.transparentPixel !is -1) { + if (src.transparentPixel is srcPixel) srcAlpha = 0; + } else if (src.alpha !is -1) { + srcAlpha = src.alpha; + } else if (src.alphaData !is null) { + srcAlpha = src.getAlpha(srcX, srcY); + } + if (srcAlpha is 0) continue; + int srcRed, srcGreen, srcBlue; + if (srcPalette.isDirect) { + srcRed = srcPixel & srcPalette.redMask; + srcRed = (srcPalette.redShift < 0) ? srcRed >>> -srcPalette.redShift : srcRed << srcPalette.redShift; + srcGreen = srcPixel & srcPalette.greenMask; + srcGreen = (srcPalette.greenShift < 0) ? srcGreen >>> -srcPalette.greenShift : srcGreen << srcPalette.greenShift; + srcBlue = srcPixel & srcPalette.blueMask; + srcBlue = (srcPalette.blueShift < 0) ? srcBlue >>> -srcPalette.blueShift : srcBlue << srcPalette.blueShift; + } else { + RGB rgb = srcPalette.getRGB(srcPixel); + srcRed = rgb.red; + srcGreen = rgb.green; + srcBlue = rgb.blue; + } + int dstRed, dstGreen, dstBlue, dstAlpha; + if (srcAlpha is 255) { + dstRed = srcRed; + dstGreen = srcGreen; + dstBlue= srcBlue; + dstAlpha = srcAlpha; + } else { + int dstPixel = dst.getPixel(dstX, dstY); + dstAlpha = dst.getAlpha(dstX, dstY); + dstRed = (dstPixel & 0xFF) >>> 0; + dstGreen = (dstPixel & 0xFF00) >>> 8; + dstBlue = (dstPixel & 0xFF0000) >>> 16; + dstRed += (srcRed - dstRed) * srcAlpha / 255; + dstGreen += (srcGreen - dstGreen) * srcAlpha / 255; + dstBlue += (srcBlue - dstBlue) * srcAlpha / 255; + dstAlpha += (srcAlpha - dstAlpha) * srcAlpha / 255; + } + dst.setPixel(dstX, dstY, ((dstRed & 0xFF) << 0) | ((dstGreen & 0xFF) << 8) | ((dstBlue & 0xFF) << 16)); + dst.setAlpha(dstX, dstY, dstAlpha); + } + } + } + + /* + * (non-Javadoc) Method declared on ImageDesciptor. + */ + public ImageData getImageData() { + Point size = getSize(); + + /* Create a 24 bit image data with alpha channel */ + imageData = new ImageData(size.x, size.y, 24, new PaletteData(0xFF, 0xFF00, 0xFF0000)); + imageData.alphaData = new byte[imageData.width * imageData.height]; + + drawCompositeImage(size.x, size.y); + + /* Detect minimum transparency */ + bool transparency = false; + byte[] alphaData = imageData.alphaData; + for (int i = 0; i < alphaData.length; i++) { + int alpha = alphaData[i] & 0xFF; + if (!(alpha is 0 || alpha is 255)) { + /* Full alpha channel transparency */ + return imageData; + } + if (!transparency && alpha is 0) transparency = true; + } + if (transparency) { + /* Reduce to 1-bit alpha channel transparency */ + PaletteData palette = new PaletteData([new RGB(0, 0, 0), new RGB(255, 255, 255)]); + ImageData mask = new ImageData(imageData.width, imageData.height, 1, palette); + for (int y = 0; y < mask.height; y++) { + for (int x = 0; x < mask.width; x++) { + mask.setPixel(x, y, imageData.getAlpha(x, y) is 255 ? 1 : 0); + } + } + } else { + /* no transparency */ + imageData.alphaData = null; + } + return imageData; + } + + + /** + * Return the transparent pixel for the receiver. + * NOTE This value is not currently in use in the + * default implementation. + * @return int + * @since 3.3 + */ + protected int getTransparentPixel() { + return 0; + } + + /** + * Return the size of this composite image. + *

+ * Subclasses must implement this framework method. + *

+ * + * @return the x and y size of the image expressed as a point object + */ + protected abstract Point getSize(); + + /** + * @param imageData The imageData to set. + * @since 3.3 + */ + protected void setImageData(ImageData imageData) { + this.imageData = imageData; + } +} diff -r a3ff22a98bef -r 6c14e54dfc11 dwtx/jface/resource/DeviceResourceManager.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/resource/DeviceResourceManager.d Sat Mar 29 02:25:12 2008 +0100 @@ -0,0 +1,94 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +module dwtx.jface.resource.DeviceResourceManager; + +import dwtx.jface.resource.AbstractResourceManager; +import dwtx.jface.resource.DeviceResourceDescriptor; +import dwtx.jface.resource.ImageDescriptor; + +import dwt.graphics.Device; +import dwt.graphics.Image; + +import dwt.dwthelper.utils; + +/** + * Manages DWT resources for a particular device. + * + *

+ * IMPORTANT: in most cases clients should use a LocalResourceManager instead of a + * DeviceResourceManager. To create a resource manager on a particular display, + * use new LocalResourceManager(JFaceResources.getResources(myDisplay)). + * DeviceResourceManager should only be used directly when managing + * resources for a device other than a Display (such as a printer). + *

+ * + * @see LocalResourceManager + * + * @since 3.1 + */ +public final class DeviceResourceManager : AbstractResourceManager { + + private Device device; + private Image missingImage; + + /* (non-Javadoc) + * @see dwtx.jface.resource.ResourceManager#getDevice() + */ + public Device getDevice() { + return device; + } + + /** + * Creates a new registry for the given device. + * + * @param device device to manage + */ + public this(Device device) { + this.device = device; + } + + /* (non-Javadoc) + * @see dwtx.jface.resource.AbstractResourceManager#allocate(dwtx.jface.resource.DeviceResourceDescriptor) + */ + protected Object allocate(DeviceResourceDescriptor descriptor){ + return descriptor.createResource(device); + } + + /* (non-Javadoc) + * @see dwtx.jface.resource.AbstractResourceManager#deallocate(java.lang.Object, dwtx.jface.resource.DeviceResourceDescriptor) + */ + protected void deallocate(Object resource, DeviceResourceDescriptor descriptor) { + descriptor.destroyResource(resource); + } + + /* (non-Javadoc) + * @see dwtx.jface.resource.ResourceManager#getDefaultImage() + */ + protected Image getDefaultImage() { + if (missingImage is null) { + missingImage = ImageDescriptor.getMissingImageDescriptor().createImage(); + } + return missingImage; + } + + /* (non-Javadoc) + * @see dwtx.jface.resource.AbstractResourceManager#dispose() + */ + public void dispose() { + super.dispose(); + if (missingImage !is null) { + missingImage.dispose(); + missingImage = null; + } + } +} diff -r a3ff22a98bef -r 6c14e54dfc11 dwtx/jface/resource/JFaceColors.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/resource/JFaceColors.d Sat Mar 29 02:25:12 2008 +0100 @@ -0,0 +1,148 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +module dwtx.jface.resource.JFaceColors; + +import dwtx.jface.resource.JFaceResources; + +import dwt.DWT; +import dwt.graphics.Color; +import dwt.widgets.Control; +import dwt.widgets.Display; +import dwtx.jface.preference.JFacePreferences; + +import dwt.dwthelper.utils; + +/** + * JFaceColors is the class that stores references + * to all of the colors used by JFace. + */ +public class JFaceColors { + + /** + * @param display the display the color is from + * @return the Color used for banner backgrounds + * @see DWT#COLOR_LIST_BACKGROUND + * @see Display#getSystemColor(int) + */ + public static Color getBannerBackground(Display display) { + return display.getSystemColor(DWT.COLOR_LIST_BACKGROUND); + } + + /** + * @param display the display the color is from + * @return the Color used for banner foregrounds + * @see DWT#COLOR_LIST_FOREGROUND + * @see Display#getSystemColor(int) + */ + public static Color getBannerForeground(Display display) { + return display.getSystemColor(DWT.COLOR_LIST_FOREGROUND); + } + + /** + * @param display the display the color is from + * @return the background Color for widgets that display errors. + * @see DWT#COLOR_WIDGET_BACKGROUND + * @see Display#getSystemColor(int) + */ + public static Color getErrorBackground(Display display) { + return display.getSystemColor(DWT.COLOR_WIDGET_BACKGROUND); + } + + /** + * @param display the display the color is from + * @return the border Color for widgets that display errors. + * @see DWT#COLOR_WIDGET_DARK_SHADOW + * @see Display#getSystemColor(int) + */ + public static Color getErrorBorder(Display display) { + return display.getSystemColor(DWT.COLOR_WIDGET_DARK_SHADOW); + } + + /** + * @param display the display the color is from + * @return the default color to use for displaying errors. + * @see ColorRegistry#get(String) + * @see JFacePreferences#ERROR_COLOR + */ + public static Color getErrorText(Display display) { + return JFaceResources.getColorRegistry().get( + JFacePreferences.ERROR_COLOR); + } + + /** + * @param display the display the color is from + * @return the default color to use for displaying hyperlinks. + * @see ColorRegistry#get(String) + * @see JFacePreferences#HYPERLINK_COLOR + */ + public static Color getHyperlinkText(Display display) { + return JFaceResources.getColorRegistry().get( + JFacePreferences.HYPERLINK_COLOR); + } + + /** + * @param display the display the color is from + * @return the default color to use for displaying active hyperlinks. + * @see ColorRegistry#get(String) + * @see JFacePreferences#ACTIVE_HYPERLINK_COLOR + */ + public static Color getActiveHyperlinkText(Display display) { + return JFaceResources.getColorRegistry().get( + JFacePreferences.ACTIVE_HYPERLINK_COLOR); + } + + /** + * Clear out the cached color for name. This is generally + * done when the color preferences changed and any cached colors + * may be disposed. Users of the colors in this class should add a IPropertyChangeListener + * to detect when any of these colors change. + * @param colorName name of the color + * + * @deprecated JFaceColors no longer maintains a cache of colors. This job + * is now handled by the ColorRegistry. + */ + public static void clearColor(String colorName) { + //no-op + } + + /** + * Dispose of all allocated colors. Called on workbench + * shutdown. + * + * @deprecated JFaceColors no longer maintains a cache of colors. This job + * is now handled by the ColorRegistry. + */ + public static void disposeColors() { + //no-op + } + + /** + * Set the foreground and background colors of the + * control to the specified values. If the values are + * null than ignore them. + * @param control the control the foreground and/or background color should be set + * + * @param foreground Color the foreground color (maybe null) + * @param background Color the background color (maybe null) + */ + public static void setColors(Control control, Color foreground, + Color background) { + if (foreground !is null) { + control.setForeground(foreground); + } + if (background !is null) { + control.setBackground(background); + } + } + +} diff -r a3ff22a98bef -r 6c14e54dfc11 dwtx/jface/resource/JFaceResources.d --- a/dwtx/jface/resource/JFaceResources.d Sat Mar 29 01:25:27 2008 +0100 +++ b/dwtx/jface/resource/JFaceResources.d Sat Mar 29 02:25:12 2008 +0100 @@ -15,26 +15,13 @@ import dwtx.jface.resource.FontRegistry; import dwtx.jface.resource.ImageRegistry; import dwtx.jface.resource.ResourceManager; - -import dwt.graphics.Font; -import dwt.widgets.Display; +import dwtx.jface.resource.ColorRegistry; +import dwtx.jface.resource.FontDescriptor; +import dwtx.jface.resource.DeviceResourceManager; +import dwtx.jface.resource.ImageDescriptor; -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; -import java.util.HashMap; -import java.util.Map; -import java.util.MissingResourceException; -import java.util.ResourceBundle; +import tango.util.collection.HashMap; +import tango.util.collection.model.Map; import dwt.graphics.Font; import dwt.graphics.Image; @@ -45,6 +32,10 @@ import dwtx.jface.preference.PreferenceDialog; import dwtx.jface.wizard.Wizard; +import dwt.dwthelper.utils; +import dwt.dwthelper.Runnable; +import dwt.dwthelper.ResourceBundle; +import tango.text.convert.Format; /** * Utility methods to access JFace-specific resources. *

@@ -66,25 +57,30 @@ /** * The path to the icons in the resources. */ - private final static String ICONS_PATH = "$nl$/icons/full/";//$NON-NLS-1$ + private const static String ICONS_PATH = "$nl$/icons/full/";//$NON-NLS-1$ /** * Map of Display onto DeviceResourceManager. Holds all the resources for * the associated display. */ - private static final Map registries = new HashMap(); + private static Map!(Display,ResourceManager) registries; + static this(){ + registries = new HashMap!(Display,ResourceManager); + } /** * The symbolic font name for the banner font (value * "dwtx.jface.bannerfont"). */ - public static final String BANNER_FONT = "dwtx.jface.bannerfont"; //$NON-NLS-1$ + public static const String BANNER_FONT = "dwtx.jface.bannerfont"; //$NON-NLS-1$ /** * The JFace resource bundle; eagerly initialized. */ - private static final ResourceBundle bundle = ResourceBundle - .getBundle("dwtx.jface.messages"); //$NON-NLS-1$ + private static /+final+/ ResourceBundle bundle; + static this(){ + bundle = ResourceBundle.getBundle("dwtx.jface.messages"); //$NON-NLS-1$ + } /** * The JFace color registry; null until lazily initialized or @@ -96,13 +92,13 @@ * The symbolic font name for the standard font (value * "dwtx.jface.defaultfont"). */ - public static final String DEFAULT_FONT = "dwtx.jface.defaultfont"; //$NON-NLS-1$ + public static const String DEFAULT_FONT = "dwtx.jface.defaultfont"; //$NON-NLS-1$ /** * The symbolic font name for the dialog font (value * "dwtx.jface.dialogfont"). */ - public static final String DIALOG_FONT = "dwtx.jface.dialogfont"; //$NON-NLS-1$ + public static const String DIALOG_FONT = "dwtx.jface.dialogfont"; //$NON-NLS-1$ /** * The JFace font registry; null until lazily initialized or @@ -114,7 +110,7 @@ * The symbolic font name for the header font (value * "dwtx.jface.headerfont"). */ - public static final String HEADER_FONT = "dwtx.jface.headerfont"; //$NON-NLS-1$ + public static const String HEADER_FONT = "dwtx.jface.headerfont"; //$NON-NLS-1$ /** * The JFace image registry; null until lazily initialized. @@ -125,7 +121,7 @@ * The symbolic font name for the text font (value * "dwtx.jface.textfont"). */ - public static final String TEXT_FONT = "dwtx.jface.textfont"; //$NON-NLS-1$ + public static const String TEXT_FONT = "dwtx.jface.textfont"; //$NON-NLS-1$ /** * The symbolic font name for the viewer font (value @@ -133,7 +129,7 @@ * * @deprecated This font is not in use */ - public static final String VIEWER_FONT = "dwtx.jface.viewerfont"; //$NON-NLS-1$ + public static const String VIEWER_FONT = "dwtx.jface.viewerfont"; //$NON-NLS-1$ /** * The symbolic font name for the window font (value @@ -141,7 +137,7 @@ * * @deprecated This font is not in use */ - public static final String WINDOW_FONT = "dwtx.jface.windowfont"; //$NON-NLS-1$ + public static const String WINDOW_FONT = "dwtx.jface.windowfont"; //$NON-NLS-1$ /** * Returns the formatted message for the given key in JFace's resource @@ -154,7 +150,7 @@ * @return the string */ public static String format(String key, Object[] args) { - return MessageFormat.format(getString(key), args); + return Format(getString(key), args); } /** @@ -208,14 +204,17 @@ * display to query * @return the global resource manager for the given display */ - public static ResourceManager getResources(final Display toQuery) { - ResourceManager reg = (ResourceManager) registries.get(toQuery); + public static ResourceManager getResources(Display toQuery) { + ResourceManager reg = cast(ResourceManager) registries.get(toQuery); if (reg is null) { - final DeviceResourceManager mgr = new DeviceResourceManager(toQuery); - reg = mgr; - registries.put(toQuery, reg); - toQuery.disposeExec(new Runnable() { + toQuery.disposeExec(new class Runnable { + DeviceResourceManager mgr; + this(){ + mgr = new DeviceResourceManager(toQuery); + reg = mgr; + registries.add(toQuery, reg); + } /* * (non-Javadoc) * @@ -223,7 +222,7 @@ */ public void run() { mgr.dispose(); - registries.remove(toQuery); + registries.removeKey(toQuery); } }); } @@ -425,33 +424,33 @@ private static void initializeDefaultImages() { Object bundle = null; - try { -//FIXME +// DWT-Note: deactivated +// try { // bundle = JFaceActivator.getBundle(); - } catch (NoClassDefFoundError exception) { - // Test to see if OSGI is present - } - declareImage(bundle, Wizard.DEFAULT_IMAGE, ICONS_PATH + "page.gif", //$NON-NLS-1$ - Wizard.class, "images/page.gif"); //$NON-NLS-1$ +// } catch (NoClassDefFoundError exception) { +// // Test to see if OSGI is present +// } + declareImage(bundle, Wizard.DEFAULT_IMAGE, ICONS_PATH ~ "page.gif", //$NON-NLS-1$ + Wizard.classinfo, "images/page.gif"); //$NON-NLS-1$ // register default images for dialogs declareImage(bundle, Dialog.DLG_IMG_MESSAGE_INFO, ICONS_PATH - + "message_info.gif", Dialog.class, "images/message_info.gif"); //$NON-NLS-1$ //$NON-NLS-2$ + ~ "message_info.gif", Dialog.classinfo, "images/message_info.gif"); //$NON-NLS-1$ //$NON-NLS-2$ declareImage(bundle, Dialog.DLG_IMG_MESSAGE_WARNING, ICONS_PATH - + "message_warning.gif", Dialog.class, //$NON-NLS-1$ + ~ "message_warning.gif", Dialog.classinfo, //$NON-NLS-1$ "images/message_warning.gif"); //$NON-NLS-1$ declareImage(bundle, Dialog.DLG_IMG_MESSAGE_ERROR, ICONS_PATH - + "message_error.gif", Dialog.class, "images/message_error.gif");//$NON-NLS-1$ //$NON-NLS-2$ + ~ "message_error.gif", Dialog.classinfo, "images/message_error.gif");//$NON-NLS-1$ //$NON-NLS-2$ declareImage(bundle, Dialog.DLG_IMG_HELP, ICONS_PATH - + "help.gif", Dialog.class, "images/help.gif");//$NON-NLS-1$ //$NON-NLS-2$ + ~ "help.gif", Dialog.classinfo, "images/help.gif");//$NON-NLS-1$ //$NON-NLS-2$ declareImage( bundle, TitleAreaDialog.DLG_IMG_TITLE_BANNER, - ICONS_PATH + "title_banner.png", TitleAreaDialog.class, "images/title_banner.gif");//$NON-NLS-1$ //$NON-NLS-2$ + ICONS_PATH ~ "title_banner.png", TitleAreaDialog.classinfo, "images/title_banner.gif");//$NON-NLS-1$ //$NON-NLS-2$ declareImage( bundle, PreferenceDialog.PREF_DLG_TITLE_IMG, - ICONS_PATH + "pref_dialog_title.gif", PreferenceDialog.class, "images/pref_dialog_title.gif");//$NON-NLS-1$ //$NON-NLS-2$ + ICONS_PATH ~ "pref_dialog_title.gif", PreferenceDialog.classinfo, "images/pref_dialog_title.gif");//$NON-NLS-1$ //$NON-NLS-2$ } @@ -476,7 +475,7 @@ * */ private static final void declareImage(Object bundle, String key, - String path, Class fallback, String fallbackPath) { + String path, ClassInfo fallback, String fallbackPath) { ImageDescriptor descriptor = null; @@ -522,10 +521,10 @@ * @return a list of corresponding string values */ public static String[] getStrings(String[] keys) { - Assert.isNotNull(keys); - int length = keys.length; - String[] result = new String[length]; - for (int i = 0; i < length; i++) { + Assert.isTrue(keys.length > 0 ); + int length_ = keys.length; + String[] result = new String[](length_); + for (int i = 0; i < length_; i++) { result[i] = getString(keys[i]); } return result; @@ -591,8 +590,7 @@ /* * (non-Javadoc) Declare a private constructor to block instantiation. */ - private JFaceResources() { + private this() { // no-op } } -++/ \ No newline at end of file diff -r a3ff22a98bef -r 6c14e54dfc11 dwtx/jface/resource/LocalResourceManager.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/resource/LocalResourceManager.d Sat Mar 29 02:25:12 2008 +0100 @@ -0,0 +1,106 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +module dwtx.jface.resource.LocalResourceManager; + +import dwtx.jface.resource.AbstractResourceManager; +import dwtx.jface.resource.ResourceManager; +import dwtx.jface.resource.DeviceResourceDescriptor; + +import dwt.events.DisposeEvent; +import dwt.events.DisposeListener; +import dwt.graphics.Device; +import dwt.graphics.Image; +import dwt.widgets.Control; + +import dwt.dwthelper.utils; + +/** + * A local registry that shares its resources with some global registry. + * LocalResourceManager is typically used to safeguard against leaks. Clients + * can use a nested registry to allocate and deallocate resources in the + * global registry. Calling dispose() on the nested registry will deallocate + * everything allocated for the nested registry without affecting the rest + * of the global registry. + *

+ * A nested registry can be used to manage the resources for, say, a dialog + * box. + *

+ * @since 3.1 + */ +public final class LocalResourceManager : AbstractResourceManager { + + private ResourceManager parentRegistry; + + /** + * Creates a local registry that delegates to the given global registry + * for all resource allocation and deallocation. + * + * @param parentRegistry global registry + */ + public this(ResourceManager parentRegistry) { + this.parentRegistry = parentRegistry; + } + + /** + * Creates a local registry that wraps the given global registry. Anything + * allocated by this registry will be automatically cleaned up with the given + * control is disposed. Note that registries created in this way should not + * be used to allocate any resource that must outlive the given control. + * + * @param parentRegistry global registry that handles resource allocation + * @param owner control whose disposal will trigger cleanup of everything + * in the registry. + */ + public this(ResourceManager parentRegistry, Control owner) { + this(parentRegistry); + + owner.addDisposeListener(new class DisposeListener { + /* (non-Javadoc) + * @see dwt.events.DisposeListener#widgetDisposed(dwt.events.DisposeEvent) + */ + public void widgetDisposed(DisposeEvent e) { + this.outer.dispose(); + } + }); + } + + /* (non-Javadoc) + * @see dwtx.jface.resource.ResourceManager#getDevice() + */ + public Device getDevice() { + return parentRegistry.getDevice(); + } + + /* (non-Javadoc) + * @see dwtx.jface.resource.AbstractResourceManager#allocate(dwtx.jface.resource.DeviceResourceDescriptor) + */ + protected Object allocate(DeviceResourceDescriptor descriptor) { + return parentRegistry.create(descriptor); + } + + /* (non-Javadoc) + * @see dwtx.jface.resource.AbstractResourceManager#deallocate(java.lang.Object, dwtx.jface.resource.DeviceResourceDescriptor) + */ + protected void deallocate(Object resource, + DeviceResourceDescriptor descriptor) { + + parentRegistry.destroy(descriptor); + } + + /* (non-Javadoc) + * @see dwtx.jface.resource.ResourceManager#getDefaultImage() + */ + protected Image getDefaultImage() { + return parentRegistry.getDefaultImage_(); + } +} diff -r a3ff22a98bef -r 6c14e54dfc11 dwtx/jface/resource/ResourceManager.d --- a/dwtx/jface/resource/ResourceManager.d Sat Mar 29 01:25:27 2008 +0100 +++ b/dwtx/jface/resource/ResourceManager.d Sat Mar 29 02:25:12 2008 +0100 @@ -228,6 +228,9 @@ * image is missing. */ protected abstract Image getDefaultImage(); + package Image getDefaultImage_(){ + return getDefaultImage(); + } /** * Undoes everything that was done by {@link #createImage(ImageDescriptor)}. diff -r a3ff22a98bef -r 6c14e54dfc11 dwtx/jface/wizard/Wizard.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/wizard/Wizard.d Sat Mar 29 02:25:12 2008 +0100 @@ -0,0 +1,464 @@ +/******************************************************************************* + * 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 + * Port to the D programming language: + * Frank Benoit + *******************************************************************************/ +module dwtx.jface.wizard.Wizard; + +import dwt.dwthelper.utils; +pragma( msg, "FIXME dwtx.jface.wizard.Wizard"); +class Wizard { + public static final String DEFAULT_IMAGE = "dwtx.jface.wizard.Wizard.pageImage";//$NON-NLS-1$ +} +/++ +import java.util.ArrayList; +import java.util.List; + +import dwt.graphics.Image; +import dwt.graphics.RGB; +import dwt.widgets.Composite; +import dwt.widgets.Shell; +import dwtx.core.runtime.Assert; +import dwtx.jface.dialogs.IDialogSettings; +import dwtx.jface.resource.ImageDescriptor; +import dwtx.jface.resource.JFaceResources; + +/** + * An abstract base implementation of a wizard. A typical client subclasses + * Wizard to implement a particular wizard. + *

+ * Subclasses may call the following methods to configure the wizard: + *

    + *
  • addPage
  • + *
  • setHelpAvailable
  • + *
  • setDefaultPageImageDescriptor
  • + *
  • setDialogSettings
  • + *
  • setNeedsProgressMonitor
  • + *
  • setTitleBarColor
  • + *
  • setWindowTitle
  • + *
+ *

+ *

+ * Subclasses may override these methods if required: + *

    + *
  • reimplement createPageControls
  • + *
  • reimplement performCancel
  • + *
  • extend addPages
  • + *
  • reimplement performFinish
  • + *
  • extend dispose
  • + *
+ *

+ *

+ * Note that clients are free to implement IWizard from scratch + * instead of subclassing Wizard. Correct implementations of + * IWizard will work with any correct implementation of + * IWizardPage. + *

+ */ +public abstract class Wizard implements IWizard { + /** + * Image registry key of the default image for wizard pages (value + * "dwtx.jface.wizard.Wizard.pageImage"). + */ + public static final String DEFAULT_IMAGE = "dwtx.jface.wizard.Wizard.pageImage";//$NON-NLS-1$ + + /** + * The wizard container this wizard belongs to; null if none. + */ + private IWizardContainer container = null; + + /** + * This wizard's list of pages (element type: IWizardPage). + */ + private List pages = new ArrayList(); + + /** + * Indicates whether this wizard needs a progress monitor. + */ + private bool needsProgressMonitor = false; + + /** + * Indicates whether this wizard needs previous and next buttons even if the + * wizard has only one page. + */ + private bool forcePreviousAndNextButtons = false; + + /** + * Indicates whether this wizard supports help. + */ + private bool isHelpAvailable = false; + + /** + * The default page image for pages without one of their one; + * null if none. + */ + private Image defaultImage = null; + + /** + * The default page image descriptor, used for creating a default page image + * if required; null if none. + */ + private ImageDescriptor defaultImageDescriptor = JFaceResources.getImageRegistry().getDescriptor(DEFAULT_IMAGE); + + /** + * The color of the wizard title bar; null if none. + */ + private RGB titleBarColor = null; + + /** + * The window title string for this wizard; null if none. + */ + private String windowTitle = null; + + /** + * The dialog settings for this wizard; null if none. + */ + private IDialogSettings dialogSettings = null; + + /** + * Creates a new empty wizard. + */ + protected Wizard() { + super(); + } + + /** + * Adds a new page to this wizard. The page is inserted at the end of the + * page list. + * + * @param page + * the new page + */ + public void addPage(IWizardPage page) { + pages.add(page); + page.setWizard(this); + } + + /** + * The Wizard implementation of this IWizard + * method does nothing. Subclasses should extend if extra pages need to be + * added before the wizard opens. New pages should be added by calling + * addPage. + */ + public void addPages() { + } + + /* + * (non-Javadoc) Method declared on IWizard. + */ + public bool canFinish() { + // Default implementation is to check if all pages are complete. + for (int i = 0; i < pages.size(); i++) { + if (!((IWizardPage) pages.get(i)).isPageComplete()) { + return false; + } + } + return true; + } + + /** + * The Wizard implementation of this IWizard + * method creates all the pages controls using + * IDialogPage.createControl. Subclasses should reimplement + * this method if they want to delay creating one or more of the pages + * lazily. The framework ensures that the contents of a page will be created + * before attempting to show it. + */ + public void createPageControls(Composite pageContainer) { + // the default behavior is to create all the pages controls + for (int i = 0; i < pages.size(); i++) { + IWizardPage page = (IWizardPage) pages.get(i); + page.createControl(pageContainer); + // page is responsible for ensuring the created control is + // accessable + // via getControl. + Assert.isNotNull(page.getControl()); + } + } + + /** + * The Wizard implementation of this IWizard + * method disposes all the pages controls using + * DialogPage.dispose. Subclasses should extend this method + * if the wizard instance maintains addition DWT resource that need to be + * disposed. + */ + public void dispose() { + // notify pages + for (int i = 0; i < pages.size(); i++) { + ((IWizardPage) pages.get(i)).dispose(); + } + // dispose of image + if (defaultImage !is null) { + JFaceResources.getResources().destroyImage(defaultImageDescriptor); + defaultImage = null; + } + } + + /* + * (non-Javadoc) Method declared on IWizard. + */ + public IWizardContainer getContainer() { + return container; + } + + /* + * (non-Javadoc) Method declared on IWizard. + */ + public Image getDefaultPageImage() { + if (defaultImage is null) { + defaultImage = JFaceResources.getResources().createImageWithDefault(defaultImageDescriptor); + } + return defaultImage; + } + + /* + * (non-Javadoc) Method declared on IWizard. + */ + public IDialogSettings getDialogSettings() { + return dialogSettings; + } + + /* + * (non-Javadoc) Method declared on IWizard. The default behavior is to + * return the page that was added to this wizard after the given page. + */ + public IWizardPage getNextPage(IWizardPage page) { + int index = pages.indexOf(page); + if (index is pages.size() - 1 || index is -1) { + // last page or page not found + return null; + } + return (IWizardPage) pages.get(index + 1); + } + + /* + * (non-Javadoc) Method declared on IWizard. + */ + public IWizardPage getPage(String name) { + for (int i = 0; i < pages.size(); i++) { + IWizardPage page = (IWizardPage) pages.get(i); + String pageName = page.getName(); + if (pageName.equals(name)) { + return page; + } + } + return null; + } + + /* + * (non-Javadoc) Method declared on IWizard. + */ + public int getPageCount() { + return pages.size(); + } + + /* + * (non-Javadoc) Method declared on IWizard. + */ + public IWizardPage[] getPages() { + return (IWizardPage[]) pages.toArray(new IWizardPage[pages.size()]); + } + + /* + * (non-Javadoc) Method declared on IWizard. The default behavior is to + * return the page that was added to this wizard before the given page. + */ + public IWizardPage getPreviousPage(IWizardPage page) { + int index = pages.indexOf(page); + if (index is 0 || index is -1) { + // first page or page not found + return null; + } + return (IWizardPage) pages.get(index - 1); + } + + /** + * Returns the wizard's shell if the wizard is visible. Otherwise + * null is returned. + * + * @return Shell + */ + public Shell getShell() { + if (container is null) { + return null; + } + return container.getShell(); + } + + /* + * (non-Javadoc) Method declared on IWizard. By default this is the first + * page inserted into the wizard. + */ + public IWizardPage getStartingPage() { + if (pages.size() is 0) { + return null; + } + return (IWizardPage) pages.get(0); + } + + /* + * (non-Javadoc) Method declared on IWizard. + */ + public RGB getTitleBarColor() { + return titleBarColor; + } + + /* + * (non-Javadoc) Method declared on IWizard. + */ + public String getWindowTitle() { + return windowTitle; + } + + /* + * (non-Javadoc) Method declared on IWizard. + */ + public bool isHelpAvailable() { + return isHelpAvailable; + } + + /* + * (non-Javadoc) Method declared on IWizard. + */ + public bool needsPreviousAndNextButtons() { + return forcePreviousAndNextButtons || pages.size() > 1; + } + + /* + * (non-Javadoc) Method declared on IWizard. + */ + public bool needsProgressMonitor() { + return needsProgressMonitor; + } + + /** + * The Wizard implementation of this IWizard + * method does nothing and returns true. Subclasses should + * reimplement this method if they need to perform any special cancel + * processing for their wizard. + */ + public bool performCancel() { + return true; + } + + /** + * Subclasses must implement this IWizard method to perform + * any special finish processing for their wizard. + */ + public abstract bool performFinish(); + + /* + * (non-Javadoc) Method declared on IWizard. + */ + public void setContainer(IWizardContainer wizardContainer) { + container = wizardContainer; + } + + /** + * Sets the default page image descriptor for this wizard. + *

+ * This image descriptor will be used to generate an image for a page with + * no image of its own; the image will be computed once and cached. + *

+ * + * @param imageDescriptor + * the default page image descriptor + */ + public void setDefaultPageImageDescriptor(ImageDescriptor imageDescriptor) { + defaultImageDescriptor = imageDescriptor; + } + + /** + * Sets the dialog settings for this wizard. + *

+ * The dialog settings is used to record state between wizard invocations + * (for example, radio button selection, last import directory, etc.) + *

+ * + * @param settings + * the dialog settings, or null if none + * @see #getDialogSettings + * + */ + public void setDialogSettings(IDialogSettings settings) { + dialogSettings = settings; + } + + /** + * Controls whether the wizard needs Previous and Next buttons even if it + * currently contains only one page. + *

+ * This flag should be set on wizards where the first wizard page adds + * follow-on wizard pages based on user input. + *

+ * + * @param b + * true to always show Next and Previous buttons, + * and false to suppress Next and Previous buttons + * for single page wizards + */ + public void setForcePreviousAndNextButtons(bool b) { + forcePreviousAndNextButtons = b; + } + + /** + * Sets whether help is available for this wizard. + *

+ * The result of this method is typically used by the container to show or + * hide the Help button. + *

+ * + * @param b + * true if help is available, and + * false if this wizard is helpless + * @see #isHelpAvailable() + */ + public void setHelpAvailable(bool b) { + isHelpAvailable = b; + } + + /** + * Sets whether this wizard needs a progress monitor. + * + * @param b + * true if a progress monitor is required, and + * false if none is needed + * @see #needsProgressMonitor() + */ + public void setNeedsProgressMonitor(bool b) { + needsProgressMonitor = b; + } + + /** + * Sets the title bar color for this wizard. + * + * @param color + * the title bar color + */ + public void setTitleBarColor(RGB color) { + titleBarColor = color; + } + + /** + * Sets the window title for the container that hosts this page to the given + * string. + * + * @param newTitle + * the window title for the container + */ + public void setWindowTitle(String newTitle) { + windowTitle = newTitle; + if (container !is null) { + container.updateWindowTitle(); + } + } +} +++/ \ No newline at end of file diff -r a3ff22a98bef -r 6c14e54dfc11 dwtx/jface/wizard/WizardDialog.d --- a/dwtx/jface/wizard/WizardDialog.d Sat Mar 29 01:25:27 2008 +0100 +++ b/dwtx/jface/wizard/WizardDialog.d Sat Mar 29 02:25:12 2008 +0100 @@ -12,7 +12,7 @@ * Frank Benoit *******************************************************************************/ module dwtx.jface.wizard.WizardDialog; - +pragma( msg, "FIXME dwtx.jface.wizard.WizardDialog"); class WizardDialog { }