# HG changeset patch # User Frank Benoit # Date 1207352747 -7200 # Node ID b3c8e32d406f894a74db5cd53b012f5dd7e3c6f2 # Parent f255825731295d7c463c129dc9a118a3b394a3b5 preference diff -r f25582573129 -r b3c8e32d406f dwtx/jface/fieldassist/ControlDecoration.d --- a/dwtx/jface/fieldassist/ControlDecoration.d Thu Apr 03 20:41:52 2008 +0200 +++ b/dwtx/jface/fieldassist/ControlDecoration.d Sat Apr 05 01:45:47 2008 +0200 @@ -86,7 +86,9 @@ /** * Cached platform flags for dealing with platform-specific issues. */ - private static bool CARBON = "carbon".equals(DWT.getPlatform()); //$NON-NLS-1$ + private static bool CARBON(){ + return "carbon".equals(DWT.getPlatform()); //$NON-NLS-1$ + } /** * The associated control diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/BooleanFieldEditor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/BooleanFieldEditor.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,261 @@ +/******************************************************************************* + * 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.BooleanFieldEditor; + +import dwtx.jface.preference.FieldEditor; + +import dwt.DWT; +import dwt.events.DisposeEvent; +import dwt.events.DisposeListener; +import dwt.events.SelectionAdapter; +import dwt.events.SelectionEvent; +import dwt.layout.GridData; +import dwt.widgets.Button; +import dwt.widgets.Composite; +import dwt.widgets.Label; + +import dwt.dwthelper.utils; + +/** + * A field editor for a bool type preference. + */ +public class BooleanFieldEditor : FieldEditor { + + /** + * Style constant (value 0) indicating the default + * layout where the field editor's check box appears to the left + * of the label. + */ + public static const int DEFAULT = 0; + + /** + * Style constant (value 1) indicating a layout + * where the field editor's label appears on the left + * with a check box on the right. + */ + public static const int SEPARATE_LABEL = 1; + + /** + * Style bits. Either DEFAULT or + * SEPARATE_LABEL. + */ + private int style; + + /** + * The previously selected, or "before", value. + */ + private bool wasSelected; + + /** + * The checkbox control, or null if none. + */ + private Button checkBox = null; + + /** + * Creates a new bool field editor + */ + protected this() { + } + + /** + * Creates a bool field editor in the given style. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param style the style, either DEFAULT or + * SEPARATE_LABEL + * @param parent the parent of the field editor's control + * @see #DEFAULT + * @see #SEPARATE_LABEL + */ + public this(String name, String labelText, int style, + Composite parent) { + init(name, labelText); + this.style = style; + createControl(parent); + } + + /** + * Creates a bool field editor in the default style. + * + * @param name the name of the preference this field editor works on + * @param label the label text of the field editor + * @param parent the parent of the field editor's control + */ + public this(String name, String label, Composite parent) { + this(name, label, DEFAULT, parent); + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void adjustForNumColumns(int numColumns) { + if (style is SEPARATE_LABEL) { + numColumns--; + } + (cast(GridData) checkBox.getLayoutData()).horizontalSpan = numColumns; + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doFillIntoGrid(Composite parent, int numColumns) { + String text = getLabelText(); + switch (style) { + case SEPARATE_LABEL: + getLabelControl(parent); + numColumns--; + text = null; + default: + checkBox = getChangeControl(parent); + GridData gd = new GridData(); + gd.horizontalSpan = numColumns; + checkBox.setLayoutData(gd); + if (text !is null) { + checkBox.setText(text); + } + } + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + * Loads the value from the preference store and sets it to + * the check box. + */ + protected void doLoad() { + if (checkBox !is null) { + bool value = getPreferenceStore() + .getBoolean(getPreferenceName()); + checkBox.setSelection(value); + wasSelected = value; + } + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + * Loads the default value from the preference store and sets it to + * the check box. + */ + protected void doLoadDefault() { + if (checkBox !is null) { + bool value = getPreferenceStore().getDefaultBoolean( + getPreferenceName()); + checkBox.setSelection(value); + wasSelected = value; + } + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doStore() { + getPreferenceStore().setValue(getPreferenceName(), + checkBox.getSelection()); + } + + /** + * Returns this field editor's current value. + * + * @return the value + */ + public bool getBooleanValue() { + return checkBox.getSelection(); + } + + /** + * Returns the change button for this field editor. + * @param parent The Composite to create the receiver in. + * + * @return the change button + */ + protected Button getChangeControl(Composite parent) { + if (checkBox is null) { + checkBox = new Button(parent, DWT.CHECK | DWT.LEFT); + checkBox.setFont(parent.getFont()); + checkBox.addSelectionListener(new class SelectionAdapter { + public void widgetSelected(SelectionEvent e) { + bool isSelected = checkBox.getSelection(); + valueChanged(wasSelected, isSelected); + wasSelected = isSelected; + } + }); + checkBox.addDisposeListener(new class DisposeListener { + public void widgetDisposed(DisposeEvent event) { + checkBox = null; + } + }); + } else { + checkParent(checkBox, parent); + } + return checkBox; + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + public int getNumberOfControls() { + switch (style) { + case SEPARATE_LABEL: + return 2; + default: + return 1; + } + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + public void setFocus() { + if (checkBox !is null) { + checkBox.setFocus(); + } + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + public void setLabelText(String text) { + super.setLabelText(text); + Label label = getLabelControl(); + if (label is null && checkBox !is null) { + checkBox.setText(text); + } + } + + /** + * Informs this field editor's listener, if it has one, about a change + * to the value (VALUE property) provided that the old and + * new values are different. + * + * @param oldValue the old value + * @param newValue the new value + */ + protected void valueChanged(bool oldValue, bool newValue) { + setPresentsDefaultValue(false); + if (oldValue !is newValue) { + fireStateChanged(VALUE, oldValue, newValue); + } + } + + /* + * @see FieldEditor.setEnabled + */ + public void setEnabled(bool enabled, Composite parent) { + //Only call super if there is a label already + if (style is SEPARATE_LABEL) { + super.setEnabled(enabled, parent); + } + getChangeControl(parent).setEnabled(enabled); + } + +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/BooleanPropertyAction.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/BooleanPropertyAction.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,74 @@ +/******************************************************************************* + * 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.BooleanPropertyAction; + +import dwtx.jface.preference.IPreferenceStore; + +import dwtx.jface.action.Action; +import dwtx.jface.util.IPropertyChangeListener; +import dwtx.jface.util.PropertyChangeEvent; + +import dwt.dwthelper.utils; + +/** + * The BooleanPropertyAction is an action that set the values of a + * bool property in the preference store. + */ + +public class BooleanPropertyAction : Action { + + private IPreferenceStore preferenceStore; + + private String property; + + /** + * Create a new instance of the receiver. + * @param title The displayable name of the action. + * @param preferenceStore The preference store to propogate changes to + * @param property The property that is being updated + * @throws IllegalArgumentException Thrown if preferenceStore or + * property are null. + */ + public this(String title, + IPreferenceStore preferenceStore, String property) { + super(title, AS_CHECK_BOX); + + if (preferenceStore is null || property is null) { + throw new IllegalArgumentException(null); + } + + this.preferenceStore = preferenceStore; + this.property = property; + final String finalProprety = property; + + preferenceStore + .addPropertyChangeListener(new class IPropertyChangeListener { + public void propertyChange(PropertyChangeEvent event) { + if (finalProprety.equals(event.getProperty())) { + setChecked(cast(bool)(Boolean.TRUE == event.getNewValue() )); + } + } + }); + + setChecked(preferenceStore.getBoolean(property)); + } + + /* + * (non-Javadoc) + * @see dwtx.jface.action.IAction#run() + */ + public void run() { + preferenceStore.setValue(property, isChecked()); + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/ColorFieldEditor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/ColorFieldEditor.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,193 @@ +/******************************************************************************* + * 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.preference.ColorFieldEditor; + +import dwtx.jface.preference.FieldEditor; +import dwtx.jface.preference.ColorSelector; +import dwtx.jface.preference.PreferenceConverter; + +import dwt.graphics.Font; +import dwt.graphics.GC; +import dwt.graphics.Point; +import dwt.layout.GridData; +import dwt.widgets.Button; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwtx.jface.resource.JFaceResources; +import dwtx.jface.util.IPropertyChangeListener; +import dwtx.jface.util.PropertyChangeEvent; + +import dwt.dwthelper.utils; + +/** + * A field editor for a color type preference. + */ +public class ColorFieldEditor : FieldEditor { + + /** + * The color selector, or null if none. + */ + private ColorSelector colorSelector; + + /** + * Creates a new color field editor + */ + protected this() { + //No default behavior + } + + /** + * Creates a color field editor. + * + * @param name + * the name of the preference this field editor works on + * @param labelText + * the label text of the field editor + * @param parent + * the parent of the field editor's control + */ + public this(String name, String labelText, Composite parent) { + super(name, labelText, parent); + } + + /* + * (non-Javadoc) Method declared on FieldEditor. + */ + protected void adjustForNumColumns(int numColumns) { + (cast(GridData) colorSelector.getButton().getLayoutData()).horizontalSpan = numColumns - 1; + } + + /** + * Computes the size of the color image displayed on the button. + *

+ * This is an internal method and should not be called by clients. + *

+ * + * @param window + * the window to create a GC on for calculation. + * @return Point The image size + * + */ + protected Point computeImageSize(Control window) { + // Make the image height as high as a corresponding character. This + // makes sure that the button has the same size as a "normal" text + // button. + GC gc = new GC(window); + Font f = JFaceResources.getFontRegistry().get( + JFaceResources.DEFAULT_FONT); + gc.setFont(f); + int height = gc.getFontMetrics().getHeight(); + gc.dispose(); + Point p = new Point(height * 3 - 6, height); + return p; + } + + + /* (non-Javadoc) + * @see dwtx.jface.preference.FieldEditor#doFillIntoGrid(dwt.widgets.Composite, int) + */ + protected void doFillIntoGrid(Composite parent, int numColumns) { + Control control = getLabelControl(parent); + GridData gd = new GridData(); + gd.horizontalSpan = numColumns - 1; + control.setLayoutData(gd); + + Button colorButton = getChangeControl(parent); + colorButton.setLayoutData(new GridData()); + + } + + + /* (non-Javadoc) + * @see dwtx.jface.preference.FieldEditor#doLoad() + */ + protected void doLoad() { + if (colorSelector is null) { + return; + } + colorSelector.setColorValue(PreferenceConverter.getColor( + getPreferenceStore(), getPreferenceName())); + } + + /* + * (non-Javadoc) Method declared on FieldEditor. + */ + protected void doLoadDefault() { + if (colorSelector is null) { + return; + } + colorSelector.setColorValue(PreferenceConverter.getDefaultColor( + getPreferenceStore(), getPreferenceName())); + } + + /* + * (non-Javadoc) Method declared on FieldEditor. + */ + protected void doStore() { + PreferenceConverter.setValue(getPreferenceStore(), getPreferenceName(), + colorSelector.getColorValue()); + } + + /** + * Get the color selector used by the receiver. + * + * @return ColorSelector/ + */ + public ColorSelector getColorSelector() { + return colorSelector; + } + + /** + * Returns the change button for this field editor. + * + * @param parent + * The control to create the button in if required. + * @return the change button + */ + protected Button getChangeControl(Composite parent) { + if (colorSelector is null) { + colorSelector = new ColorSelector(parent); + colorSelector.addListener(new class IPropertyChangeListener { + // forward the property change of the color selector + public void propertyChange(PropertyChangeEvent event) { + this.outer.fireValueChanged(event.getProperty(), + event.getOldValue(), event.getNewValue()); + setPresentsDefaultValue(false); + } + }); + + } else { + checkParent(colorSelector.getButton(), parent); + } + return colorSelector.getButton(); + } + + /* + * (non-Javadoc) Method declared on FieldEditor. + */ + public int getNumberOfControls() { + return 2; + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.preference.FieldEditor#setEnabled(bool, + * dwt.widgets.Composite) + */ + public void setEnabled(bool enabled, Composite parent) { + super.setEnabled(enabled, parent); + getChangeControl(parent).setEnabled(enabled); + } + +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/ColorSelector.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/ColorSelector.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,236 @@ +/******************************************************************************* + * 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.preference.ColorSelector; + + +import dwt.DWT; +import dwt.accessibility.AccessibleAdapter; +import dwt.accessibility.AccessibleEvent; +import dwt.events.DisposeEvent; +import dwt.events.DisposeListener; +import dwt.events.SelectionAdapter; +import dwt.events.SelectionEvent; +import dwt.graphics.Color; +import dwt.graphics.Font; +import dwt.graphics.GC; +import dwt.graphics.Image; +import dwt.graphics.Point; +import dwt.graphics.RGB; +import dwt.widgets.Button; +import dwt.widgets.ColorDialog; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Display; +import dwtx.core.commands.common.EventManager; +import dwtx.jface.resource.JFaceResources; +import dwtx.jface.util.IPropertyChangeListener; +import dwtx.jface.util.PropertyChangeEvent; + +import dwt.dwthelper.utils; + +/** + * The ColorSelector is a wrapper for a button that displays a + * selected Color and allows the user to change the selection. + */ +public class ColorSelector : EventManager { + /** + * Property name that signifies the selected color of this + * ColorSelector has changed. + * + * @since 3.0 + */ + public static const String PROP_COLORCHANGE = "colorValue"; //$NON-NLS-1$ + + private Button fButton; + + private Color fColor; + + private RGB fColorValue; + + private Point fExtent; + + private Image fImage; + + /** + * Create a new instance of the reciever and the button that it wrappers in + * the supplied parent Composite. + * + * @param parent + * The parent of the button. + */ + public this(Composite parent) { + fButton = new Button(parent, DWT.PUSH); + fExtent = computeImageSize(parent); + fImage = new Image(parent.getDisplay(), fExtent.x, fExtent.y); + GC gc = new GC(fImage); + gc.setBackground(fButton.getBackground()); + gc.fillRectangle(0, 0, fExtent.x, fExtent.y); + gc.dispose(); + fButton.setImage(fImage); + fButton.addSelectionListener(new class SelectionAdapter { + public void widgetSelected(SelectionEvent event) { + open(); + } + }); + fButton.addDisposeListener(new class DisposeListener { + public void widgetDisposed(DisposeEvent event) { + if (fImage !is null) { + fImage.dispose(); + fImage = null; + } + if (fColor !is null) { + fColor.dispose(); + fColor = null; + } + } + }); + fButton.getAccessible().addAccessibleListener(new class AccessibleAdapter { + /* + * (non-Javadoc) + * + * @see dwt.accessibility.AccessibleAdapter#getName(dwt.accessibility.AccessibleEvent) + */ + public void getName(AccessibleEvent e) { + e.result = JFaceResources.getString("ColorSelector.Name"); //$NON-NLS-1$ + } + }); + } + + /** + * Adds a property change listener to this ColorSelector. + * Events are fired when the color in the control changes via the user + * clicking an selecting a new one in the color dialog. No event is fired in + * the case where setColorValue(RGB) is invoked. + * + * @param listener + * a property change listener + * @since 3.0 + */ + public void addListener(IPropertyChangeListener listener) { + addListenerObject(cast(Object)listener); + } + + /** + * Compute the size of the image to be displayed. + * + * @param window - + * the window used to calculate + * @return Point + */ + private Point computeImageSize(Control window) { + GC gc = new GC(window); + Font f = JFaceResources.getFontRegistry().get( + JFaceResources.DIALOG_FONT); + gc.setFont(f); + int height = gc.getFontMetrics().getHeight(); + gc.dispose(); + Point p = new Point(height * 3 - 6, height); + return p; + } + + /** + * Get the button control being wrappered by the selector. + * + * @return Button + */ + public Button getButton() { + return fButton; + } + + /** + * Return the currently displayed color. + * + * @return RGB + */ + public RGB getColorValue() { + return fColorValue; + } + + /** + * Removes the given listener from this ColorSelector. Has + * no affect if the listener is not registered. + * + * @param listener + * a property change listener + * @since 3.0 + */ + public void removeListener(IPropertyChangeListener listener) { + removeListenerObject(cast(Object)listener); + } + + /** + * Set the current color value and update the control. + * + * @param rgb + * The new color. + */ + public void setColorValue(RGB rgb) { + fColorValue = rgb; + updateColorImage(); + } + + /** + * Set whether or not the button is enabled. + * + * @param state + * the enabled state. + */ + public void setEnabled(bool state) { + getButton().setEnabled(state); + } + + /** + * Update the image being displayed on the button using the current color + * setting. + */ + protected void updateColorImage() { + Display display = fButton.getDisplay(); + GC gc = new GC(fImage); + gc.setForeground(display.getSystemColor(DWT.COLOR_BLACK)); + gc.drawRectangle(0, 2, fExtent.x - 1, fExtent.y - 4); + if (fColor !is null) { + fColor.dispose(); + } + fColor = new Color(display, fColorValue); + gc.setBackground(fColor); + gc.fillRectangle(1, 3, fExtent.x - 2, fExtent.y - 5); + gc.dispose(); + fButton.setImage(fImage); + } + + /** + * Activate the editor for this selector. This causes the color selection + * dialog to appear and wait for user input. + * + * @since 3.2 + */ + public void open() { + ColorDialog colorDialog = new ColorDialog(fButton.getShell()); + colorDialog.setRGB(fColorValue); + RGB newColor = colorDialog.open(); + if (newColor !is null) { + RGB oldValue = fColorValue; + fColorValue = newColor; + final Object[] finalListeners = getListeners(); + if (finalListeners.length > 0) { + PropertyChangeEvent pEvent = new PropertyChangeEvent( + this, PROP_COLORCHANGE, oldValue, newColor); + for (int i = 0; i < finalListeners.length; ++i) { + IPropertyChangeListener listener = cast(IPropertyChangeListener) finalListeners[i]; + listener.propertyChange(pEvent); + } + } + updateColorImage(); + } + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/ComboFieldEditor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/ComboFieldEditor.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,213 @@ +/******************************************************************************* + * 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.ComboFieldEditor; + +import dwtx.jface.preference.FieldEditor; + +import dwt.DWT; +import dwt.events.SelectionAdapter; +import dwt.events.SelectionEvent; +import dwt.layout.GridData; +import dwt.widgets.Combo; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwtx.core.runtime.Assert; + +import dwt.dwthelper.utils; + +/** + * A field editor for a combo box that allows the drop-down selection of one of + * a list of items. + * + * @since 3.3 + */ +public class ComboFieldEditor : FieldEditor { + + /** + * The Combo widget. + */ + private Combo fCombo; + + /** + * The value (not the name) of the currently selected item in the Combo widget. + */ + private String fValue; + + /** + * The names (labels) and underlying values to populate the combo widget. These should be + * arranged as: { {name1, value1}, {name2, value2}, ...} + */ + private String[][] fEntryNamesAndValues; + + /** + * Create the combo box field editor. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param entryNamesAndValues the names (labels) and underlying values to populate the combo widget. These should be + * arranged as: { {name1, value1}, {name2, value2}, ...} + * @param parent the parent composite + */ + public this(String name, String labelText, String[][] entryNamesAndValues, Composite parent) { + init(name, labelText); + Assert.isTrue(checkArray(entryNamesAndValues)); + fEntryNamesAndValues = entryNamesAndValues; + createControl(parent); + } + + /** + * Checks whether given String[][] is of "type" + * String[][2]. + * + * @return true if it is ok, and false otherwise + */ + private bool checkArray(String[][] table) { + if (table is null) { + return false; + } + for (int i = 0; i < table.length; i++) { + String[] array = table[i]; + if (array is null || array.length !is 2) { + return false; + } + } + return true; + } + + /* (non-Javadoc) + * @see dwtx.jface.preference.FieldEditor#adjustForNumColumns(int) + */ + protected void adjustForNumColumns(int numColumns) { + if (numColumns > 1) { + Control control = getLabelControl(); + int left = numColumns; + if (control !is null) { + (cast(GridData)control.getLayoutData()).horizontalSpan = 1; + left = left - 1; + } + (cast(GridData)fCombo.getLayoutData()).horizontalSpan = left; + } else { + Control control = getLabelControl(); + if (control !is null) { + (cast(GridData)control.getLayoutData()).horizontalSpan = 1; + } + (cast(GridData)fCombo.getLayoutData()).horizontalSpan = 1; + } + } + + /* (non-Javadoc) + * @see dwtx.jface.preference.FieldEditor#doFillIntoGrid(dwt.widgets.Composite, int) + */ + protected void doFillIntoGrid(Composite parent, int numColumns) { + int comboC = 1; + if (numColumns > 1) { + comboC = numColumns - 1; + } + Control control = getLabelControl(parent); + GridData gd = new GridData(); + gd.horizontalSpan = 1; + control.setLayoutData(gd); + control = getComboBoxControl(parent); + gd = new GridData(); + gd.horizontalSpan = comboC; + gd.horizontalAlignment = GridData.FILL; + control.setLayoutData(gd); + control.setFont(parent.getFont()); + } + + /* (non-Javadoc) + * @see dwtx.jface.preference.FieldEditor#doLoad() + */ + protected void doLoad() { + updateComboForValue(getPreferenceStore().getString(getPreferenceName())); + } + + /* (non-Javadoc) + * @see dwtx.jface.preference.FieldEditor#doLoadDefault() + */ + protected void doLoadDefault() { + updateComboForValue(getPreferenceStore().getDefaultString(getPreferenceName())); + } + + /* (non-Javadoc) + * @see dwtx.jface.preference.FieldEditor#doStore() + */ + protected void doStore() { + if (fValue is null) { + getPreferenceStore().setToDefault(getPreferenceName()); + return; + } + getPreferenceStore().setValue(getPreferenceName(), fValue); + } + + /* (non-Javadoc) + * @see dwtx.jface.preference.FieldEditor#getNumberOfControls() + */ + public int getNumberOfControls() { + return 2; + } + + /* + * Lazily create and return the Combo control. + */ + private Combo getComboBoxControl(Composite parent) { + if (fCombo is null) { + fCombo = new Combo(parent, DWT.READ_ONLY); + fCombo.setFont(parent.getFont()); + for (int i = 0; i < fEntryNamesAndValues.length; i++) { + fCombo.add(fEntryNamesAndValues[i][0], i); + } + + fCombo.addSelectionListener(new class SelectionAdapter { + public void widgetSelected(SelectionEvent evt) { + String oldValue = fValue; + String name = fCombo.getText(); + fValue = getValueForName(name); + setPresentsDefaultValue(false); + fireValueChanged(VALUE, stringcast(oldValue), stringcast(fValue)); + } + }); + } + return fCombo; + } + + /* + * Given the name (label) of an entry, return the corresponding value. + */ + private String getValueForName(String name) { + for (int i = 0; i < fEntryNamesAndValues.length; i++) { + String[] entry = fEntryNamesAndValues[i]; + if (name.equals(entry[0])) { + return entry[1]; + } + } + return fEntryNamesAndValues[0][0]; + } + + /* + * Set the name in the combo widget to match the specified value. + */ + private void updateComboForValue(String value) { + fValue = value; + for (int i = 0; i < fEntryNamesAndValues.length; i++) { + if (value.equals(fEntryNamesAndValues[i][1])) { + fCombo.setText(fEntryNamesAndValues[i][0]); + return; + } + } + if (fEntryNamesAndValues.length > 0) { + fValue = fEntryNamesAndValues[0][1]; + fCombo.setText(fEntryNamesAndValues[0][0]); + } + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/DirectoryFieldEditor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/DirectoryFieldEditor.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,107 @@ +/******************************************************************************* + * 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.DirectoryFieldEditor; + +import dwtx.jface.preference.StringButtonFieldEditor; +// import java.io.File; + +import dwt.DWT; +import dwt.widgets.Composite; +import dwt.widgets.DirectoryDialog; +import dwtx.jface.resource.JFaceResources; + +import dwt.dwthelper.utils; +import tango.io.FilePath; +import tango.io.FileSystem; + +/** + * A field editor for a directory path type preference. A standard directory + * dialog appears when the user presses the change button. + */ +public class DirectoryFieldEditor : StringButtonFieldEditor { + /** + * Creates a new directory field editor + */ + protected this() { + } + + /** + * Creates a directory field editor. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param parent the parent of the field editor's control + */ + public this(String name, String labelText, Composite parent) { + init(name, labelText); + setErrorMessage(JFaceResources + .getString("DirectoryFieldEditor.errorMessage"));//$NON-NLS-1$ + setChangeButtonText(JFaceResources.getString("openBrowse"));//$NON-NLS-1$ + setValidateStrategy(VALIDATE_ON_FOCUS_LOST); + createControl(parent); + } + + /* (non-Javadoc) + * Method declared on StringButtonFieldEditor. + * Opens the directory chooser dialog and returns the selected directory. + */ + protected String changePressed() { + auto f = new FilePath(getTextControl().getText()); + if (!f.exists()) { + f = cast(FilePath)null; + } + auto d = getDirectory(f); + if (d is null) { + return null; + } + + return FileSystem.toAbsolute( d ).toString; + } + + /* (non-Javadoc) + * Method declared on StringFieldEditor. + * Checks whether the text input field contains a valid directory. + */ + protected bool doCheckState() { + String fileName = getTextControl().getText(); + fileName = fileName.trim(); + if (fileName.length is 0 && isEmptyStringAllowed()) { + return true; + } + auto file = new FilePath(fileName); + return file.isFolder(); + } + + /** + * Helper that opens the directory chooser dialog. + * @param startingDirectory The directory the dialog will open in. + * @return File File or null. + * + */ + private FilePath getDirectory(FilePath startingDirectory) { + + DirectoryDialog fileDialog = new DirectoryDialog(getShell(), DWT.OPEN); + if (startingDirectory !is null) { + fileDialog.setFilterPath(startingDirectory.path); + } + String dir = fileDialog.open(); + if (dir !is null) { + dir = dir.trim(); + if (dir.length > 0) { + return new FilePath(dir); + } + } + + return null; + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/FieldEditor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/FieldEditor.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,731 @@ +/******************************************************************************* + * 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.FieldEditor; + +import dwtx.jface.preference.IPreferenceStore; +import dwtx.jface.preference.PreferencePage; + +import dwt.DWT; +import dwt.events.DisposeEvent; +import dwt.events.DisposeListener; +import dwt.graphics.FontMetrics; +import dwt.graphics.GC; +import dwt.layout.GridData; +import dwt.layout.GridLayout; +import dwt.widgets.Button; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Label; +import dwtx.core.runtime.Assert; +import dwtx.jface.dialogs.DialogPage; +import dwtx.jface.dialogs.IDialogConstants; +import dwtx.jface.resource.JFaceResources; +import dwtx.jface.util.IPropertyChangeListener; +import dwtx.jface.util.PropertyChangeEvent; + +import dwt.dwthelper.utils; + +/** + * Abstract base class for all field editors. + *

+ * A field editor presents the value of a preference to the end + * user. The value is loaded from a preference store; if + * modified by the end user, the value is validated and eventually + * stored back to the preference store. A field editor reports + * an event when the value, or the validity of the value, changes. + *

+ *

+ * Field editors should be used in conjunction with a field + * editor preference page (FieldEditorPreferencePage) + * which coordinates everything and provides the message line + * which display messages emanating from the editor. + *

+ *

+ * This package contains ready-to-use field editors for various + * types of preferences: + *

    + *
  • BooleanFieldEditor - booleans
  • + *
  • IntegerFieldEditor - integers
  • + *
  • StringFieldEditor - text strings
  • + *
  • RadioGroupFieldEditor - enumerations
  • + *
  • ColorFieldEditor - RGB colors
  • + *
  • FontFieldEditor - fonts
  • + *
  • DirectoryFieldEditor - directories
  • + *
  • FileFieldEditor - files
  • + *
  • PathEditor - paths
  • + *
+ *

+ */ +public abstract class FieldEditor { + + /** + * Property name constant (value "field_editor_is_valid") + * to signal a change in the validity of the value of this field editor. + */ + public static const String IS_VALID = "field_editor_is_valid";//$NON-NLS-1$ + + /** + * Property name constant (value "field_editor_value") + * to signal a change in the value of this field editor. + */ + public static const String VALUE = "field_editor_value";//$NON-NLS-1$ + + /** + * Gap between label and control. + */ + protected static const int HORIZONTAL_GAP = 8; + + /** + * The preference store, or null if none. + */ + private IPreferenceStore preferenceStore = null; + + /** + * The name of the preference displayed in this field editor. + */ + private String preferenceName; + + /** + * Indicates whether the default value is currently displayed, + * initially false. + */ + private bool isDefaultPresented = false; + + /** + * The label's text. + */ + private String labelText; + + /** + * The label control. + */ + private Label label; + + /** + * Listener, or null if none + */ + private IPropertyChangeListener propertyChangeListener; + + /** + * The page containing this field editor + */ + private DialogPage page; + + /** + * Creates a new field editor. + */ + protected this() { + } + + /** + * Creates a new field editor. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param parent the parent of the field editor's control + */ + protected this(String name, String labelText, Composite parent) { + init(name, labelText); + createControl(parent); + } + + /** + * Adjusts the horizontal span of this field editor's basic controls. + *

+ * Subclasses must implement this method to adjust the horizontal span + * of controls so they appear correct in the given number of columns. + *

+ *

+ * The number of columns will always be equal to or greater than the + * value returned by this editor's getNumberOfControls method. + * + * @param numColumns the number of columns + */ + protected abstract void adjustForNumColumns(int numColumns); + package void adjustForNumColumns_package(int numColumns){ + adjustForNumColumns(numColumns); + } + + /** + * Applies a font. + *

+ * The default implementation of this framework method + * does nothing. Subclasses should override this method + * if they want to change the font of the DWT control to + * a value different than the standard dialog font. + *

+ */ + protected void applyFont() { + } + package void applyFont_package() { + applyFont(); + } + + /** + * Checks if the given parent is the current parent of the + * supplied control; throws an (unchecked) exception if they + * are not correctly related. + * + * @param control the control + * @param parent the parent control + */ + protected void checkParent(Control control, Composite parent) { + Assert.isTrue(control.getParent() is parent, "Different parents");//$NON-NLS-1$ + } + + /** + * Clears the error message from the message line. + */ + protected void clearErrorMessage() { + if (page !is null) { + page.setErrorMessage(null); + } + } + + /** + * Clears the normal message from the message line. + */ + protected void clearMessage() { + if (page !is null) { + page.setMessage(null); + } + } + + /** + * Returns the number of pixels corresponding to the + * given number of horizontal dialog units. + *

+ * Clients may call this framework method, but should not override it. + *

+ * + * @param control the control being sized + * @param dlus the number of horizontal dialog units + * @return the number of pixels + */ + protected int convertHorizontalDLUsToPixels(Control control, int dlus) { + GC gc = new GC(control); + gc.setFont(control.getFont()); + int averageWidth = gc.getFontMetrics().getAverageCharWidth(); + gc.dispose(); + + double horizontalDialogUnitSize = averageWidth * 0.25; + + return cast(int) Math.round(dlus * horizontalDialogUnitSize); + } + + /** + * Returns the number of pixels corresponding to the + * given number of vertical dialog units. + *

+ * Clients may call this framework method, but should not override it. + *

+ * + * @param control the control being sized + * @param dlus the number of vertical dialog units + * @return the number of pixels + */ + protected int convertVerticalDLUsToPixels(Control control, int dlus) { + GC gc = new GC(control); + gc.setFont(control.getFont()); + int height = gc.getFontMetrics().getHeight(); + gc.dispose(); + + double verticalDialogUnitSize = height * 0.125; + + return cast(int) Math.round(dlus * verticalDialogUnitSize); + } + + /** + * Creates this field editor's main control containing all of its + * basic controls. + * + * @param parent the parent control + */ + protected void createControl(Composite parent) { + GridLayout layout = new GridLayout(); + layout.numColumns = getNumberOfControls(); + layout.marginWidth = 0; + layout.marginHeight = 0; + layout.horizontalSpacing = HORIZONTAL_GAP; + parent.setLayout(layout); + doFillIntoGrid(parent, layout.numColumns); + } + + /** + * Disposes the DWT resources used by this field editor. + */ + public void dispose() { + // nothing to dispose + } + + /** + * Fills this field editor's basic controls into the given parent. + *

+ * Subclasses must implement this method to create the controls + * for this field editor. + *

+ * + * @param parent the composite used as a parent for the basic controls; + * the parent's layout must be a GridLayout + * @param numColumns the number of columns + */ + protected abstract void doFillIntoGrid(Composite parent, int numColumns); + + /** + * Initializes this field editor with the preference value from + * the preference store. + *

+ * Subclasses must implement this method to properly initialize + * the field editor. + *

+ */ + protected abstract void doLoad(); + + /** + * Initializes this field editor with the default preference value from + * the preference store. + *

+ * Subclasses must implement this method to properly initialize + * the field editor. + *

+ */ + protected abstract void doLoadDefault(); + + /** + * Stores the preference value from this field editor into + * the preference store. + *

+ * Subclasses must implement this method to save the entered value + * into the preference store. + *

+ */ + protected abstract void doStore(); + + /** + * Fills this field editor's basic controls into the given parent. + * + * @param parent the composite used as a parent for the basic controls; + * the parent's layout must be a GridLayout + * @param numColumns the number of columns + */ + public void fillIntoGrid(Composite parent, int numColumns) { + Assert.isTrue(numColumns >= getNumberOfControls()); + Assert.isTrue(null !is cast(GridLayout)parent.getLayout() ); + doFillIntoGrid(parent, numColumns); + } + + /** + * Informs this field editor's listener, if it has one, about a change to + * one of this field editor's bool-valued properties. Does nothing + * if the old and new values are the same. + * + * @param property the field editor property name, + * such as VALUE or IS_VALID + * @param oldValue the old value + * @param newValue the new value + */ + protected void fireStateChanged(String property, bool oldValue, + bool newValue) { + if (oldValue is newValue) { + return; + } + fireValueChanged(property, oldValue ? Boolean.TRUE : Boolean.FALSE, newValue ? Boolean.TRUE : Boolean.FALSE); + } + + /** + * Informs this field editor's listener, if it has one, about a change to + * one of this field editor's properties. + * + * @param property the field editor property name, + * such as VALUE or IS_VALID + * @param oldValue the old value object, or null + * @param newValue the new value, or null + */ + protected void fireValueChanged(String property, Object oldValue, + Object newValue) { + if (propertyChangeListener is null) { + return; + } + propertyChangeListener.propertyChange(new PropertyChangeEvent(this, + property, oldValue, newValue)); + } + + /** + * Returns the symbolic font name used by this field editor. + * + * @return the symbolic font name + */ + public String getFieldEditorFontName() { + return JFaceResources.DIALOG_FONT; + } + + /** + * Returns the label control. + * + * @return the label control, or null + * if no label control has been created + */ + protected Label getLabelControl() { + return label; + } + + /** + * Returns this field editor's label component. + *

+ * The label is created if it does not already exist + *

+ * + * @param parent the parent + * @return the label control + */ + public Label getLabelControl(Composite parent) { + if (label is null) { + label = new Label(parent, DWT.LEFT); + label.setFont(parent.getFont()); + String text = getLabelText(); + if (text !is null) { + label.setText(text); + } + label.addDisposeListener(new class DisposeListener { + public void widgetDisposed(DisposeEvent event) { + label = null; + } + }); + } else { + checkParent(label, parent); + } + return label; + } + + /** + * Returns this field editor's label text. + * + * @return the label text + */ + public String getLabelText() { + return labelText; + } + + /** + * Returns the number of basic controls this field editor consists of. + * + * @return the number of controls + */ + public abstract int getNumberOfControls(); + + /** + * Returns the name of the preference this field editor operates on. + * + * @return the name of the preference + */ + public String getPreferenceName() { + return preferenceName; + } + + /** + * Returns the preference page in which this field editor + * appears. + * + * @return the preference page, or null if none + * @deprecated use #getPage() + */ + protected PreferencePage getPreferencePage() { + if(page !is null && cast(PreferencePage)page ) { + return cast(PreferencePage) page; + } + return null; + } + + /** + * Return the DialogPage that the receiver is sending + * updates to. + * + * @return DialogPage or null if it + * has not been set. + * + * @since 3.1 + */ + protected DialogPage getPage(){ + return page; + } + + /** + * Returns the preference store used by this field editor. + * + * @return the preference store, or null if none + * @see #setPreferenceStore + */ + public IPreferenceStore getPreferenceStore() { + return preferenceStore; + } + + /** + * Initialize the field editor with the given preference name and label. + * + * @param name the name of the preference this field editor works on + * @param text the label text of the field editor + */ + protected void init(String name, String text) { + Assert.isNotNull(name); + Assert.isNotNull(text); + preferenceName = name; + this.labelText = text; + } + + /** + * Returns whether this field editor contains a valid value. + *

+ * The default implementation of this framework method + * returns true. Subclasses wishing to perform + * validation should override both this method and + * refreshValidState. + *

+ * + * @return true if the field value is valid, + * and false if invalid + * @see #refreshValidState() + */ + public bool isValid() { + return true; + } + + /** + * Initializes this field editor with the preference value from + * the preference store. + */ + public void load() { + if (preferenceStore !is null) { + isDefaultPresented = false; + doLoad(); + refreshValidState(); + } + } + + /** + * Initializes this field editor with the default preference value + * from the preference store. + */ + public void loadDefault() { + if (preferenceStore !is null) { + isDefaultPresented = true; + doLoadDefault(); + refreshValidState(); + } + } + + /** + * Returns whether this field editor currently presents the + * default value for its preference. + * + * @return true if the default value is presented, + * and false otherwise + */ + public bool presentsDefaultValue() { + return isDefaultPresented; + } + + /** + * Refreshes this field editor's valid state after a value change + * and fires an IS_VALID property change event if + * warranted. + *

+ * The default implementation of this framework method does + * nothing. Subclasses wishing to perform validation should override + * both this method and isValid. + *

+ * + * @see #isValid + */ + protected void refreshValidState() { + } + + /** + * Sets the focus to this field editor. + *

+ * The default implementation of this framework method + * does nothing. Subclasses may reimplement. + *

+ */ + public void setFocus() { + // do nothing; + } + + /** + * Sets this field editor's label text. + * The label is typically presented to the left of the entry field. + * + * @param text the label text + */ + public void setLabelText(String text) { + Assert.isNotNull(text); + labelText = text; + if (label !is null) { + label.setText(text); + } + } + + /** + * Sets the name of the preference this field editor operates on. + *

+ * The ability to change this allows the same field editor object + * to be reused for different preferences. + *

+ *

+ * For example:

+ *

+     *  ...
+     *  editor.setPreferenceName("font");
+     *  editor.load();
+     * 
+ *

+ * + * @param name the name of the preference + */ + public void setPreferenceName(String name) { + preferenceName = name; + } + + /** + * Sets the preference page in which this field editor + * appears. + * + * @param preferencePage the preference page, or null if none + * @deprecated use #setPage(DialogPage) + */ + public void setPreferencePage(PreferencePage preferencePage) { + setPage(preferencePage); + } + + + /** + * Set the page to be the receiver. + * @param dialogPage + * + * @since 3.1 + */ + public void setPage(DialogPage dialogPage) { + page = dialogPage; + + } + + /** + * Sets the preference store used by this field editor. + * + * @param store the preference store, or null if none + * @see #getPreferenceStore + */ + public void setPreferenceStore(IPreferenceStore store) { + preferenceStore = store; + } + + /** + * Sets whether this field editor is presenting the default value. + * + * @param booleanValue true if the default value is being presented, + * and false otherwise + */ + protected void setPresentsDefaultValue(bool booleanValue) { + isDefaultPresented = booleanValue; + } + package void setPresentsDefaultValue_package(bool booleanValue) { + setPresentsDefaultValue(booleanValue); + } + + /** + * Sets or removes the property change listener for this field editor. + *

+ * Note that field editors can support only a single listener. + *

+ * + * @param listener a property change listener, or null + * to remove + */ + public void setPropertyChangeListener(IPropertyChangeListener listener) { + propertyChangeListener = listener; + } + + /** + * Shows the given error message in the page for this + * field editor if it has one. + * + * @param msg the error message + */ + protected void showErrorMessage(String msg) { + if (page !is null) { + page.setErrorMessage(msg); + } + } + + /** + * Shows the given message in the page for this + * field editor if it has one. + * + * @param msg the message + */ + protected void showMessage(String msg) { + if (page !is null) { + page.setErrorMessage(msg); + } + } + + /** + * Stores this field editor's value back into the preference store. + */ + public void store() { + if (preferenceStore is null) { + return; + } + + if (isDefaultPresented) { + preferenceStore.setToDefault(preferenceName); + } else { + doStore(); + } + } + + /** + * Set the GridData on button to be one that is spaced for the + * current font. + * @param button the button the data is being set on. + */ + + protected void setButtonLayoutData(Button button) { + + GridData data = new GridData(GridData.HORIZONTAL_ALIGN_FILL); + + // Compute and store a font metric + GC gc = new GC(button); + gc.setFont(button.getFont()); + FontMetrics fontMetrics = gc.getFontMetrics(); + gc.dispose(); + + int widthHint = dwtx.jface.dialogs.Dialog.Dialog + .convertVerticalDLUsToPixels(fontMetrics, + IDialogConstants.BUTTON_WIDTH); + data.widthHint = Math.max(widthHint, button.computeSize(DWT.DEFAULT, + DWT.DEFAULT, true).x); + button.setLayoutData(data); + } + + /** + * Set whether or not the controls in the field editor + * are enabled. + * @param enabled The enabled state. + * @param parent The parent of the controls in the group. + * Used to create the controls if required. + */ + public void setEnabled(bool enabled, Composite parent) { + getLabelControl(parent).setEnabled(enabled); + } + +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/FieldEditorPreferencePage.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/FieldEditorPreferencePage.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,382 @@ +/******************************************************************************* + * Copyright (c) 2000, 2007 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Chris Tilt (chris@tilts.net) - Bug 38547 - [Preferences] Changing preferences + * ignored after "Restore defaults" pressed. + * Port to the D programming language: + * Frank Benoit + *******************************************************************************/ +module dwtx.jface.preference.FieldEditorPreferencePage; + +import dwtx.jface.preference.PreferencePage; +import dwtx.jface.preference.FieldEditor; +import dwtx.jface.preference.FieldEditorPreferencePage; + +import tango.util.collection.ArraySeq; +import tango.util.collection.model.Seq; +// import java.util.Iterator; +// import java.util.List; + +import dwt.DWT; +import dwt.layout.GridData; +import dwt.layout.GridLayout; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwtx.jface.resource.ImageDescriptor; +import dwtx.jface.util.IPropertyChangeListener; +import dwtx.jface.util.PropertyChangeEvent; + +import dwt.dwthelper.utils; + +/** + * A special abstract preference page to host field editors. + *

+ * Subclasses must implement the createFieldEditors method + * and should override createLayout if a special layout of the field + * editors is needed. + *

+ */ +public abstract class FieldEditorPreferencePage : PreferencePage, + IPropertyChangeListener { + + /** + * Layout constant (value 0) indicating that + * each field editor is handled as a single component. + */ + public static const int FLAT = 0; + + /** + * Layout constant (value 1) indicating that + * the field editors' basic controls are put into a grid layout. + */ + public static const int GRID = 1; + + /** + * The vertical spacing used by layout styles FLAT + * and GRID. + */ + protected static const int VERTICAL_SPACING = 10; + + /** + * The margin width used by layout styles FLAT + * and GRID. + */ + protected static const int MARGIN_WIDTH = 0; + + /** + * The margin height used by layout styles FLAT + * and GRID. + */ + protected static const int MARGIN_HEIGHT = 0; + + /** + * The field editors, or null if not created yet. + */ + private Seq!(Object) fields = null; + + /** + * The layout style; either FLAT or GRID. + */ + private int style; + + /** + * The first invalid field editor, or null + * if all field editors are valid. + */ + private FieldEditor invalidFieldEditor = null; + + /** + * The parent composite for field editors + */ + private Composite fieldEditorParent; + + /** + * Create a new instance of the reciever. + */ + public this() { + this(FLAT); + } + + /** + * Creates a new field editor preference page with the given style, + * an empty title, and no image. + * + * @param style either GRID or FLAT + */ + protected this(int style) { + super(); + this.style = style; + } + + /** + * Creates a new field editor preference page with the given title + * and style, but no image. + * + * @param title the title of this preference page + * @param style either GRID or FLAT + */ + protected this(String title, int style) { + super(title); + this.style = style; + } + + /** + * Creates a new field editor preference page with the given title, + * image, and style. + * + * @param title the title of this preference page + * @param image the image for this preference page, or + * null if none + * @param style either GRID or FLAT + */ + protected this(String title, ImageDescriptor image, + int style) { + super(title, image); + this.style = style; + } + + /** + * Adds the given field editor to this page. + * + * @param editor the field editor + */ + protected void addField(FieldEditor editor) { + if (fields is null) { + fields = new ArraySeq!(Object); + } + fields.append(editor); + } + + /** + * Adjust the layout of the field editors so that + * they are properly aligned. + */ + protected void adjustGridLayout() { + int numColumns = calcNumberOfColumns(); + (cast(GridLayout) fieldEditorParent.getLayout()).numColumns = numColumns; + if (fields !is null) { + for (int i = 0; i < fields.size(); i++) { + FieldEditor fieldEditor = cast(FieldEditor) fields.get(i); + fieldEditor.adjustForNumColumns_package(numColumns); + } + } + } + + /** + * Applys the font to the field editors managed by this page. + */ + protected void applyFont() { + if (fields !is null) { + foreach( e; fields ){ + FieldEditor pe = cast(FieldEditor) e; + pe.applyFont_package(); + } + } + } + + /** + * Calculates the number of columns needed to host all field editors. + * + * @return the number of columns + */ + private int calcNumberOfColumns() { + int result = 0; + if (fields !is null) { + foreach( e; fields ){ + FieldEditor pe = cast(FieldEditor) e; + result = Math.max(result, pe.getNumberOfControls()); + } + } + return result; + } + + /** + * Recomputes the page's error state by calling isValid for + * every field editor. + */ + protected void checkState() { + bool valid = true; + invalidFieldEditor = null; + // The state can only be set to true if all + // field editors contain a valid value. So we must check them all + if (fields !is null) { + int size = fields.size(); + for (int i = 0; i < size; i++) { + FieldEditor editor = cast(FieldEditor) fields.get(i); + valid = valid && editor.isValid(); + if (!valid) { + invalidFieldEditor = editor; + break; + } + } + } + setValid(valid); + } + + /* (non-Javadoc) + * Method declared on PreferencePage. + */ + protected Control createContents(Composite parent) { + fieldEditorParent = new Composite(parent, DWT.NULL); + GridLayout layout = new GridLayout(); + layout.numColumns = 1; + layout.marginHeight = 0; + layout.marginWidth = 0; + fieldEditorParent.setLayout(layout); + fieldEditorParent.setFont(parent.getFont()); + + createFieldEditors(); + + if (style is GRID) { + adjustGridLayout(); + } + + initialize(); + checkState(); + return fieldEditorParent; + } + + /** + * Creates the page's field editors. + *

+ * The default implementation of this framework method + * does nothing. Subclass must implement this method to + * create the field editors. + *

+ *

+ * Subclasses should call getFieldEditorParent + * to obtain the parent control for each field editor. + * This same parent should not be used for more than + * one editor as the parent may change for each field + * editor depending on the layout style of the page + *

+ */ + protected abstract void createFieldEditors(); + + /** + * The field editor preference page implementation of an IDialogPage + * method disposes of this page's controls and images. + * Subclasses may override to release their own allocated DWT + * resources, but must call super.dispose. + */ + public void dispose() { + super.dispose(); + if (fields !is null) { + foreach( e; fields ){ + FieldEditor pe = cast(FieldEditor) e; + pe.setPage(null); + pe.setPropertyChangeListener(null); + pe.setPreferenceStore(null); + } + } + } + + /** + * Returns a parent composite for a field editor. + *

+ * This value must not be cached since a new parent + * may be created each time this method called. Thus + * this method must be called each time a field editor + * is constructed. + *

+ * + * @return a parent + */ + protected Composite getFieldEditorParent() { + if (style is FLAT) { + // Create a new parent for each field editor + Composite parent = new Composite(fieldEditorParent, DWT.NULL); + parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); + return parent; + } + // Just return the parent + return fieldEditorParent; + } + + /** + * Initializes all field editors. + */ + protected void initialize() { + if (fields !is null) { + foreach( e; fields ){ + FieldEditor pe = cast(FieldEditor) e; + pe.setPage(this); + pe.setPropertyChangeListener(this); + pe.setPreferenceStore(getPreferenceStore()); + pe.load(); + } + } + } + + /** + * The field editor preference page implementation of a PreferencePage + * method loads all the field editors with their default values. + */ + protected void performDefaults() { + if (fields !is null) { + foreach( e; fields ){ + FieldEditor pe = cast(FieldEditor) e; + pe.loadDefault(); + } + } + // Force a recalculation of my error state. + checkState(); + super.performDefaults(); + } + + /** + * The field editor preference page implementation of this + * PreferencePage method saves all field editors by + * calling FieldEditor.store. Note that this method + * does not save the preference store itself; it just stores the + * values back into the preference store. + * + * @see FieldEditor#store() + */ + public bool performOk() { + if (fields !is null) { + foreach( e; fields ){ + FieldEditor pe = cast(FieldEditor) e; + pe.store(); + pe.setPresentsDefaultValue_package(false); + } + } + return true; + } + + /** + * The field editor preference page implementation of this IPreferencePage + * (and IPropertyChangeListener) method intercepts IS_VALID + * events but passes other events on to its superclass. + */ + public void propertyChange(PropertyChangeEvent event) { + + if (event.getProperty().equals(FieldEditor.IS_VALID)) { + bool newValue = (cast(ValueWrapperBool) event.getNewValue()).value; + // If the new value is true then we must check all field editors. + // If it is false, then the page is invalid in any case. + if (newValue) { + checkState(); + } else { + invalidFieldEditor = cast(FieldEditor) event.getSource(); + setValid(newValue); + } + } + } + + /* (non-Javadoc) + * Method declared on IDialog. + */ + public void setVisible(bool visible) { + super.setVisible(visible); + if (visible && invalidFieldEditor !is null) { + invalidFieldEditor.setFocus(); + } + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/FileFieldEditor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/FileFieldEditor.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,174 @@ +/******************************************************************************* + * 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.FileFieldEditor; + +import dwtx.jface.preference.StringButtonFieldEditor; +// import java.io.File; + +import dwt.DWT; +import dwt.widgets.Composite; +import dwt.widgets.FileDialog; +import dwtx.jface.resource.JFaceResources; + +import dwt.dwthelper.utils; +import tango.io.FilePath; +import tango.io.FileSystem; + +/** + * A field editor for a file path type preference. A standard file + * dialog appears when the user presses the change button. + */ +public class FileFieldEditor : StringButtonFieldEditor { + + /** + * List of legal file extension suffixes, or null + * for system defaults. + */ + private String[] extensions = null; + + /** + * Indicates whether the path must be absolute; + * false by default. + */ + private bool enforceAbsolute = false; + + /** + * Creates a new file field editor + */ + protected this() { + } + + /** + * Creates a file field editor. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param parent the parent of the field editor's control + */ + public this(String name, String labelText, Composite parent) { + this(name, labelText, false, parent); + } + + /** + * Creates a file field editor. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param enforceAbsolute true if the file path + * must be absolute, and false otherwise + * @param parent the parent of the field editor's control + */ + public this(String name, String labelText, + bool enforceAbsolute, Composite parent) { + init(name, labelText); + this.enforceAbsolute = enforceAbsolute; + setErrorMessage(JFaceResources + .getString("FileFieldEditor.errorMessage"));//$NON-NLS-1$ + setChangeButtonText(JFaceResources.getString("openBrowse"));//$NON-NLS-1$ + setValidateStrategy(VALIDATE_ON_FOCUS_LOST); + createControl(parent); + } + + /* (non-Javadoc) + * Method declared on StringButtonFieldEditor. + * Opens the file chooser dialog and returns the selected file. + */ + protected String changePressed() { + auto f = new FilePath(getTextControl().getText()); + if (!f.exists()) { + f = cast(FilePath)null; + } + auto d = getFile(f); + if (d is null) { + return null; + } + + return FileSystem.toAbsolute( d ).toString(); + } + + /* (non-Javadoc) + * Method declared on StringFieldEditor. + * Checks whether the text input field specifies an existing file. + */ + protected bool checkState() { + + String msg = null; + + String path = getTextControl().getText(); + if (path !is null) { + path = path.trim(); + } else { + path = "";//$NON-NLS-1$ + } + if (path.length is 0) { + if (!isEmptyStringAllowed()) { + msg = getErrorMessage(); + } + } else { + auto file = new FilePath(path); + if (/+file.isFile()+/ file.exists && !file.isFolder ) { + if (enforceAbsolute && !file.isAbsolute()) { + msg = JFaceResources + .getString("FileFieldEditor.errorMessage2");//$NON-NLS-1$ + } + } else { + msg = getErrorMessage(); + } + } + + if (msg !is null) { // error + showErrorMessage(msg); + return false; + } + + // OK! + clearErrorMessage(); + return true; + } + + /** + * Helper to open the file chooser dialog. + * @param startingDirectory the directory to open the dialog on. + * @return File The File the user selected or null if they + * do not. + */ + private FilePath getFile(FilePath startingDirectory) { + + FileDialog dialog = new FileDialog(getShell(), DWT.OPEN); + if (startingDirectory !is null) { + dialog.setFileName(startingDirectory.path()); + } + if (extensions !is null) { + dialog.setFilterExtensions(extensions); + } + String file = dialog.open(); + if (file !is null) { + file = file.trim(); + if (file.length > 0) { + return new FilePath(file); + } + } + + return null; + } + + /** + * Sets this file field editor's file extension filter. + * + * @param extensions a list of file extension, or null + * to set the filter to the system's default value + */ + public void setFileExtensions(String[] extensions) { + this.extensions = extensions; + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/FontFieldEditor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/FontFieldEditor.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,427 @@ +/******************************************************************************* + * 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.FontFieldEditor; + +import dwtx.jface.preference.FieldEditor; +import dwtx.jface.preference.PreferenceConverter; + +import dwt.DWT; +import dwt.events.DisposeEvent; +import dwt.events.DisposeListener; +import dwt.events.SelectionAdapter; +import dwt.events.SelectionEvent; +import dwt.graphics.Font; +import dwt.graphics.FontData; +import dwt.layout.GridData; +import dwt.widgets.Button; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.FontDialog; +import dwt.widgets.Label; +import dwt.widgets.Text; +import dwtx.core.runtime.Assert; +import dwtx.jface.dialogs.IDialogConstants; +import dwtx.jface.resource.JFaceResources; +import dwtx.jface.resource.StringConverter; + +import dwt.dwthelper.utils; + +/** + * A field editor for a font type preference. + */ +public class FontFieldEditor : FieldEditor { + + /** + * The change font button, or null if none + * (before creation and after disposal). + */ + private Button changeFontButton = null; + + /** + * The text for the change font button, or null + * if missing. + */ + private String changeButtonText; + + /** + * The text for the preview, or null if no preview is desired + */ + private String previewText; + + /** + * Font data for the chosen font button, or null if none. + */ + private FontData[] chosenFont; + + /** + * The label that displays the selected font, or null if none. + */ + private Label valueControl; + + /** + * The previewer, or null if none. + */ + private DefaultPreviewer previewer; + + /** + * Internal font previewer implementation. + */ + private static class DefaultPreviewer { + private Text text; + + private String string; + + private Font font; + + /** + * Constructor for the previewer. + * @param s + * @param parent + */ + public this(String s, Composite parent) { + string = s; + text = new Text(parent, DWT.READ_ONLY | DWT.BORDER); + text.addDisposeListener(new class DisposeListener { + public void widgetDisposed(DisposeEvent e) { + if (font !is null) { + font.dispose(); + } + } + }); + if (string !is null) { + text.setText(string); + } + } + + /** + * @return the control the previewer is using + */ + public Control getControl() { + return text; + } + + /** + * Set the font to display with + * @param fontData + */ + public void setFont(FontData[] fontData) { + if (font !is null) { + font.dispose(); + } + font = new Font(text.getDisplay(), fontData); + text.setFont(font); + } + + /** + * @return the preferred size of the previewer. + */ + public int getPreferredExtent() { + return 40; + } + } + + /** + * Creates a new font field editor + */ + protected this() { + } + + /** + * Creates a font field editor with an optional preview area. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param previewAreaText the text used for the preview window. If it is + * null there will be no preview area, + * @param parent the parent of the field editor's control + */ + public this(String name, String labelText, + String previewAreaText, Composite parent) { + init(name, labelText); + previewText = previewAreaText; + changeButtonText = JFaceResources.getString("openChange"); //$NON-NLS-1$ + createControl(parent); + + } + + /** + * Creates a font field editor without a preview. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param parent the parent of the field editor's control + */ + public this(String name, String labelText, Composite parent) { + this(name, labelText, null, parent); + + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void adjustForNumColumns(int numColumns) { + + GridData data = new GridData(); + if (valueControl.getLayoutData() !is null) { + data = cast(GridData) valueControl.getLayoutData(); + } + + data.horizontalSpan = numColumns - getNumberOfControls() + 1; + valueControl.setLayoutData(data); + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void applyFont() { + if (chosenFont !is null && previewer !is null) { + previewer.setFont(chosenFont); + } + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doFillIntoGrid(Composite parent, int numColumns) { + getLabelControl(parent); + + valueControl = getValueControl(parent); + + GridData gd = new GridData(GridData.FILL_HORIZONTAL + | GridData.GRAB_HORIZONTAL); + gd.horizontalSpan = numColumns - getNumberOfControls() + 1; + valueControl.setLayoutData(gd); + if (previewText !is null) { + previewer = new DefaultPreviewer(previewText, parent); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.heightHint = previewer.getPreferredExtent(); + gd.widthHint = previewer.getPreferredExtent(); + previewer.getControl().setLayoutData(gd); + } + + changeFontButton = getChangeControl(parent); + gd = new GridData(); + int widthHint = convertHorizontalDLUsToPixels(changeFontButton, + IDialogConstants.BUTTON_WIDTH); + gd.widthHint = Math.max(widthHint, changeFontButton.computeSize( + DWT.DEFAULT, DWT.DEFAULT, true).x); + changeFontButton.setLayoutData(gd); + + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doLoad() { + if (changeFontButton is null) { + return; + } + updateFont(PreferenceConverter.getFontDataArray(getPreferenceStore(), + getPreferenceName())); + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doLoadDefault() { + if (changeFontButton is null) { + return; + } + updateFont(PreferenceConverter.getDefaultFontDataArray( + getPreferenceStore(), getPreferenceName())); + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doStore() { + if (chosenFont !is null) { + PreferenceConverter.setValue(getPreferenceStore(), + getPreferenceName(), chosenFont); + } + } + + /** + * Returns the change button for this field editor. + * + * @param parent The Composite to create the button in if required. + * @return the change button + */ + protected Button getChangeControl(Composite parent) { + if (changeFontButton is null) { + changeFontButton = new Button(parent, DWT.PUSH); + if (changeButtonText !is null) { + changeFontButton.setText(changeButtonText); + } + changeFontButton.addSelectionListener(new class SelectionAdapter { + public void widgetSelected(SelectionEvent event) { + FontDialog fontDialog = new FontDialog(changeFontButton + .getShell()); + if (chosenFont !is null) { + fontDialog.setFontList(chosenFont); + } + FontData font = fontDialog.open(); + if (font !is null) { + FontData[] oldFont = chosenFont; + if (oldFont is null) { + oldFont = JFaceResources.getDefaultFont() + .getFontData(); + } + setPresentsDefaultValue(false); + FontData[] newData = new FontData[1]; + newData[0] = font; + updateFont(newData); + fireValueChanged(VALUE, oldFont[0], font); + } + + } + }); + changeFontButton.addDisposeListener(new class DisposeListener { + public void widgetDisposed(DisposeEvent event) { + changeFontButton = null; + } + }); + changeFontButton.setFont(parent.getFont()); + setButtonLayoutData(changeFontButton); + } else { + checkParent(changeFontButton, parent); + } + return changeFontButton; + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + public int getNumberOfControls() { + if (previewer is null) { + return 3; + } + + return 4; + } + + /** + * Returns the preferred preview height. + * + * @return the height, or -1 if no previewer + * is installed + */ + public int getPreferredPreviewHeight() { + if (previewer is null) { + return -1; + } + return previewer.getPreferredExtent(); + } + + /** + * Returns the preview control for this field editor. + * + * @return the preview control + */ + public Control getPreviewControl() { + if (previewer is null) { + return null; + } + + return previewer.getControl(); + } + + /** + * Returns the value control for this field editor. The value control + * displays the currently selected font name. + * @param parent The Composite to create the viewer in if required + * @return the value control + */ + protected Label getValueControl(Composite parent) { + if (valueControl is null) { + valueControl = new Label(parent, DWT.LEFT); + valueControl.setFont(parent.getFont()); + valueControl.addDisposeListener(new class DisposeListener { + public void widgetDisposed(DisposeEvent event) { + valueControl = null; + } + }); + } else { + checkParent(valueControl, parent); + } + return valueControl; + } + + /** + * Sets the text of the change button. + * + * @param text the new text + */ + public void setChangeButtonText(String text) { + Assert.isNotNull(text); + changeButtonText = text; + if (changeFontButton !is null) { + changeFontButton.setText(text); + } + } + + /** + * Updates the change font button and the previewer to reflect the + * newly selected font. + * @param font The FontData[] to update with. + */ + private void updateFont(FontData font[]) { + FontData[] bestFont = JFaceResources.getFontRegistry().filterData( + font, valueControl.getDisplay()); + + //if we have nothing valid do as best we can + if (bestFont is null) { + bestFont = getDefaultFontData(); + } + + //Now cache this value in the receiver + this.chosenFont = bestFont; + + if (valueControl !is null) { + valueControl.setText(StringConverter.asString(chosenFont[0])); + } + if (previewer !is null) { + previewer.setFont(bestFont); + } + } + + /** + * Store the default preference for the field + * being edited + */ + protected void setToDefault() { + FontData[] defaultFontData = PreferenceConverter + .getDefaultFontDataArray(getPreferenceStore(), + getPreferenceName()); + PreferenceConverter.setValue(getPreferenceStore(), getPreferenceName(), + defaultFontData); + } + + /** + * Get the system default font data. + * @return FontData[] + */ + private FontData[] getDefaultFontData() { + return valueControl.getDisplay().getSystemFont().getFontData(); + } + + /* + * @see FieldEditor.setEnabled(bool,Composite). + */ + public void setEnabled(bool enabled, Composite parent) { + super.setEnabled(enabled, parent); + getChangeControl(parent).setEnabled(enabled); + getValueControl(parent).setEnabled(enabled); + } + +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/IPersistentPreferenceStore.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/IPersistentPreferenceStore.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,31 @@ +/******************************************************************************* + * 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.IPersistentPreferenceStore; + +import dwtx.jface.preference.IPreferenceStore; + +/** + * IPersistentPreferenceStore is a preference store that can + * be saved. + */ +public interface IPersistentPreferenceStore : IPreferenceStore { + + /** + * Saves the non-default-valued preferences known to this preference + * store to the file from which they were originally loaded. + * + * @exception java.io.IOException if there is a problem saving this store + */ + public void save(); + +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/IPreferenceNode.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/IPreferenceNode.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,120 @@ +/******************************************************************************* + * 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.IPreferenceNode; + +import dwtx.jface.preference.IPreferencePage; + +import dwt.graphics.Image; +import dwt.dwthelper.utils; + +/** + * Interface to a node in a preference dialog. + * A preference node maintains a label and image used to display the + * node in a preference dialog (usually in the form of a tree), + * as well as the preference page this node stands for. + * + * The node may use lazy creation for its page + * + * Note that all preference nodes must be dispose their resources. + * The node must dispose the page managed by this node, and any DWT resources + * allocated by this node (Images, Fonts, etc). + * However the node itself may be reused. + */ +public interface IPreferenceNode { + /** + * Adds the given preference node as a subnode of this + * preference node. + * + * @param node the node to add + */ + public void add(IPreferenceNode node); + + /** + * Creates the preference page for this node. + */ + public void createPage(); + + /** + * Release the page managed by this node, and any DWT resources + * held onto by this node (Images, Fonts, etc). + * + * Note that nodes are reused so this is not a call to dispose the + * node itself. + */ + public void disposeResources(); + + /** + * Returns the subnode of this contribution node with the given node id. + * + * @param id the preference node id + * @return the subnode, or null if none + */ + public IPreferenceNode findSubNode(String id); + + /** + * Returns the id of this contribution node. + * This id identifies a contribution node relative to its parent. + * + * @return the node id + */ + public String getId(); + + /** + * Returns the image used to present this node in a preference dialog. + * + * @return the image for this node, or null + * if there is no image for this node + */ + public Image getLabelImage(); + + /** + * Returns the text label used to present this node in a preference dialog. + * + * @return the text label for this node, or null + * if there is no label for this node + */ + public String getLabelText(); + + /** + * Returns the preference page for this node. + * + * @return the preference page + */ + public IPreferencePage getPage(); + + /** + * Returns an iterator over the subnodes (immediate children) + * of this contribution node. + * + * @return an IPreferenceNode array containing the child nodes + */ + public IPreferenceNode[] getSubNodes(); + + /** + * Removes the subnode of this preference node with the given node id. + * + * @param id the subnode id + * @return the removed subnode, or null if none + */ + public IPreferenceNode remove(String id); + + /** + * Removes the given preference node from the list of subnodes + * (immediate children) of this node. + * + * @param node the node to remove + * @return true if the node was removed, + * and false otherwise + */ + public bool remove(IPreferenceNode node); +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/IPreferencePage.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/IPreferencePage.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,82 @@ +/******************************************************************************* + * 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.IPreferencePage; + +import dwtx.jface.preference.IPreferencePageContainer; + +import dwt.graphics.Point; +import dwtx.jface.dialogs.IDialogPage; + +/** + * An interface for a preference page. This interface + * is used primarily by the page's container + */ +public interface IPreferencePage : IDialogPage { + + /** + * Computes a size for this page's UI component. + * + * @return the size of the preference page encoded as + * new Point(width,height), or + * (0,0) if the page doesn't currently have any UI component + */ + public Point computeSize(); + + /** + * Returns whether this dialog page is in a valid state. + * + * @return true if the page is in a valid state, + * and false if invalid + */ + public bool isValid(); + + /** + * Checks whether it is alright to leave this page. + * + * @return false to abort page flipping and the + * have the current page remain visible, and true + * to allow the page flip + */ + public bool okToLeave(); + + /** + * Notifies that the container of this preference page has been canceled. + * + * @return false to abort the container's cancel + * procedure and true to allow the cancel to happen + */ + public bool performCancel(); + + /** + * Notifies that the OK button of this page's container has been pressed. + * + * @return false to abort the container's OK + * processing and true to allow the OK to happen + */ + public bool performOk(); + + /** + * Sets or clears the container of this page. + * + * @param preferencePageContainer the preference page container, or null + */ + public void setContainer(IPreferencePageContainer preferencePageContainer); + + /** + * Sets the size of this page's UI component. + * + * @param size the size of the preference page encoded as + * new Point(width,height) + */ + public void setSize(Point size); +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/IPreferencePageContainer.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/IPreferencePageContainer.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,67 @@ +/******************************************************************************* + * 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.IPreferencePageContainer; + +import dwtx.jface.preference.IPreferenceStore; + +import dwt.dwthelper.utils; + +/** + * An interface used by a preference page to talk to + * its dialog. + */ +public interface IPreferencePageContainer { + /** + * Returns the preference store. + * + * @return the preference store, or null if none + */ + public IPreferenceStore getPreferenceStore(); + + /** + * Adjusts the enable state of the OK + * button to reflect the state of the currently active + * page in this container. + *

+ * This method is called by the container itself + * when its preference page changes and may be called + * by the page at other times to force a button state + * update. + *

+ */ + public void updateButtons(); + + /** + * Updates the message (or error message) shown in the message line to + * reflect the state of the currently active page in this container. + *

+ * This method is called by the container itself + * when its preference page changes and may be called + * by the page at other times to force a message + * update. + *

+ */ + public void updateMessage(); + + /** + * Updates the title to reflect the state of the + * currently active page in this container. + *

+ * This method is called by the container itself + * when its page changes and may be called + * by the page at other times to force a title + * update. + *

+ */ + public void updateTitle(); +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/IntegerFieldEditor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/IntegerFieldEditor.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,157 @@ +/******************************************************************************* + * 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.IntegerFieldEditor; + +import dwtx.jface.preference.StringFieldEditor; + +import dwt.widgets.Composite; +import dwt.widgets.Text; +import dwtx.jface.resource.JFaceResources; + +import dwt.dwthelper.utils; + +/** + * A field editor for an integer type preference. + */ +public class IntegerFieldEditor : StringFieldEditor { + private int minValidValue = 0; + + private int maxValidValue = int.max; + + private static const int DEFAULT_TEXT_LIMIT = 10; + + /** + * Creates a new integer field editor + */ + protected this() { + } + + /** + * Creates an integer field editor. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param parent the parent of the field editor's control + */ + public this(String name, String labelText, Composite parent) { + this(name, labelText, parent, DEFAULT_TEXT_LIMIT); + } + + /** + * Creates an integer field editor. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param parent the parent of the field editor's control + * @param textLimit the maximum number of characters in the text. + */ + public this(String name, String labelText, Composite parent, + int textLimit) { + init(name, labelText); + setTextLimit(textLimit); + setEmptyStringAllowed(false); + setErrorMessage(JFaceResources + .getString("IntegerFieldEditor.errorMessage"));//$NON-NLS-1$ + createControl(parent); + } + + /** + * Sets the range of valid values for this field. + * + * @param min the minimum allowed value (inclusive) + * @param max the maximum allowed value (inclusive) + */ + public void setValidRange(int min, int max) { + minValidValue = min; + maxValidValue = max; + setErrorMessage(JFaceResources.format( + "IntegerFieldEditor.errorMessageRange", //$NON-NLS-1$ + [ new Integer(min), new Integer(max) ])); + } + + /* (non-Javadoc) + * Method declared on StringFieldEditor. + * Checks whether the entered String is a valid integer or not. + */ + protected bool checkState() { + + Text text = getTextControl(); + + if (text is null) { + return false; + } + + String numberString = text.getText(); + try { + int number = Integer.valueOf(numberString).intValue(); + if (number >= minValidValue && number <= maxValidValue) { + clearErrorMessage(); + return true; + } + + showErrorMessage(); + return false; + + } catch (NumberFormatException e1) { + showErrorMessage(); + } + + return false; + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doLoad() { + Text text = getTextControl(); + if (text !is null) { + int value = getPreferenceStore().getInt(getPreferenceName()); + text.setText( tango.text.convert.Integer.toString(value));//$NON-NLS-1$ + } + + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doLoadDefault() { + Text text = getTextControl(); + if (text !is null) { + int value = getPreferenceStore().getDefaultInt(getPreferenceName()); + text.setText(tango.text.convert.Integer.toString( value));//$NON-NLS-1$ + } + valueChanged(); + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doStore() { + Text text = getTextControl(); + if (text !is null) { + Integer i = new Integer(text.getText()); + getPreferenceStore().setValue(getPreferenceName(), i.intValue()); + } + } + + /** + * Returns this field editor's current value as an integer. + * + * @return the value + * @exception NumberFormatException if the String does not + * contain a parsable integer + */ + public int getIntValue() { + return (new Integer(getStringValue())).intValue(); + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/ListEditor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/ListEditor.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,454 @@ +/******************************************************************************* + * 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.ListEditor; + +import dwtx.jface.preference.FieldEditor; + +import dwt.DWT; +import dwt.events.DisposeEvent; +import dwt.events.DisposeListener; +import dwt.events.SelectionAdapter; +import dwt.events.SelectionEvent; +import dwt.events.SelectionListener; +import dwt.layout.GridData; +import dwt.layout.GridLayout; +import dwt.widgets.Button; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.List; +import dwt.widgets.Shell; +import dwt.widgets.Widget; +import dwtx.core.runtime.Assert; +import dwtx.jface.dialogs.IDialogConstants; +import dwtx.jface.resource.JFaceResources; + +import dwt.dwthelper.utils; + +/** + * An abstract field editor that manages a list of input values. + * The editor displays a list containing the values, buttons for + * adding and removing values, and Up and Down buttons to adjust + * the order of elements in the list. + *

+ * Subclasses must implement the parseString, + * createList, and getNewInputObject + * framework methods. + *

+ */ +public abstract class ListEditor : FieldEditor { + + /** + * The list widget; null if none + * (before creation or after disposal). + */ + private List list; + + /** + * The button box containing the Add, Remove, Up, and Down buttons; + * null if none (before creation or after disposal). + */ + private Composite buttonBox; + + /** + * The Add button. + */ + private Button addButton; + + /** + * The Remove button. + */ + private Button removeButton; + + /** + * The Up button. + */ + private Button upButton; + + /** + * The Down button. + */ + private Button downButton; + + /** + * The selection listener. + */ + private SelectionListener selectionListener; + + /** + * Creates a new list field editor + */ + protected this() { + } + + /** + * Creates a list field editor. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param parent the parent of the field editor's control + */ + protected this(String name, String labelText, Composite parent) { + init(name, labelText); + createControl(parent); + } + + /** + * Notifies that the Add button has been pressed. + */ + private void addPressed() { + setPresentsDefaultValue(false); + String input = getNewInputObject(); + + if (input !is null) { + int index = list.getSelectionIndex(); + if (index >= 0) { + list.add(input, index + 1); + } else { + list.add(input, 0); + } + selectionChanged(); + } + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void adjustForNumColumns(int numColumns) { + Control control = getLabelControl(); + (cast(GridData) control.getLayoutData()).horizontalSpan = numColumns; + (cast(GridData) list.getLayoutData()).horizontalSpan = numColumns - 1; + } + + /** + * Creates the Add, Remove, Up, and Down button in the given button box. + * + * @param box the box for the buttons + */ + private void createButtons(Composite box) { + addButton = createPushButton(box, "ListEditor.add");//$NON-NLS-1$ + removeButton = createPushButton(box, "ListEditor.remove");//$NON-NLS-1$ + upButton = createPushButton(box, "ListEditor.up");//$NON-NLS-1$ + downButton = createPushButton(box, "ListEditor.down");//$NON-NLS-1$ + } + + /** + * Combines the given list of items into a single string. + * This method is the converse of parseString. + *

+ * Subclasses must implement this method. + *

+ * + * @param items the list of items + * @return the combined string + * @see #parseString + */ + protected abstract String createList(String[] items); + + /** + * Helper method to create a push button. + * + * @param parent the parent control + * @param key the resource name used to supply the button's label text + * @return Button + */ + private Button createPushButton(Composite parent, String key) { + Button button = new Button(parent, DWT.PUSH); + button.setText(JFaceResources.getString(key)); + button.setFont(parent.getFont()); + GridData data = new GridData(GridData.FILL_HORIZONTAL); + int widthHint = convertHorizontalDLUsToPixels(button, + IDialogConstants.BUTTON_WIDTH); + data.widthHint = Math.max(widthHint, button.computeSize(DWT.DEFAULT, + DWT.DEFAULT, true).x); + button.setLayoutData(data); + button.addSelectionListener(getSelectionListener()); + return button; + } + + /** + * Creates a selection listener. + */ + public void createSelectionListener() { + selectionListener = new class SelectionAdapter { + public void widgetSelected(SelectionEvent event) { + Widget widget = event.widget; + if (widget is addButton) { + addPressed(); + } else if (widget is removeButton) { + removePressed(); + } else if (widget is upButton) { + upPressed(); + } else if (widget is downButton) { + downPressed(); + } else if (widget is list) { + selectionChanged(); + } + } + }; + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doFillIntoGrid(Composite parent, int numColumns) { + Control control = getLabelControl(parent); + GridData gd = new GridData(); + gd.horizontalSpan = numColumns; + control.setLayoutData(gd); + + list = getListControl(parent); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.verticalAlignment = GridData.FILL; + gd.horizontalSpan = numColumns - 1; + gd.grabExcessHorizontalSpace = true; + list.setLayoutData(gd); + + buttonBox = getButtonBoxControl(parent); + gd = new GridData(); + gd.verticalAlignment = GridData.BEGINNING; + buttonBox.setLayoutData(gd); + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doLoad() { + if (list !is null) { + String s = getPreferenceStore().getString(getPreferenceName()); + String[] array = parseString(s); + for (int i = 0; i < array.length; i++) { + list.add(array[i]); + } + } + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doLoadDefault() { + if (list !is null) { + list.removeAll(); + String s = getPreferenceStore().getDefaultString( + getPreferenceName()); + String[] array = parseString(s); + for (int i = 0; i < array.length; i++) { + list.add(array[i]); + } + } + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doStore() { + String s = createList(list.getItems()); + if (s !is null) { + getPreferenceStore().setValue(getPreferenceName(), s); + } + } + + /** + * Notifies that the Down button has been pressed. + */ + private void downPressed() { + swap(false); + } + + /** + * Returns this field editor's button box containing the Add, Remove, + * Up, and Down button. + * + * @param parent the parent control + * @return the button box + */ + public Composite getButtonBoxControl(Composite parent) { + if (buttonBox is null) { + buttonBox = new Composite(parent, DWT.NULL); + GridLayout layout = new GridLayout(); + layout.marginWidth = 0; + buttonBox.setLayout(layout); + createButtons(buttonBox); + buttonBox.addDisposeListener(new class DisposeListener { + public void widgetDisposed(DisposeEvent event) { + addButton = null; + removeButton = null; + upButton = null; + downButton = null; + buttonBox = null; + } + }); + + } else { + checkParent(buttonBox, parent); + } + + selectionChanged(); + return buttonBox; + } + + /** + * Returns this field editor's list control. + * + * @param parent the parent control + * @return the list control + */ + public List getListControl(Composite parent) { + if (list is null) { + list = new List(parent, DWT.BORDER | DWT.SINGLE | DWT.V_SCROLL + | DWT.H_SCROLL); + list.setFont(parent.getFont()); + list.addSelectionListener(getSelectionListener()); + list.addDisposeListener(new class DisposeListener { + public void widgetDisposed(DisposeEvent event) { + list = null; + } + }); + } else { + checkParent(list, parent); + } + return list; + } + + /** + * Creates and returns a new item for the list. + *

+ * Subclasses must implement this method. + *

+ * + * @return a new item + */ + protected abstract String getNewInputObject(); + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + public int getNumberOfControls() { + return 2; + } + + /** + * Returns this field editor's selection listener. + * The listener is created if nessessary. + * + * @return the selection listener + */ + private SelectionListener getSelectionListener() { + if (selectionListener is null) { + createSelectionListener(); + } + return selectionListener; + } + + /** + * Returns this field editor's shell. + *

+ * This method is internal to the framework; subclassers should not call + * this method. + *

+ * + * @return the shell + */ + protected Shell getShell() { + if (addButton is null) { + return null; + } + return addButton.getShell(); + } + + /** + * Splits the given string into a list of strings. + * This method is the converse of createList. + *

+ * Subclasses must implement this method. + *

+ * + * @param stringList the string + * @return an array of String + * @see #createList + */ + protected abstract String[] parseString(String stringList); + + /** + * Notifies that the Remove button has been pressed. + */ + private void removePressed() { + setPresentsDefaultValue(false); + int index = list.getSelectionIndex(); + if (index >= 0) { + list.remove(index); + selectionChanged(); + } + } + + /** + * Notifies that the list selection has changed. + */ + private void selectionChanged() { + + int index = list.getSelectionIndex(); + int size = list.getItemCount(); + + removeButton.setEnabled(index >= 0); + upButton.setEnabled(size > 1 && index > 0); + downButton.setEnabled(size > 1 && index >= 0 && index < size - 1); + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + public void setFocus() { + if (list !is null) { + list.setFocus(); + } + } + + /** + * Moves the currently selected item up or down. + * + * @param up true if the item should move up, + * and false if it should move down + */ + private void swap(bool up) { + setPresentsDefaultValue(false); + int index = list.getSelectionIndex(); + int target = up ? index - 1 : index + 1; + + if (index >= 0) { + String[] selection = list.getSelection(); + Assert.isTrue(selection.length is 1); + list.remove(index); + list.add(selection[0], target); + list.setSelection(target); + } + selectionChanged(); + } + + /** + * Notifies that the Up button has been pressed. + */ + private void upPressed() { + swap(true); + } + + /* + * @see FieldEditor.setEnabled(bool,Composite). + */ + public void setEnabled(bool enabled, Composite parent) { + super.setEnabled(enabled, parent); + getListControl(parent).setEnabled(enabled); + addButton.setEnabled(enabled); + removeButton.setEnabled(enabled); + upButton.setEnabled(enabled); + downButton.setEnabled(enabled); + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/PathEditor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/PathEditor.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,113 @@ +/******************************************************************************* + * 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.PathEditor; + +import dwtx.jface.preference.ListEditor; + +import tango.io.FilePath; +import tango.io.FileConst; +// import java.util.ArrayList; +// import java.util.StringTokenizer; + +import dwt.widgets.Composite; +import dwt.widgets.DirectoryDialog; + +import dwt.dwthelper.utils; +import tango.text.Util; + +/** + * A field editor to edit directory paths. + */ +public class PathEditor : ListEditor { + + /** + * The last path, or null if none. + */ + private String lastPath; + + /** + * The special label text for directory chooser, + * or null if none. + */ + private String dirChooserLabelText; + + /** + * Creates a new path field editor + */ + protected this() { + } + + /** + * Creates a path field editor. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param dirChooserLabelText the label text displayed for the directory chooser + * @param parent the parent of the field editor's control + */ + public this(String name, String labelText, + String dirChooserLabelText, Composite parent) { + init(name, labelText); + this.dirChooserLabelText = dirChooserLabelText; + createControl(parent); + } + + /* (non-Javadoc) + * Method declared on ListEditor. + * Creates a single string from the given array by separating each + * string with the appropriate OS-specific path separator. + */ + protected String createList(String[] items) { + StringBuffer path = new StringBuffer("");//$NON-NLS-1$ + + for (int i = 0; i < items.length; i++) { + path.append(items[i]); + path.append(FileConst.PathSeparatorString); + } + return path.toString(); + } + + /* (non-Javadoc) + * Method declared on ListEditor. + * Creates a new path element by means of a directory dialog. + */ + protected String getNewInputObject() { + + DirectoryDialog dialog = new DirectoryDialog(getShell()); + if (dirChooserLabelText !is null) { + dialog.setMessage(dirChooserLabelText); + } + if (lastPath !is null) { + if ((new FilePath(lastPath)).exists()) { + dialog.setFilterPath(lastPath); + } + } + String dir = dialog.open(); + if (dir !is null) { + dir = dwt.dwthelper.utils.trim(dir); + if (dir.length is 0) { + return null; + } + lastPath = dir; + } + return dir; + } + + /* (non-Javadoc) + * Method declared on ListEditor. + */ + protected String[] parseString(String stringList) { + return tango.text.Util.delimit(stringList.dup, FileConst.PathSeparatorString + ~ "\n\r");//$NON-NLS-1$ + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/PreferenceContentProvider.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/PreferenceContentProvider.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,118 @@ +/******************************************************************************* + * 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.preference.PreferenceContentProvider; + +import dwtx.jface.preference.IPreferenceNode; +import dwtx.jface.preference.PreferenceManager; + +import dwtx.jface.viewers.ITreeContentProvider; +import dwtx.jface.viewers.Viewer; + +import dwt.dwthelper.utils; + +/** + * Provides a tree model for PreferenceManager content. + * + * @since 3.0 + */ +public class PreferenceContentProvider : ITreeContentProvider { + + private PreferenceManager manager; + + /* (non-Javadoc) + * @see dwtx.jface.viewers.IContentProvider#dispose() + */ + public void dispose() { + manager = null; + } + + /** + * Find the parent of the provided node. Will search recursivly through the + * preference tree. + * + * @param parent the possible parent node. + * @param target the target child node. + * @return the parent node of the child node. + */ + private IPreferenceNode findParent(IPreferenceNode parent, + IPreferenceNode target) { + if (parent.getId().equals(target.getId())) { + return null; + } + + IPreferenceNode found = parent.findSubNode(target.getId()); + if (found !is null) { + return parent; + } + + IPreferenceNode[] children = parent.getSubNodes(); + + for (int i = 0; i < children.length; i++) { + found = findParent(children[i], target); + if (found !is null) { + return found; + } + } + + return null; + } + + /* + * (non-Javadoc) + * @see dwtx.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object) + */ + public Object[] getChildren(Object parentElement) {//must be an instance of IPreferenceNode. + return arraycast!(Object)((cast(IPreferenceNode) parentElement).getSubNodes()); + } + + /* + * (non-Javadoc) + * @see dwtx.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) + */ + public Object[] getElements(Object inputElement) {// must be an instance of PreferenceManager. + return getChildren(cast(Object)(cast(PreferenceManager) inputElement).getRoot_package()); + } + + /* + * (non-Javadoc) + * @see dwtx.jface.viewers.ITreeContentProvider#getParent(java.lang.Object) + */ + public Object getParent(Object element) {//must be an instance of IPreferenceNode. + IPreferenceNode targetNode = cast(IPreferenceNode) element; + IPreferenceNode root = manager.getRoot_package(); + return cast(Object)findParent(root, targetNode); + } + + /* (non-Javadoc) + * @see dwtx.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object) + */ + public bool hasChildren(Object element) { + return getChildren(element).length > 0; + } + + /* (non-Javadoc) + * @see dwtx.jface.viewers.IContentProvider#inputChanged(dwtx.jface.viewers.Viewer, java.lang.Object, java.lang.Object) + */ + public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { + manager = cast(PreferenceManager) newInput; + } + /** + * Set the manager for the preferences. + * @param manager The manager to set. + * + * @since 3.1 + */ + protected void setManager(PreferenceManager manager) { + this.manager = manager; + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/PreferenceConverter.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/PreferenceConverter.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,563 @@ +/******************************************************************************* + * 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.PreferenceConverter; + +import dwtx.jface.preference.IPreferenceStore; + +// import java.util.Arrays; +// import java.util.StringTokenizer; + +import dwt.DWTException; +import dwt.graphics.FontData; +import dwt.graphics.Point; +import dwt.graphics.RGB; +import dwt.graphics.Rectangle; +import dwt.widgets.Display; +import dwtx.jface.resource.JFaceResources; +import dwtx.jface.resource.StringConverter; + +import dwt.dwthelper.utils; + +/** + * A utility class for dealing with preferences whose values are + * common DWT objects (color, points, rectangles, and font data). + * The static methods on this class handle the conversion between + * the DWT objects and their string representations. + *

+ * Usage: + *

+ * IPreferenceStore store = ...;
+ * PreferenceConverter.setValue(store, "bg", new RGB(127,127,127));
+ * ...
+ * RBG bgColor = PreferenceConverter.getValue(store, "bg");
+ * 
+ *

+ *

+ * This class contains static methods and fields only and cannot + * be instantiated. + *

+ * Note: touching this class has the side effect of creating a display (static initializer). + */ +public class PreferenceConverter { + + /** + * The default-default value for point preferences + * (the origin, (0,0)). + */ + public static const Point POINT_DEFAULT_DEFAULT; + + /** + * The default-default value for rectangle preferences + * (the empty rectangle (0,0,0,0)). + */ + public static const Rectangle RECTANGLE_DEFAULT_DEFAULT; + + /** + * The default-default value for color preferences + * (black, RGB(0,0,0)). + */ + public static const RGB COLOR_DEFAULT_DEFAULT; + + private static const String ENTRY_SEPARATOR = ";"; //$NON-NLS-1$ + + /** + * The default-default value for FontData[] preferences. + */ + public static const FontData[] FONTDATA_ARRAY_DEFAULT_DEFAULT; + + /** + * The default-default value for FontData preferences. + */ + public static const FontData FONTDATA_DEFAULT_DEFAULT; + static this() { + POINT_DEFAULT_DEFAULT = new Point(0, 0); + RECTANGLE_DEFAULT_DEFAULT = new Rectangle(0, + 0, 0, 0); + COLOR_DEFAULT_DEFAULT = new RGB(0, 0, 0); + Display display = Display.getCurrent(); + if (display is null) { + display = Display.getDefault (); + } + + FONTDATA_ARRAY_DEFAULT_DEFAULT = display.getSystemFont().getFontData(); + /** + * The default-default value for FontData preferences. + * This is left in for compatibility purposes. It is recommended that + * FONTDATA_ARRAY_DEFAULT_DEFAULT is actually used. + */ + + FONTDATA_DEFAULT_DEFAULT = FONTDATA_ARRAY_DEFAULT_DEFAULT[0]; + } + + /* (non-Javadoc) + * private constructor to prevent instantiation. + */ + private this() { + //no-op + } + + /** + * Helper method to construct a color from the given string. + * @param value the indentifier for the color + * @return RGB + */ + private static RGB basicGetColor(String value) { + + if (IPreferenceStore.STRING_DEFAULT_DEFAULT.equals(value)) { + return COLOR_DEFAULT_DEFAULT; + } + + RGB color = StringConverter.asRGB(value, null); + if (color is null) { + return COLOR_DEFAULT_DEFAULT; + } + return color; + } + + /** + * Helper method to construct a FontData from the given string. + * String is in the form FontData;FontData; in order that + * multiple FontDatas can be defined. + * @param value the identifier for the font + * @return FontData[] + * + * @since 3.0 + */ + public static FontData[] basicGetFontData(String value) { + if (IPreferenceStore.STRING_DEFAULT_DEFAULT.equals(value)) { + return FONTDATA_ARRAY_DEFAULT_DEFAULT; + } + + //Read in all of them to get the value + auto tokens = tango.text.Util.delimit( value, ENTRY_SEPARATOR); + int numTokens = tokens.length; + FontData[] fontData = new FontData[numTokens]; + + for (int i = 0; i < numTokens; i++) { + try { + fontData[i] = new FontData(tokens[i]); + } catch (DWTException error) { + return FONTDATA_ARRAY_DEFAULT_DEFAULT; + } catch (IllegalArgumentException error) { + return FONTDATA_ARRAY_DEFAULT_DEFAULT; + } + } + return fontData; + } + + /** + * Reads the supplied string and returns its corresponding + * FontData. If it cannot be read then the default FontData + * will be returned. + * + * @param fontDataValue the string value for the font data + * @return the font data + */ + public static FontData[] readFontData(String fontDataValue) { + return basicGetFontData(fontDataValue); + } + + /** + * Helper method to construct a point from the given string. + * @param value + * @return Point + */ + private static Point basicGetPoint(String value) { + Point dp = new Point(POINT_DEFAULT_DEFAULT.x, POINT_DEFAULT_DEFAULT.y); + if (IPreferenceStore.STRING_DEFAULT_DEFAULT.equals(value)) { + return dp; + } + return StringConverter.asPoint(value, dp); + } + + /** + * Helper method to construct a rectangle from the given string. + * @param value + * @return Rectangle + */ + private static Rectangle basicGetRectangle(String value) { + // We can't just return RECTANGLE_DEFAULT_DEFAULT because + // a rectangle object doesn't have value semantik. + Rectangle dr = new Rectangle(RECTANGLE_DEFAULT_DEFAULT.x, + RECTANGLE_DEFAULT_DEFAULT.y, RECTANGLE_DEFAULT_DEFAULT.width, + RECTANGLE_DEFAULT_DEFAULT.height); + + if (IPreferenceStore.STRING_DEFAULT_DEFAULT.equals(value)) { + return dr; + } + return StringConverter.asRectangle(value, dr); + } + + /** + * Returns the current value of the color-valued preference with the + * given name in the given preference store. + * Returns the default-default value (COLOR_DEFAULT_DEFAULT) + * if there is no preference with the given name, or if the current value + * cannot be treated as a color. + * + * @param store the preference store + * @param name the name of the preference + * @return the color-valued preference + */ + public static RGB getColor(IPreferenceStore store, String name) { + return basicGetColor(store.getString(name)); + } + + /** + * Returns the default value for the color-valued preference + * with the given name in the given preference store. + * Returns the default-default value (COLOR_DEFAULT_DEFAULT) + * is no default preference with the given name, or if the default + * value cannot be treated as a color. + * + * @param store the preference store + * @param name the name of the preference + * @return the default value of the preference + */ + public static RGB getDefaultColor(IPreferenceStore store, String name) { + return basicGetColor(store.getDefaultString(name)); + } + + /** + * Returns the default value array for the font-valued preference + * with the given name in the given preference store. + * Returns the default-default value (FONTDATA_ARRAY_DEFAULT_DEFAULT) + * is no default preference with the given name, or if the default + * value cannot be treated as font data. + * + * @param store the preference store + * @param name the name of the preference + * @return the default value of the preference + */ + public static FontData[] getDefaultFontDataArray(IPreferenceStore store, + String name) { + return basicGetFontData(store.getDefaultString(name)); + } + + /** + * Returns a single default value for the font-valued preference + * with the given name in the given preference store. + * Returns the default-default value (FONTDATA_DEFAULT_DEFAULT) + * is no default preference with the given name, or if the default + * value cannot be treated as font data. + * This method is provided for backwards compatibility. It is + * recommended that getDefaultFontDataArray is + * used instead. + * + * @param store the preference store + * @param name the name of the preference + * @return the default value of the preference + */ + public static FontData getDefaultFontData(IPreferenceStore store, + String name) { + return getDefaultFontDataArray(store, name)[0]; + } + + /** + * Returns the default value for the point-valued preference + * with the given name in the given preference store. + * Returns the default-default value (POINT_DEFAULT_DEFAULT) + * is no default preference with the given name, or if the default + * value cannot be treated as a point. + * + * @param store the preference store + * @param name the name of the preference + * @return the default value of the preference + */ + public static Point getDefaultPoint(IPreferenceStore store, String name) { + return basicGetPoint(store.getDefaultString(name)); + } + + /** + * Returns the default value for the rectangle-valued preference + * with the given name in the given preference store. + * Returns the default-default value (RECTANGLE_DEFAULT_DEFAULT) + * is no default preference with the given name, or if the default + * value cannot be treated as a rectangle. + * + * @param store the preference store + * @param name the name of the preference + * @return the default value of the preference + */ + public static Rectangle getDefaultRectangle(IPreferenceStore store, + String name) { + return basicGetRectangle(store.getDefaultString(name)); + } + + /** + * Returns the current value of the font-valued preference with the + * given name in the given preference store. + * Returns the default-default value (FONTDATA_ARRAY_DEFAULT_DEFAULT) + * if there is no preference with the given name, or if the current value + * cannot be treated as font data. + * + * @param store the preference store + * @param name the name of the preference + * @return the font-valued preference + */ + public static FontData[] getFontDataArray(IPreferenceStore store, + String name) { + return basicGetFontData(store.getString(name)); + } + + /** + * Returns the current value of the first entry of the + * font-valued preference with the + * given name in the given preference store. + * Returns the default-default value (FONTDATA_ARRAY_DEFAULT_DEFAULT) + * if there is no preference with the given name, or if the current value + * cannot be treated as font data. + * This API is provided for backwards compatibility. It is + * recommended that getFontDataArray is used instead. + * + * @param store the preference store + * @param name the name of the preference + * @return the font-valued preference + */ + public static FontData getFontData(IPreferenceStore store, String name) { + return getFontDataArray(store, name)[0]; + } + + /** + * Returns the current value of the point-valued preference with the + * given name in the given preference store. + * Returns the default-default value (POINT_DEFAULT_DEFAULT) + * if there is no preference with the given name, or if the current value + * cannot be treated as a point. + * + * @param store the preference store + * @param name the name of the preference + * @return the point-valued preference + */ + public static Point getPoint(IPreferenceStore store, String name) { + return basicGetPoint(store.getString(name)); + } + + /** + * Returns the current value of the rectangle-valued preference with the + * given name in the given preference store. + * Returns the default-default value (RECTANGLE_DEFAULT_DEFAULT) + * if there is no preference with the given name, or if the current value + * cannot be treated as a rectangle. + * + * @param store the preference store + * @param name the name of the preference + * @return the rectangle-valued preference + */ + public static Rectangle getRectangle(IPreferenceStore store, String name) { + return basicGetRectangle(store.getString(name)); + } + + /** + * Sets the default value of the preference with the given name + * in the given preference store. As FontDatas are stored as + * arrays this method is only provided for backwards compatibility. + * Use setDefault(IPreferenceStore, String, FontData[]) + * instead. + * + * @param store the preference store + * @param name the name of the preference + * @param value the new default value of the preference + */ + public static void setDefault(IPreferenceStore store, String name, + FontData value) { + FontData[] fontDatas = new FontData[1]; + fontDatas[0] = value; + setDefault(store, name, fontDatas); + } + + /** + * Sets the default value of the preference with the given name + * in the given preference store. + * + * @param store the preference store + * @param name the name of the preference + * @param value the new default value of the preference + */ + public static void setDefault(IPreferenceStore store, String name, + FontData[] value) { + store.setDefault(name, getStoredRepresentation(value)); + } + + /** + * Sets the default value of the preference with the given name + * in the given preference store. + * + * @param store the preference store + * @param name the name of the preference + * @param value the new default value of the preference + */ + public static void setDefault(IPreferenceStore store, String name, + Point value) { + store.setDefault(name, StringConverter.asString(value)); + } + + /** + * Sets the default value of the preference with the given name + * in the given preference store. + * + * @param store the preference store + * @param name the name of the preference + * @param value the new default value of the preference + */ + public static void setDefault(IPreferenceStore store, String name, + Rectangle value) { + store.setDefault(name, StringConverter.asString(value)); + } + + /** + * Sets the default value of the preference with the given name + * in the given preference store. + * + * @param store the preference store + * @param name the name of the preference + * @param value the new default value of the preference + */ + public static void setDefault(IPreferenceStore store, String name, RGB value) { + store.setDefault(name, StringConverter.asString(value)); + } + + /** + * Sets the current value of the preference with the given name + * in the given preference store. + *

+ * Included for backwards compatibility. This method is equivalent to + * setValue(store, name, new FontData[]{value}). + *

+ * + * @param store the preference store + * @param name the name of the preference + * @param value the new current value of the preference + */ + public static void setValue(IPreferenceStore store, String name, + FontData value) { + setValue(store, name, [ value ]); + } + + /** + * Sets the current value of the preference with the given name + * in the given preference store. This method also sets the corresponding + * key in the JFace font registry to the value and fires a + * property change event to listeners on the preference store. + * + *

+ * Note that this API does not update any other settings that may + * be dependant upon it. Only the value in the preference store + * and in the font registry is updated. + *

+ * @param store the preference store + * @param name the name of the preference + * @param value the new current value of the preference + * + * @see #putValue(IPreferenceStore, String, FontData[]) + */ + public static void setValue(IPreferenceStore store, String name, + FontData[] value) { + FontData[] oldValue = getFontDataArray(store, name); + // see if the font has changed + if (!Arrays.equals(oldValue, value)) { + store.putValue(name, getStoredRepresentation(value)); + JFaceResources.getFontRegistry().put(name, value); + store.firePropertyChangeEvent(name, new ArrayWrapperT!(FontData)(oldValue), new ArrayWrapperT!(FontData)(value)); + } + } + + /** + * Sets the current value of the preference with the given name + * in the given preference store. This method does not update + * the font registry or fire a property change event. + * + * @param store the preference store + * @param name the name of the preference + * @param value the new current value of the preference + * + * @see PreferenceConverter#setValue(IPreferenceStore, String, FontData[]) + */ + public static void putValue(IPreferenceStore store, String name, + FontData[] value) { + FontData[] oldValue = getFontDataArray(store, name); + // see if the font has changed + if (!Arrays.equals(oldValue, value)) { + store.putValue(name, getStoredRepresentation(value)); + } + } + + /** + * Returns the stored representation of the given array of FontData objects. + * The stored representation has the form FontData;FontData; + * Only includes the non-null entries. + * + * @param fontData the array of FontData objects + * @return the stored representation of the FontData objects + * @since 3.0 + */ + public static String getStoredRepresentation(FontData[] fontData) { + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < fontData.length; i++) { + if (fontData[i] !is null) { + buffer.append(fontData[i].toString()); + buffer.append(ENTRY_SEPARATOR); + } + } + return buffer.toString(); + } + + /** + * Sets the current value of the preference with the given name + * in the given preference store. + * + * @param store the preference store + * @param name the name of the preference + * @param value the new current value of the preference + */ + public static void setValue(IPreferenceStore store, String name, Point value) { + Point oldValue = getPoint(store, name); + if (oldValue is null || !oldValue.opEquals(value)) { + store.putValue(name, StringConverter.asString(value)); + store.firePropertyChangeEvent(name, oldValue, value); + } + } + + /** + * Sets the current value of the preference with the given name + * in the given preference store. + * + * @param store the preference store + * @param name the name of the preference + * @param value the new current value of the preference + */ + public static void setValue(IPreferenceStore store, String name, + Rectangle value) { + Rectangle oldValue = getRectangle(store, name); + if (oldValue is null || !oldValue.opEquals(value)) { + store.putValue(name, StringConverter.asString(value)); + store.firePropertyChangeEvent(name, oldValue, value); + } + } + + /** + * Sets the current value of the preference with the given name + * in the given preference store. + * + * @param store the preference store + * @param name the name of the preference + * @param value the new current value of the preference + */ + public static void setValue(IPreferenceStore store, String name, RGB value) { + RGB oldValue = getColor(store, name); + if (oldValue is null || !oldValue.opEquals(value)) { + store.putValue(name, StringConverter.asString(value)); + store.firePropertyChangeEvent(name, oldValue, value); + } + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/PreferenceDialog.d --- a/dwtx/jface/preference/PreferenceDialog.d Thu Apr 03 20:41:52 2008 +0200 +++ b/dwtx/jface/preference/PreferenceDialog.d Sat Apr 05 01:45:47 2008 +0200 @@ -14,17 +14,15 @@ *******************************************************************************/ 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 dwtx.jface.preference.IPreferencePageContainer; +import dwtx.jface.preference.IPreferencePage; +import dwtx.jface.preference.IPreferenceNode; +import dwtx.jface.preference.IPreferenceStore; +import dwtx.jface.preference.IPersistentPreferenceStore; +import dwtx.jface.preference.PreferenceManager; +import dwtx.jface.preference.PreferencePage; +import dwtx.jface.preference.PreferenceLabelProvider; +import dwtx.jface.preference.PreferenceContentProvider; import dwt.DWT; import dwt.custom.BusyIndicator; @@ -84,18 +82,21 @@ import dwtx.jface.viewers.TreeViewer; import dwtx.jface.viewers.ViewerFilter; +import dwt.dwthelper.utils; +import dwt.dwthelper.Runnable; + /** * 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 { +public class PreferenceDialog : TrayDialog, IPreferencePageContainer, IPageChangeProvider { /** * Layout for the page container. * */ - private class PageLayout extends Layout { + private class PageLayout : 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); @@ -144,17 +145,17 @@ /** * Indentifier for the error image */ - public static final String PREF_DLG_IMG_TITLE_ERROR = DLG_IMG_MESSAGE_ERROR; + public static const 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$ + public static const String PREF_DLG_TITLE_IMG = "preference_dialog_title_image"; //$NON-NLS-1$ /** * Return code used when dialog failed */ - protected static final int FAILED = 2; + protected static const int FAILED = 2; /** * The current preference page, or null if there is none. @@ -172,7 +173,7 @@ * * @see #setMinimumPageSize(Point) */ - private Point minimumPageSize = new Point(400, 400); + private Point minimumPageSize; /** * The OK button. @@ -208,7 +209,7 @@ */ private TreeViewer treeViewer; - private ListenerList pageChangedListeners = new ListenerList(); + private ListenerList pageChangedListeners; /** * Composite with a FormLayout to contain the title area @@ -226,7 +227,9 @@ * @param manager * the preference manager */ - public PreferenceDialog(Shell parentShell, PreferenceManager manager) { + public this(Shell parentShell, PreferenceManager manager) { + minimumPageSize = new Point(400, 400); + pageChangedListeners = new ListenerList(); super(parentShell); setShellStyle(getShellStyle() | DWT.RESIZE | DWT.MAX); preferenceManager = manager; @@ -261,13 +264,21 @@ */ 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(); + foreach( e; preferenceManager.getElements(PreferenceManager.PRE_ORDER)){ + IPreferenceNode node = cast(IPreferenceNode) e; if (getPage(node) !is null) { - SafeRunnable.run(new SafeRunnable() { + + // this_: strange workaround for compiler error with dmd 1.028 in run() + SafeRunnable.run(new class(this) SafeRunnable { + PreferenceDialog this_; + IPreferenceNode node_; + this(PreferenceDialog outer_){ + node_=node; + this_=outer_; + auto p = this_.getPage( node ); + } public void run() { - if (!getPage(node).performCancel()) { + if (!this_.getPage(node_).performCancel()) { return; } } @@ -294,14 +305,14 @@ public bool close() { //Do this is in a SafeRunnable as it may run client code - SafeRunnable runnable = new SafeRunnable(){ + SafeRunnable runnable = new class SafeRunnable{ /* (non-Javadoc) * @see dwtx.core.runtime.ISafeRunnable#run() */ - public void run() throws Exception { - List nodes = preferenceManager.getElements(PreferenceManager.PRE_ORDER); + public void run() { + auto nodes = preferenceManager.getElements(PreferenceManager.PRE_ORDER); for (int i = 0; i < nodes.size(); i++) { - IPreferenceNode node = (IPreferenceNode) nodes.get(i); + IPreferenceNode node = cast(IPreferenceNode) nodes.get(i); node.disposeResources(); } @@ -310,7 +321,7 @@ /* (non-Javadoc) * @see dwtx.jface.util.SafeRunnable#handleException(java.lang.Throwable) */ - public void handleException(Throwable e) { + public void handleException(Exception e) { super.handleException(e); clearSelectedNode();//Do not cache a node with problems } @@ -329,7 +340,7 @@ protected void configureShell(Shell newShell) { super.configureShell(newShell); newShell.setText(JFaceResources.getString("PreferenceDialog.title")); //$NON-NLS-1$ - newShell.addShellListener(new ShellAdapter() { + newShell.addShellListener(new class ShellAdapter { public void shellActivated(ShellEvent e) { if (lastShellSize is null) { lastShellSize = getShell().getSize(); @@ -370,11 +381,15 @@ * * @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() { + protected Control createContents(Composite parent) { + Control[1] control; + BusyIndicator.showWhile(getShell().getDisplay(), new class Runnable { + Composite parent_; + this(){ + parent_=parent; + } public void run() { - control[0] = PreferenceDialog.super.createContents(parent); + control[0] = callSuperCreateContents(parent); // Add the first page selectSavedItem(); } @@ -382,15 +397,17 @@ return control[0]; } - + private Control callSuperCreateContents( Composite c ){ + return super.createContents( c ); + } /* * (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()); + final Composite composite = cast(Composite) super.createDialogArea(parent); + GridLayout parentLayout = (cast(GridLayout) composite.getLayout()); parentLayout.numColumns = 4; parentLayout.marginHeight = 0; parentLayout.marginWidth = 0; @@ -470,13 +487,21 @@ * * @since 3.1 */ - protected Sash createSash(final Composite composite, final Control rightControl) { - final Sash sash = new Sash(composite, DWT.VERTICAL); + protected Sash createSash(Composite composite, Control rightControl) { + 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() { + sash.addListener(DWT.Selection, new class Listener { + Composite composite_; + Control rightControl_; + Sash sash_; + this(){ + composite_=composite; + rightControl_=rightControl; + sash_=sash; + } /* * (non-Javadoc) * @@ -486,8 +511,8 @@ if (event.detail is DWT.DRAG) { return; } - int shift = event.x - sash.getBounds().x; - GridData data = (GridData) rightControl.getLayoutData(); + int shift = event.x - sash_.getBounds().x; + GridData data = cast(GridData) rightControl_.getLayoutData(); int newWidthHint = data.widthHint + shift; if (newWidthHint < 20) { return; @@ -496,10 +521,10 @@ 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); + bool customSize = !computedSize.opEquals(currentSize); data.widthHint = newWidthHint; setLastTreeWidth(newWidthHint); - composite.layout(true); + 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 @@ -508,7 +533,7 @@ computedSize.x = Math.max(computedSize.x, currentSize.x); } computedSize.y = Math.max(computedSize.y, currentSize.y); - if (computedSize.equals(currentSize)) { + if (computedSize.opEquals(currentSize)) { return; } setShellSize(computedSize.x, computedSize.y); @@ -596,7 +621,7 @@ messageArea = new DialogMessageArea(); messageArea.createContents(titleArea); - titleArea.addControlListener(new ControlAdapter() { + titleArea.addControlListener(new class ControlAdapter { /* (non-Javadoc) * @see dwt.events.ControlAdapter#controlResized(dwt.events.ControlEvent) */ @@ -605,7 +630,7 @@ } }); - final IPropertyChangeListener fontListener = new IPropertyChangeListener() { + final IPropertyChangeListener fontListener = new class IPropertyChangeListener { public void propertyChange(PropertyChangeEvent event) { if (JFaceResources.BANNER_FONT.equals(event.getProperty())) { updateMessage(); @@ -614,7 +639,7 @@ updateMessage(); Font dialogFont = JFaceResources.getDialogFont(); updateTreeFont(dialogFont); - Control[] children = ((Composite) buttonBar).getChildren(); + Control[] children = (cast(Composite) buttonBar).getChildren(); for (int i = 0; i < children.length; i++) { children[i].setFont(dialogFont); } @@ -622,7 +647,7 @@ } }; - titleArea.addDisposeListener(new DisposeListener() { + titleArea.addDisposeListener(new class DisposeListener { public void widgetDisposed(DisposeEvent event) { JFaceResources.getFontRegistry().removeListener(fontListener); } @@ -684,50 +709,58 @@ * * @since 3.1 */ - protected void addListeners(final TreeViewer viewer) { - viewer.addPostSelectionChangedListener(new ISelectionChangedListener() { + protected void addListeners(TreeViewer viewer) { + viewer.addPostSelectionChangedListener(new class ISelectionChangedListener { + TreeViewer viewer_; + this(){ + viewer_=viewer; + } 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); + viewer_.removePostSelectionChangedListener(this); showPageFlippingAbortDialog(); selectCurrentPageAgain(); clearSelectedNode(); } finally { - viewer.addPostSelectionChangedListener(this); + viewer_.addPostSelectionChangedListener(this); } } public void selectionChanged(SelectionChangedEvent event) { - Object selection = getSingleSelection(event.getSelection()); - if (selection instanceof IPreferenceNode) { + Object selection = cast(Object) getSingleSelection(event.getSelection()); + if (cast(IPreferenceNode)selection ) { if (!isCurrentPageValid()) { handleError(); - } else if (!showPage((IPreferenceNode) selection)) { + } else if (!showPage(cast(IPreferenceNode) selection)) { // Page flipping wasn't successful handleError(); } else { // Everything went well - lastSuccessfulNode = (IPreferenceNode) selection; + lastSuccessfulNode = cast(IPreferenceNode) selection; } } } }); - ((Tree) viewer.getControl()).addSelectionListener(new SelectionAdapter() { - public void widgetDefaultSelected(final SelectionEvent event) { - ISelection selection = viewer.getSelection(); + (cast(Tree) viewer.getControl()).addSelectionListener(new class SelectionAdapter { + TreeViewer viewer_; + this(){ + viewer_=viewer; + } + public void widgetDefaultSelected(SelectionEvent event) { + ISelection selection = viewer_.getSelection(); if (selection.isEmpty()) { return; } IPreferenceNode singleSelection = getSingleSelection(selection); - bool expanded = viewer.getExpandedState(singleSelection); - viewer.setExpandedState(singleSelection, !expanded); + bool expanded = viewer_.getExpandedState(cast(Object)singleSelection); + viewer_.setExpandedState(cast(Object)singleSelection, !expanded); } }); //Register help listener on the tree to use context sensitive help - viewer.getControl().addHelpListener(new HelpListener() { + viewer.getControl().addHelpListener(new class HelpListener { public void helpRequested(HelpEvent event) { // call perform help on the current page if (currentPage !is null) { @@ -747,9 +780,8 @@ * 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(); + foreach( e; preferenceManager.getElements(PreferenceManager.POST_ORDER)){ + IPreferenceNode node = cast(IPreferenceNode) e; if (node.getId().equals(nodeId)) { return node; } @@ -800,9 +832,9 @@ */ protected IPreferenceNode getSingleSelection(ISelection selection) { if (!selection.isEmpty()) { - IStructuredSelection structured = (IStructuredSelection) selection; - if (structured.getFirstElement() instanceof IPreferenceNode) { - return (IPreferenceNode) structured.getFirstElement(); + IStructuredSelection structured = cast(IStructuredSelection) selection; + if (cast(IPreferenceNode)structured.getFirstElement() ) { + return cast(IPreferenceNode) structured.getFirstElement(); } } return null; @@ -828,17 +860,16 @@ *

*/ protected void handleSave() { - Iterator nodes = preferenceManager.getElements(PreferenceManager.PRE_ORDER).iterator(); - while (nodes.hasNext()) { - IPreferenceNode node = (IPreferenceNode) nodes.next(); + foreach( e; preferenceManager.getElements(PreferenceManager.PRE_ORDER)){ + IPreferenceNode node = cast(IPreferenceNode) e; IPreferencePage page = node.getPage(); - if (page instanceof PreferencePage) { + if (cast(PreferencePage)page ) { // Save now in case tbe workbench does not shutdown cleanly - IPreferenceStore store = ((PreferencePage) page).getPreferenceStore(); + IPreferenceStore store = (cast(PreferencePage) page).getPreferenceStore(); if (store !is null && store.needsSaving() - && store instanceof IPersistentPreferenceStore) { + && cast(IPersistentPreferenceStore)store ) { try { - ((IPersistentPreferenceStore) store).save(); + (cast(IPersistentPreferenceStore) store).save(); } catch (IOException e) { MessageDialog .openError( @@ -846,7 +877,7 @@ JFaceResources.getString("PreferenceDialog.saveErrorTitle"), //$NON-NLS-1$ JFaceResources .format( - "PreferenceDialog.saveErrorMessage", new Object[] { page.getTitle(), e.getMessage() })); //$NON-NLS-1$ + "PreferenceDialog.saveErrorMessage", [ page.getTitle(), e.msg ])); //$NON-NLS-1$ } } } @@ -913,7 +944,7 @@ * save any state, and then calls close to close this dialog. */ protected void okPressed() { - SafeRunnable.run(new SafeRunnable() { + SafeRunnable.run(new class SafeRunnable { private bool errorOccurred; /* @@ -927,10 +958,8 @@ 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(); + foreach( e; preferenceManager.getElements(PreferenceManager.PRE_ORDER)){ + IPreferenceNode node = cast(IPreferenceNode) e; IPreferencePage page = node.getPage(); if (page !is null) { if (!page.performOk()){ @@ -946,16 +975,18 @@ if(hasFailedOK){ setReturnCode(FAILED); getButton(IDialogConstants.OK_ID).setEnabled(true); - return; + //return; } + else{ - if (!errorOccurred) { - //Give subclasses the choice to save the state of the - //preference pages. - handleSave(); + if (!errorOccurred) { + //Give subclasses the choice to save the state of the + //preference pages. + handleSave(); + } + setReturnCode(OK); + close(); } - setReturnCode(OK); - close(); } } @@ -964,7 +995,7 @@ * * @see dwtx.core.runtime.ISafeRunnable#handleException(java.lang.Throwable) */ - public void handleException(Throwable e) { + public void handleException(Exception e) { errorOccurred = true; Policy.getLog().log(new Status(IStatus.ERROR, Policy.JFACE, 0, e.toString(), e)); @@ -985,7 +1016,7 @@ if (lastSuccessfulNode is null) { return; } - getTreeViewer().setSelection(new StructuredSelection(lastSuccessfulNode)); + getTreeViewer().setSelection(new StructuredSelection(cast(Object)lastSuccessfulNode)); currentPage.setVisible(true); } @@ -1002,8 +1033,8 @@ 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)) { + if (!filters[j].select(this.treeViewer, cast(Object)preferenceManager + .getRoot_package(), cast(Object)selectedNode)) { selectedNode = null; break; } @@ -1016,7 +1047,7 @@ } } if (node !is null) { - getTreeViewer().setSelection(new StructuredSelection(node), true); + getTreeViewer().setSelection(new StructuredSelection(cast(Object)node), true); // Keep focus in tree. See bugs 2692, 2621, and 6775. getTreeViewer().getControl().setFocus(); } @@ -1122,7 +1153,7 @@ * @see #getPreferenceStore */ public void setPreferenceStore(IPreferenceStore store) { - Assert.isNotNull(store); + Assert.isNotNull(cast(Object)store); preferenceStore = store; } @@ -1131,9 +1162,9 @@ */ private void setSelectedNode() { String storeValue = null; - IStructuredSelection selection = (IStructuredSelection) getTreeViewer().getSelection(); + IStructuredSelection selection = cast(IStructuredSelection) getTreeViewer().getSelection(); if (selection.size() is 1) { - IPreferenceNode node = (IPreferenceNode) selection.getFirstElement(); + IPreferenceNode node = cast(IPreferenceNode) selection.getFirstElement(); storeValue = node.getId(); } setSelectedNodePreference(storeValue); @@ -1213,9 +1244,9 @@ // 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) { + bool[1] failed; failed[0] = false; + SafeRunnable.run(new class ISafeRunnable { + public void handleException(Exception e) { failed[0] = true; } @@ -1235,8 +1266,8 @@ // 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) { + SafeRunnable.run(new class ISafeRunnable { + public void handleException(Exception e) { size[0] = failed; } @@ -1244,7 +1275,7 @@ size[0] = currentPage.computeSize(); } }); - if (size[0].equals(failed)) { + if (size[0].opEquals(failed)) { return false; } Point contentSize = size[0]; @@ -1259,7 +1290,7 @@ 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)) { + if ((hdiff > 0 || vdiff > 0) && shellSize.opEquals(lastShellSize)) { hdiff = Math.max(0, hdiff); vdiff = Math.max(0, vdiff); setShellSize(shellSize.x + hdiff, shellSize.y + vdiff); @@ -1336,7 +1367,7 @@ updateButtons(); //Saved the selected node in the preferences setSelectedNode(); - firePageChanged(new PageChangedEvent(this, getCurrentPage())); + firePageChanged(new PageChangedEvent(this, cast(Object)getCurrentPage())); } /* @@ -1361,8 +1392,8 @@ errorMessage = currentPage.getErrorMessage(); } int messageType = IMessageProvider.NONE; - if (message !is null && currentPage instanceof IMessageProvider) { - messageType = ((IMessageProvider) currentPage).getMessageType(); + if (message !is null && cast(IMessageProvider)currentPage ) { + messageType = (cast(IMessageProvider) currentPage).getMessageType(); } if (errorMessage is null){ @@ -1472,7 +1503,7 @@ * @since 3.1 */ public Object getSelectedPage() { - return getCurrentPage(); + return cast(Object)getCurrentPage(); } /** @@ -1480,7 +1511,7 @@ * @since 3.1 */ public void addPageChangedListener(IPageChangedListener listener) { - pageChangedListeners.add(listener); + pageChangedListeners.add(cast(Object)listener); } /** @@ -1488,7 +1519,7 @@ * @since 3.1 */ public void removePageChangedListener(IPageChangedListener listener) { - pageChangedListeners.remove(listener); + pageChangedListeners.remove(cast(Object)listener); } @@ -1503,16 +1534,20 @@ * * @since 3.1 */ - protected void firePageChanged(final PageChangedEvent event) { + protected void firePageChanged(PageChangedEvent event) { Object[] listeners = pageChangedListeners.getListeners(); for (int i = 0; i < listeners.length; i++) { - final IPageChangedListener l = (IPageChangedListener) listeners[i]; - SafeRunnable.run(new SafeRunnable() { + SafeRunnable.run(new class SafeRunnable { + PageChangedEvent event_; + IPageChangedListener l; + this(){ + event_=event; + l = cast(IPageChangedListener) listeners[i]; + } public void run() { - l.pageChanged(event); + l.pageChanged(event_); } }); } } } -++/ \ No newline at end of file diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/PreferenceLabelProvider.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/PreferenceLabelProvider.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,44 @@ +/******************************************************************************* + * 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.preference.PreferenceLabelProvider; + +import dwtx.jface.preference.IPreferenceNode; + +import dwt.graphics.Image; +import dwtx.jface.viewers.LabelProvider; + +import dwt.dwthelper.utils; + +/** + * Provides labels for IPreferenceNode objects. + * + * @since 3.0 + */ +public class PreferenceLabelProvider : LabelProvider { + + /** + * @param element must be an instance of IPreferenceNode. + * @see dwtx.jface.viewers.ILabelProvider#getText(java.lang.Object) + */ + public String getText(Object element) { + return (cast(IPreferenceNode) element).getLabelText(); + } + + /** + * @param element must be an instance of IPreferenceNode. + * @see dwtx.jface.viewers.ILabelProvider#getImage(java.lang.Object) + */ + public Image getImage(Object element) { + return (cast(IPreferenceNode) element).getLabelImage(); + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/PreferenceManager.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/PreferenceManager.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,257 @@ +/******************************************************************************* + * 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.PreferenceManager; + +import dwtx.jface.preference.PreferenceNode; +import dwtx.jface.preference.IPreferenceNode; + +import tango.util.collection.ArraySeq; +import tango.util.collection.model.Seq; +// import java.util.List; +// import java.util.StringTokenizer; + +import dwtx.core.runtime.Assert; + +import dwt.dwthelper.utils; +import tango.text.Util; + +/** + * A preference manager maintains a hierarchy of preference nodes and + * associated preference pages. + */ +public class PreferenceManager { + /** + * Pre-order traversal means visit the root first, + * then the children. + */ + public static const int PRE_ORDER = 0; + + /** + * Post-order means visit the children, and then the root. + */ + public static const int POST_ORDER = 1; + + /** + * The root node. + * Note that the root node is a special internal node + * that is used to collect together all the nodes that + * have no parent; it is not given out to clients. + */ + PreferenceNode root; + + /** + * The path separator character. + */ + String separator; + + /** + * Creates a new preference manager. + */ + public this() { + this('.'); + } + + /** + * Creates a new preference manager with the given + * the path separator. + * + * @param separatorChar the separator character + */ + public this(char separatorChar) { + root = new PreferenceNode("");//$NON-NLS-1$ + separator = [ separatorChar ]; + } + + /** + * Adds the given preference node as a subnode of the + * node at the given path. + * + * @param path the path + * @param node the node to add + * @return true if the add was successful, + * and false if there is no contribution at + * the given path + */ + public bool addTo(String path, IPreferenceNode node) { + IPreferenceNode target = find(path); + if (target is null) { + return false; + } + target.add(node); + return true; + } + + /** + * Adds the given preference node as a subnode of the + * root. + * + * @param node the node to add, which must implement + * IPreferenceNode + */ + public void addToRoot(IPreferenceNode node) { + Assert.isNotNull(cast(Object)node); + root.add(node); + } + + /** + * Recursively enumerates all nodes at or below the given node + * and adds them to the given list in the given order. + * + * @param node the starting node + * @param sequence a read-write list of preference nodes + * (element type: IPreferenceNode) + * in the given order + * @param order the traversal order, one of + * PRE_ORDER and POST_ORDER + */ + protected void buildSequence(IPreferenceNode node, Seq!(Object) sequence, int order) { + if (order is PRE_ORDER) { + sequence.append(cast(Object)node); + } + IPreferenceNode[] subnodes = node.getSubNodes(); + for (int i = 0; i < subnodes.length; i++) { + buildSequence(subnodes[i], sequence, order); + } + if (order is POST_ORDER) { + sequence.append(cast(Object)node); + } + } + + /** + * Finds and returns the contribution node at the given path. + * + * @param path the path + * @return the node, or null if none + */ + public IPreferenceNode find(String path) { + return find(path,root); + } + + /** + * Finds and returns the preference node directly + * below the top at the given path. + * + * @param path the path + * @param top top at the given path + * @return the node, or null if none + * + * @since 3.1 + */ + protected IPreferenceNode find(String path,IPreferenceNode top){ + Assert.isNotNull(path); + auto tokens = tango.text.Util.delimit( path, separator ); + IPreferenceNode node = top; + foreach( id; tokens ){ + node = node.findSubNode(id); + if (node is null) { + return null; + } + } + if (node is top) { + return null; + } + return node; + } + + /** + * Returns all preference nodes managed by this + * manager. + * + * @param order the traversal order, one of + * PRE_ORDER and POST_ORDER + * @return a list of preference nodes + * (element type: IPreferenceNode) + * in the given order + */ + public Seq!(Object) getElements(int order) { + Assert.isTrue(order is PRE_ORDER || order is POST_ORDER, + "invalid traversal order");//$NON-NLS-1$ + auto sequence = new ArraySeq!(Object); + IPreferenceNode[] subnodes = getRoot().getSubNodes(); + for (int i = 0; i < subnodes.length; i++) { + buildSequence(subnodes[i], sequence, order); + } + return sequence; + } + + /** + * Returns the root node. + * Note that the root node is a special internal node + * that is used to collect together all the nodes that + * have no parent; it is not given out to clients. + * + * @return the root node + */ + protected IPreferenceNode getRoot() { + return root; + } + package IPreferenceNode getRoot_package() { + return getRoot(); + } + + /** + * Returns the root level nodes of this preference manager. + * + * @return an array containing the root nodes + * @since 3.2 + */ + public final IPreferenceNode[] getRootSubNodes() { + return getRoot().getSubNodes(); + } + + /** + * Removes the preference node at the given path. + * + * @param path + * the path + * @return the node that was removed, or null if there was no + * node at the given path + */ + public IPreferenceNode remove(String path) { + Assert.isNotNull(path); + int index = path.lastIndexOf(separator); + if (index is -1) { + return root.remove(path); + } + // Make sure that the last character in the string isn't the "." + Assert.isTrue(index < path.length - 1, "Path can not end with a dot");//$NON-NLS-1$ + String parentPath = path.substring(0, index); + String id = path.substring(index + 1); + IPreferenceNode parentNode = find(parentPath); + if (parentNode is null) { + return null; + } + return parentNode.remove(id); + } + + /** + * Removes the given prefreence node if it is managed by + * this contribution manager. + * + * @param node the node to remove + * @return true if the node was removed, + * and false otherwise + */ + public bool remove(IPreferenceNode node) { + Assert.isNotNull(cast(Object)node); + + return root.remove(node); + } + + /** + * Removes all contribution nodes known to this manager. + */ + public void removeAll() { + root = new PreferenceNode("");//$NON-NLS-1$ + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/PreferenceNode.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/PreferenceNode.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,290 @@ +/******************************************************************************* + * 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.preference.PreferenceNode; + +import dwtx.jface.preference.IPreferenceNode; +import dwtx.jface.preference.IPreferencePage; + + +import tango.util.collection.ArraySeq; +// import java.util.List; + +import dwt.graphics.Image; +import dwtx.core.runtime.Assert; +import dwtx.jface.resource.ImageDescriptor; + +import dwt.dwthelper.utils; + +/** + * A concrete implementation of a node in a preference dialog tree. This class + * also supports lazy creation of the node's preference page. + */ +public class PreferenceNode : IPreferenceNode { + /** + * Preference page, or null if not yet loaded. + */ + private IPreferencePage page; + + /** + * The list of subnodes (immediate children) of this node (element type: + * IPreferenceNode). + */ + private ArraySeq!(Object) subNodes; + + /** + * Name of a class that implements IPreferencePage, or + * null if none. + */ + private String classname; + + /** + * The id of this node. + */ + private String id; + + /** + * Text label for this node. Note that this field is only used prior to the + * creation of the preference page. + */ + private String label; + + /** + * Image descriptor for this node, or null if none. + */ + private ImageDescriptor imageDescriptor; + + /** + * Cached image, or null if none. + */ + private Image image; + + /** + * Creates a new preference node with the given id. The new node has no + * subnodes. + * + * @param id + * the node id + */ + public this(String id) { + Assert.isNotNull(id); + this.id = id; + } + + /** + * Creates a preference node with the given id, label, and image, and + * lazily-loaded preference page. The preference node assumes (sole) + * responsibility for disposing of the image; this will happen when the node + * is disposed. + * + * @param id + * the node id + * @param label + * the label used to display the node in the preference dialog's + * tree + * @param image + * the image displayed left of the label in the preference + * dialog's tree, or null if none + * @param className + * the class name of the preference page; this class must + * implement IPreferencePage + */ + public this(String id, String label, ImageDescriptor image, + String className) { + this(id); + this.imageDescriptor = image; + Assert.isNotNull(label); + this.label = label; + this.classname = className; + } + + /** + * Creates a preference node with the given id and preference page. The + * title of the preference page is used for the node label. The node will + * not have an image. + * + * @param id + * the node id + * @param preferencePage + * the preference page + */ + public this(String id, IPreferencePage preferencePage) { + this(id); + Assert.isNotNull(cast(Object)preferencePage); + page = preferencePage; + } + + /* + * (non-Javadoc) Method declared on IPreferenceNode. + */ + public void add(IPreferenceNode node) { + if (subNodes is null) { + subNodes = new ArraySeq!(Object); + } + subNodes.append(cast(Object)node); + } + + /** + * Creates a new instance of the given class className. + * + * @param className + * @return new Object or null in case of failures. + */ + private Object createObject(String className) { + Assert.isNotNull(className); +// try { + ClassInfo cl = ClassInfo.find(className); + if (cl !is null) { + return cl.create(); + } +// } catch (ClassNotFoundException e) { +// return null; +// } catch (InstantiationException e) { +// return null; +// } catch (IllegalAccessException e) { +// return null; +// } catch (NoSuchMethodError e) { +// return null; +// } + return null; + } + + /* + * (non-Javadoc) Method declared on IPreferenceNode. + */ + public void createPage() { + page = cast(IPreferencePage) createObject(classname); + if (getLabelImage() !is null) { + page.setImageDescriptor(imageDescriptor); + } + page.setTitle(label); + } + + /** + * (non-Javadoc) Method declared on IPreferenceNode. + */ + public void disposeResources() { + if (image !is null) { + image.dispose(); + image = null; + } + if (page !is null) { + page.dispose(); + page = null; + } + } + + /* + * (non-Javadoc) Method declared on IContributionNode. + */ + public IPreferenceNode findSubNode(String id) { + Assert.isNotNull(id); + Assert.isTrue(id.length > 0); + if (subNodes is null) { + return null; + } + int size = subNodes.size(); + for (int i = 0; i < size; i++) { + IPreferenceNode node = cast(IPreferenceNode) subNodes.get(i); + if (id.equals(node.getId())) { + return node; + } + } + return null; + } + + /* + * (non-Javadoc) Method declared on IPreferenceNode. + */ + public String getId() { + return this.id; + } + + /** + * Returns the image descriptor for this node. + * + * @return the image descriptor + */ + protected ImageDescriptor getImageDescriptor() { + return imageDescriptor; + } + + /* + * (non-Javadoc) Method declared on IPreferenceNode. + */ + public Image getLabelImage() { + if (image is null && imageDescriptor !is null) { + image = imageDescriptor.createImage(); + } + return image; + } + + /* + * (non-Javadoc) Method declared on IPreferenceNode. + */ + public String getLabelText() { + if (page !is null) { + return page.getTitle(); + } + return label; + } + + /* + * (non-Javadoc) Method declared on IPreferenceNode. + */ + public IPreferencePage getPage() { + return page; + } + + /* + * (non-Javadoc) Method declared on IPreferenceNode. + */ + public IPreferenceNode[] getSubNodes() { + if (subNodes is null) { + return new IPreferenceNode[0]; + } + return arraycast!(IPreferenceNode)( subNodes + .toArray()); + } + + /* + * (non-Javadoc) Method declared on IPreferenceNode. + */ + public IPreferenceNode remove(String id) { + IPreferenceNode node = findSubNode(id); + if (node !is null) { + remove(node); + } + return node; + } + + /* + * (non-Javadoc) Method declared on IPreferenceNode. + */ + public bool remove(IPreferenceNode node) { + if (subNodes is null) { + return false; + } + bool res = subNodes.contains(cast(Object)node); + subNodes.remove(cast(Object)node); + return res; + } + + /** + * Set the current page to be newPage. + * + * @param newPage + */ + public void setPage(IPreferencePage newPage) { + page = newPage; + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/PreferencePage.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/PreferencePage.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,662 @@ +/******************************************************************************* + * 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 + * Sebastian Davids - Fix for bug 38729 - [Preferences] + * NPE PreferencePage isValid. + * Port to the D programming language: + * Frank Benoit + *******************************************************************************/ +module dwtx.jface.preference.PreferencePage; + +import dwtx.jface.preference.IPreferencePage; +import dwtx.jface.preference.IPreferenceStore; +import dwtx.jface.preference.IPreferencePageContainer; + +import dwt.DWT; +import dwt.events.DisposeEvent; +import dwt.events.DisposeListener; +import dwt.events.SelectionAdapter; +import dwt.events.SelectionEvent; +import dwt.graphics.Font; +import dwt.graphics.Point; +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 dwtx.jface.dialogs.Dialog; +import dwtx.jface.dialogs.DialogPage; +import dwtx.jface.dialogs.IDialogConstants; +import dwtx.jface.resource.ImageDescriptor; +import dwtx.jface.resource.JFaceResources; +import dwtx.jface.util.IPropertyChangeListener; +import dwtx.jface.util.PropertyChangeEvent; + +import dwt.dwthelper.utils; + +/** + * Abstract base implementation for all preference page implementations. + *

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

+ *

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

+ *

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

+ *

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

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

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

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

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

+     * ((GridLayout) parent.getLayout()).numColumns++);
+     * 
+ *

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

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

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

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

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

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

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

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

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

+ */ + protected void noDefaultAndApplyButton() { + createDefaultAndApplyButton = false; + } + + /** + * The PreferencePage implementation of this + * IPreferencePage method returns true + * if the page is valid. + */ + public bool okToLeave() { + return isValid(); + } + + /** + * Performs special processing when this page's Apply button has been pressed. + *

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

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

+ * This is a framework hook method for sublcasses to do special things when + * the Cancel button has been pressed. The default implementation of this + * framework method does nothing and returns true. + */ + public bool performCancel() { + return true; + } + + /** + * Performs special processing when this page's Defaults button has been pressed. + *

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

+ */ + protected void performDefaults() { + updateApplyButton(); + } + + /** + * Method declared on IPreferencePage. + * Subclasses should override + */ + public bool performOk() { + return true; + } + + /** (non-Javadoc) + * Method declared on IPreferencePage. + */ + public void setContainer(IPreferencePageContainer container) { + this.container = container; + } + + /** + * Sets the preference store for this preference page. + *

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

+ * + * @param store the preference store, or null + * @see #getPreferenceStore + */ + public void setPreferenceStore(IPreferenceStore store) { + preferenceStore = store; + } + + /* (non-Javadoc) + * Method declared on IPreferencePage. + */ + public void setSize(Point uiSize) { + Control control = getControl(); + if (control !is null) { + control.setSize(uiSize); + size = uiSize; + } + } + + /** + * The PreferencePage implementation of this IDialogPage + * method extends the DialogPage implementation to update + * the preference page container title. Subclasses may extend. + */ + public void setTitle(String title) { + super.setTitle(title); + if (getContainer() !is null) { + getContainer().updateTitle(); + } + } + + /** + * Sets whether this page is valid. + * The enable state of the container buttons and the + * apply button is updated when a page's valid state + * changes. + *

+ * + * @param b the new valid state + */ + public void setValid(bool b) { + bool oldValue = isValid_; + isValid_ = b; + if (oldValue !is isValid_) { + // update container state + if (getContainer() !is null) { + getContainer().updateButtons(); + } + // update page state + updateApplyButton(); + } + } + + /** + * Returns a string suitable for debugging purpose only. + */ + public String toString() { + return getTitle(); + } + + /** + * Updates the enabled state of the Apply button to reflect whether + * this page is valid. + */ + protected void updateApplyButton() { + if (applyButton !is null) { + applyButton.setEnabled(isValid()); + } + } + + /** + * Creates a composite with a highlighted Note entry and a message text. + * This is designed to take up the full width of the page. + * + * @param font the font to use + * @param composite the parent composite + * @param title the title of the note + * @param message the message for the note + * @return the composite for the note + */ + protected Composite createNoteComposite(Font font, Composite composite, + String title, String message) { + Composite messageComposite = new Composite(composite, DWT.NONE); + GridLayout messageLayout = new GridLayout(); + messageLayout.numColumns = 2; + messageLayout.marginWidth = 0; + messageLayout.marginHeight = 0; + messageComposite.setLayout(messageLayout); + messageComposite.setLayoutData(new GridData( + GridData.HORIZONTAL_ALIGN_FILL)); + messageComposite.setFont(font); + + final Label noteLabel = new Label(messageComposite, DWT.BOLD); + noteLabel.setText(title); + noteLabel.setFont(JFaceResources.getFontRegistry().getBold( + JFaceResources.DEFAULT_FONT)); + noteLabel + .setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING)); + + final IPropertyChangeListener fontListener = new class IPropertyChangeListener { + public void propertyChange(PropertyChangeEvent event) { + if (JFaceResources.BANNER_FONT.equals(event.getProperty())) { + noteLabel.setFont(JFaceResources + .getFont(JFaceResources.BANNER_FONT)); + } + } + }; + JFaceResources.getFontRegistry().addListener(fontListener); + noteLabel.addDisposeListener(new class DisposeListener { + public void widgetDisposed(DisposeEvent event) { + JFaceResources.getFontRegistry().removeListener(fontListener); + } + }); + + Label messageLabel = new Label(messageComposite, DWT.WRAP); + messageLabel.setText(message); + messageLabel.setFont(font); + return messageComposite; + } + + /** + * Returns the Apply button. + * + * @return the Apply button + */ + protected Button getApplyButton() { + return applyButton; + } + + /** + * Returns the Restore Defaults button. + * + * @return the Restore Defaults button + */ + protected Button getDefaultsButton() { + return defaultsButton; + } + + /* (non-Javadoc) + * @see dwtx.jface.dialogs.IDialogPage#performHelp() + */ + public void performHelp() { + getControl().notifyListeners(DWT.Help, new Event()); + } + + /** + * Apply the data to the receiver. By default do nothing. + * @param data + * @since 3.1 + */ + public void applyData(Object data) { + + } + + /* (non-Javadoc) + * @see dwtx.jface.dialogs.DialogPage#setErrorMessage(java.lang.String) + */ + public void setErrorMessage(String newMessage) { + super.setErrorMessage(newMessage); + if (getContainer() !is null) { + getContainer().updateMessage(); + } + } + + /* (non-Javadoc) + * @see dwtx.jface.dialogs.DialogPage#setMessage(java.lang.String, int) + */ + public void setMessage(String newMessage, int newType) { + super.setMessage(newMessage, newType); + if (getContainer() !is null) { + getContainer().updateMessage(); + } + } + +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/PreferenceStore.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/PreferenceStore.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,937 @@ +/******************************************************************************* + * 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.PreferenceStore; + +import dwtx.jface.preference.IPersistentPreferenceStore; +import dwtx.jface.preference.IPreferenceStore; + +// import java.io.FileInputStream; +// import java.io.FileOutputStream; +// import java.io.IOException; +// import java.io.InputStream; +// import java.io.OutputStream; +// import java.io.PrintStream; +// import java.io.PrintWriter; +// import java.util.ArrayList; +// import java.util.Enumeration; +// import java.util.Properties; +import tango.util.collection.ArraySeq; + +import dwtx.core.commands.common.EventManager; +import dwtx.core.runtime.Assert; +import dwtx.jface.resource.JFaceResources; +import dwtx.jface.util.IPropertyChangeListener; +import dwtx.jface.util.PropertyChangeEvent; +import dwtx.jface.util.SafeRunnable; + +import dwt.dwthelper.utils; +import tango.io.Print; +import tango.io.stream.FileStream; + + import tango.io.model.IConduit; + import tango.text.Util; + public class Properties { + + protected Properties defaults; + + private String[ String ] map; + + public this (){ + } + + public this ( Properties defaults ){ + this.defaults = defaults; + } + + public synchronized String setProperty( String key, String value ){ + String res; + if( auto v = key in map ){ + res = *v; + } + map[ key ] = value; + return res; + } + + public synchronized void load( InputStream inStream ){ + char[] line; + bool eof = false; + //tango.io.Stdout.Stdout.formatln( "properties put ..." ); + void readLine(){ + line.length = 0; + char[1] rdbuf; + int i = inStream.read( rdbuf ); + while( i is 1 && rdbuf[0] != '\n' && rdbuf[0] != '\r' ){ + line ~= rdbuf[0]; + i = inStream.read( rdbuf ); + } + eof = i !is 1; + } + + //tango.io.Stdout.Stdout.formatln( "properties put {}", __LINE__ ); + bool linecontinue = false; + bool iskeypart = true; + char[] key; + char[] value; + nextline: + while( !eof ){ + //tango.io.Stdout.Stdout.formatln( "properties put {} startline", __LINE__ ); + readLine(); + line = tango.text.Util.trim( line ); + if( line.length == 0 ){ + //tango.io.Stdout.Stdout.formatln( "properties put {} was 0 length", __LINE__ ); + continue; + } + if( line[0] == '#' ){ + //tango.io.Stdout.Stdout.formatln( "properties put {} was comment", __LINE__ ); + continue; + } + int pos = 0; + bool esc = false; + if( !linecontinue ){ + iskeypart = true; + key = null; + value = null; + } + else{ + linecontinue = false; + } + while( pos < line.length ){ + char c = line[pos]; + if( esc ){ + esc = false; + switch( c ){ + case 't': c = '\t'; break; + case 'n': c = '\n'; break; + case '\\': c = '\\'; break; + default: c = '?'; break; + } + } + else{ + if( c == '\\' ){ + if( pos == line.length -1 ){ + linecontinue = true; + goto nextline; + } + esc = true; + pos++; + continue; + } + else if( iskeypart && c == '=' ){ + pos++; + iskeypart = false; + continue; + } + } + pos++; + if( iskeypart ){ + key ~= c; + } + else{ + value ~= c; + } + } + if( iskeypart ){ + tango.io.Stdout.Stdout.formatln( "dejavu.util.Properties put cannot find '='." ); + continue; + } + key = tango.text.Util.trim( key ); + value = tango.text.Util.trim(value); + //tango.io.Stdout.Stdout.formatln( "properties put {}=>{}", key, value ); + + map[ key.dup ] = value.dup; + //tango.io.Stdout.Stdout.formatln( "properties put {}", __LINE__ ); + } + } + + public synchronized void store( OutputStream out_, String comments ){ + implMissing( __FILE__, __LINE__ ); + } + +// public synchronized void save( dejavu.io.OutputStream.OutputStream out_KEYWORDESCAPE, dejavu.lang.String.String comments ){ +// implMissing( __FILE__, __LINE__ ); +// } +// +// public synchronized void loadFromXML( dejavu.io.InputStream.InputStream in_KEYWORDESCAPE ){ +// implMissing( __FILE__, __LINE__ ); +// } +// +// public synchronized void storeToXML( dejavu.io.OutputStream.OutputStream os, dejavu.lang.String.String comment ){ +// implMissing( __FILE__, __LINE__ ); +// } +// +// public synchronized void storeToXML( dejavu.io.OutputStream.OutputStream os, dejavu.lang.String.String comment, dejavu.lang.String.String encoding ){ +// implMissing( __FILE__, __LINE__ ); +// } + + public String getProperty( String aKey ){ + if( auto res = aKey in map ){ + return *res; + } + if( defaults !is null ){ + return defaults.getProperty( aKey ); + } + return null; + } + + public String get( String aKey ){ + if( auto res = aKey in map ){ + return *res; + } + return null; + } + public String put( String aKey, String aValue ){ + if( auto pres = aKey in map ){ + String res = *pres; + map[ aKey ] = aValue; + return res; + } + map[ aKey ] = aValue; + return null; + } + public String remove( String aKey ){ + if( auto res = aKey in map ){ + map.remove(aKey); + return *res; + } + return null; + } + + public String getProperty( String key, String defaultValue ){ + if( auto res = key in map ){ + return *res; + } + return defaultValue; + } + + public void list(Print!(char) print){ + foreach( k, v; map ){ + print( k )( '=' )( v ).newline; + } + } + public bool containsKey( String key ){ + return ( key in map ) !is null; + } + public String[] propertyNames(){ + String[] res = new String[ map.length ]; + int idx; + foreach( key, val; map ){ + res[idx] = key; + idx++; + } + return res; + } + +// public dejavu.util.Enumeration.Enumeration propertyNames(){ +// implMissing( __FILE__, __LINE__ ); +// return null; +// } +// +// public void list( dejavu.io.PrintStream.PrintStream out_KEYWORDESCAPE ){ +// implMissing( __FILE__, __LINE__ ); +// } +// +// public void list( dejavu.io.PrintWriter.PrintWriter out_KEYWORDESCAPE ){ +// implMissing( __FILE__, __LINE__ ); +// } +// +// public override char[] toUtf8(){ +// return ""; +// } + + } + + + +/** + * A concrete preference store implementation based on an internal + * java.util.Properties object, with support for persisting the + * non-default preference values to files or streams. + *

+ * This class was not designed to be subclassed. + *

+ * + * @see IPreferenceStore + */ +public class PreferenceStore : EventManager, + IPersistentPreferenceStore { + + /** + * The mapping from preference name to preference value (represented as + * strings). + */ + private Properties properties; + + /** + * The mapping from preference name to default preference value (represented + * as strings); null if none. + */ + private Properties defaultProperties; + + /** + * Indicates whether a value as been changed by setToDefault + * or setValue; initially false. + */ + private bool dirty = false; + + /** + * The file name used by the load method to load a property + * file. This filename is used to save the properties file when + * save is called. + */ + private String filename; + + /** + * Creates an empty preference store. + *

+ * Use the methods load(InputStream) and + * save(InputStream) to load and store this preference store. + *

+ * + * @see #load(InputStream) + * @see #save(OutputStream, String) + */ + public this() { + defaultProperties = new Properties(); + properties = new Properties(defaultProperties); + } + + /** + * Creates an empty preference store that loads from and saves to the a + * file. + *

+ * Use the methods load() and save() to load + * and store this preference store. + *

+ * + * @param filename + * the file name + * @see #load() + * @see #save() + */ + public this(String filename) { + this(); + Assert.isNotNull(filename); + this.filename = filename; + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void addPropertyChangeListener(IPropertyChangeListener listener) { + addListenerObject(cast(Object)listener); + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public bool contains(String name) { + return (properties.containsKey(name) || defaultProperties + .containsKey(name)); + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void firePropertyChangeEvent(String name, Object oldValue, + Object newValue) { + final Object[] finalListeners = getListeners(); + // Do we need to fire an event. + if (finalListeners.length > 0 + && (oldValue is null || !oldValue.opEquals(newValue))) { + final PropertyChangeEvent pe = new PropertyChangeEvent(this, name, + oldValue, newValue); + for (int i = 0; i < finalListeners.length; ++i) { + SafeRunnable.run(new class(JFaceResources.getString("PreferenceStore.changeError")) SafeRunnable { //$NON-NLS-1$ + IPropertyChangeListener l; + this(char[] s){ + super(s); + l = cast(IPropertyChangeListener) finalListeners[i]; + } + public void run() { + l.propertyChange(pe); + } + }); + } + } + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public bool getBoolean(String name) { + return getBoolean(properties, name); + } + + /** + * Helper function: gets bool for a given name. + * + * @param p + * @param name + * @return bool + */ + private bool getBoolean(Properties p, String name) { + String value = p !is null ? p.getProperty(name) : null; + if (value is null) { + return BOOLEAN_DEFAULT_DEFAULT; + } + if (value.equals(IPreferenceStore.TRUE)) { + return true; + } + return false; + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public bool getDefaultBoolean(String name) { + return getBoolean(defaultProperties, name); + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public double getDefaultDouble(String name) { + return getDouble(defaultProperties, name); + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public float getDefaultFloat(String name) { + return getFloat(defaultProperties, name); + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public int getDefaultInt(String name) { + return getInt(defaultProperties, name); + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public long getDefaultLong(String name) { + return getLong(defaultProperties, name); + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public String getDefaultString(String name) { + return getString(defaultProperties, name); + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public double getDouble(String name) { + return getDouble(properties, name); + } + + /** + * Helper function: gets double for a given name. + * + * @param p + * @param name + * @return double + */ + private double getDouble(Properties p, String name) { + String value = p !is null ? p.getProperty(name) : null; + if (value is null) { + return DOUBLE_DEFAULT_DEFAULT; + } + double ival = DOUBLE_DEFAULT_DEFAULT; + try { + ival = (new Double(value)).doubleValue(); + } catch (NumberFormatException e) { + } + return ival; + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public float getFloat(String name) { + return getFloat(properties, name); + } + + /** + * Helper function: gets float for a given name. + * + * @param p + * @param name + * @return float + */ + private float getFloat(Properties p, String name) { + String value = p !is null ? p.getProperty(name) : null; + if (value is null) { + return FLOAT_DEFAULT_DEFAULT; + } + float ival = FLOAT_DEFAULT_DEFAULT; + try { + ival = (new Float(value)).floatValue(); + } catch (NumberFormatException e) { + } + return ival; + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public int getInt(String name) { + return getInt(properties, name); + } + + /** + * Helper function: gets int for a given name. + * + * @param p + * @param name + * @return int + */ + private int getInt(Properties p, String name) { + String value = p !is null ? p.getProperty(name) : null; + if (value is null) { + return INT_DEFAULT_DEFAULT; + } + int ival = 0; + try { + ival = Integer.parseInt(value); + } catch (NumberFormatException e) { + } + return ival; + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public long getLong(String name) { + return getLong(properties, name); + } + + /** + * Helper function: gets long for a given name. + * + * @param p + * the properties storage (may be null) + * @param name + * the name of the property + * @return the long or a default value of if: + *
    + *
  • properties storage is null
  • + *
  • property is not found
  • + *
  • property value is not a number
  • + *
+ * @see IPreferenceStore#LONG_DEFAULT_DEFAULT + */ + private long getLong(Properties p, String name) { + String value = p !is null ? p.getProperty(name) : null; + if (value is null) { + return LONG_DEFAULT_DEFAULT; + } + long ival = LONG_DEFAULT_DEFAULT; + try { + ival = Long.parseLong(value); + } catch (NumberFormatException e) { + } + return ival; + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public String getString(String name) { + return getString(properties, name); + } + + /** + * Helper function: gets string for a given name. + * + * @param p + * the properties storage (may be null) + * @param name + * the name of the property + * @return the value or a default value of if: + *
    + *
  • properties storage is null
  • + *
  • property is not found
  • + *
  • property value is not a number
  • + *
+ * @see IPreferenceStore#STRING_DEFAULT_DEFAULT + */ + private String getString(Properties p, String name) { + String value = p !is null ? p.getProperty(name) : null; + if (value is null) { + return STRING_DEFAULT_DEFAULT; + } + return value; + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public bool isDefault(String name) { + return (!properties.containsKey(name) && defaultProperties + .containsKey(name)); + } + + /** + * Prints the contents of this preference store to the given print stream. + * + * @param out + * the print stream + */ + public void list(Print!(char) out_) { + properties.list(out_); + } + +// /** +// * Prints the contents of this preference store to the given print writer. +// * +// * @param out +// * the print writer +// */ +// public void list(PrintWriter out_) { +// properties.list(out_); +// } + + /** + * Loads this preference store from the file established in the constructor + * PreferenceStore(java.lang.String) (or by + * setFileName). Default preference values are not affected. + * + * @exception java.io.IOException + * if there is a problem loading this store + */ + public void load() { + if (filename is null) { + throw new IOException("File name not specified");//$NON-NLS-1$ + } + FileInput in_ = new FileInput(filename); + load(in_.input); + in_.close(); + } + + /** + * Loads this preference store from the given input stream. Default + * preference values are not affected. + * + * @param in + * the input stream + * @exception java.io.IOException + * if there is a problem loading this store + */ + public void load(InputStream in_) { + properties.load(in_); + dirty = false; + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public bool needsSaving() { + return dirty; + } + + /** + * Returns an enumeration of all preferences known to this store which have + * current values other than their default value. + * + * @return an array of preference names + */ + public String[] preferenceNames() { + String[] list; + foreach( prop; properties.propertyNames() ){ + list ~= prop; + } + return list; + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void putValue(String name, String value) { + String oldValue = getString(name); + if (oldValue is null || !oldValue.equals(value)) { + setValue(properties, name, value); + dirty = true; + } + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void removePropertyChangeListener(IPropertyChangeListener listener) { + removeListenerObject(cast(Object)listener); + } + + /** + * Saves the non-default-valued preferences known to this preference store + * to the file from which they were originally loaded. + * + * @exception java.io.IOException + * if there is a problem saving this store + */ + public void save() { + if (filename is null) { + throw new IOException("File name not specified");//$NON-NLS-1$ + } + FileOutput out_ = null; + try { + out_ = new FileOutput(filename); + save(out_, null); + } finally { + if (out_ !is null) { + out_.close(); + } + } + } + + /** + * Saves this preference store to the given output stream. The given string + * is inserted as header information. + * + * @param out + * the output stream + * @param header + * the header + * @exception java.io.IOException + * if there is a problem saving this store + */ + public void save(OutputStream out_, String header) { + properties.store(out_, header); + dirty = false; + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void setDefault(String name, double value) { + setValue(defaultProperties, name, value); + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void setDefault(String name, float value) { + setValue(defaultProperties, name, value); + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void setDefault(String name, int value) { + setValue(defaultProperties, name, value); + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void setDefault(String name, long value) { + setValue(defaultProperties, name, value); + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void setDefault(String name, String value) { + setValue(defaultProperties, name, value); + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void setDefault(String name, bool value) { + setValue(defaultProperties, name, value); + } + + /** + * Sets the name of the file used when loading and storing this preference + * store. + *

+ * Afterward, the methods load() and save() + * can be used to load and store this preference store. + *

+ * + * @param name + * the file name + * @see #load() + * @see #save() + */ + public void setFilename(String name) { + filename = name; + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void setToDefault(String name) { + String oldValue = properties.get(name); + properties.remove(name); + dirty = true; + String newValue; + if (defaultProperties !is null) { + newValue = defaultProperties.get(name); + } + firePropertyChangeEvent(name, stringcast(oldValue), stringcast(newValue)); + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void setValue(String name, double value) { + double oldValue = getDouble(name); + if (oldValue !is value) { + setValue(properties, name, value); + dirty = true; + firePropertyChangeEvent(name, new Double(oldValue), new Double( + value)); + } + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void setValue(String name, float value) { + float oldValue = getFloat(name); + if (oldValue !is value) { + setValue(properties, name, value); + dirty = true; + firePropertyChangeEvent(name, new Float(oldValue), new Float(value)); + } + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void setValue(String name, int value) { + int oldValue = getInt(name); + if (oldValue !is value) { + setValue(properties, name, value); + dirty = true; + firePropertyChangeEvent(name, new Integer(oldValue), new Integer( + value)); + } + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void setValue(String name, long value) { + long oldValue = getLong(name); + if (oldValue !is value) { + setValue(properties, name, value); + dirty = true; + firePropertyChangeEvent(name, new Long(oldValue), new Long(value)); + } + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void setValue(String name, String value) { + String oldValue = getString(name); + if (oldValue is null || !oldValue.equals(value)) { + setValue(properties, name, value); + dirty = true; + firePropertyChangeEvent(name, stringcast(oldValue), stringcast(value)); + } + } + + /* + * (non-Javadoc) Method declared on IPreferenceStore. + */ + public void setValue(String name, bool value) { + bool oldValue = getBoolean(name); + if (oldValue !is value) { + setValue(properties, name, value); + dirty = true; + firePropertyChangeEvent(name, oldValue ? Boolean.TRUE + : Boolean.FALSE, value ? Boolean.TRUE : Boolean.FALSE); + } + } + + /** + * Helper method: sets value for a given name. + * + * @param p + * @param name + * @param value + */ + private void setValue(Properties p, String name, double value) { + Assert.isTrue(p !is null); + p.put(name, Double.toString(value)); + } + + /** + * Helper method: sets value for a given name. + * + * @param p + * @param name + * @param value + */ + private void setValue(Properties p, String name, float value) { + Assert.isTrue(p !is null); + p.put(name, Float.toString(value)); + } + + /** + * Helper method: sets value for a given name. + * + * @param p + * @param name + * @param value + */ + private void setValue(Properties p, String name, int value) { + Assert.isTrue(p !is null); + p.put(name, Integer.toString(value)); + } + + /** + * Helper method: sets the value for a given name. + * + * @param p + * @param name + * @param value + */ + private void setValue(Properties p, String name, long value) { + Assert.isTrue(p !is null); + p.put(name, Long.toString(value)); + } + + /** + * Helper method: sets the value for a given name. + * + * @param p + * @param name + * @param value + */ + private void setValue(Properties p, String name, String value) { + Assert.isTrue(p !is null && value !is null); + p.put(name, value); + } + + /** + * Helper method: sets the value for a given name. + * + * @param p + * @param name + * @param value + */ + private void setValue(Properties p, String name, bool value) { + Assert.isTrue(p !is null); + p.put(name, value is true ? IPreferenceStore.TRUE + : IPreferenceStore.FALSE); + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/RadioGroupFieldEditor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/RadioGroupFieldEditor.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,355 @@ +/******************************************************************************* + * 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.RadioGroupFieldEditor; + +import dwtx.jface.preference.FieldEditor; + +import dwt.DWT; +import dwt.events.DisposeEvent; +import dwt.events.DisposeListener; +import dwt.events.SelectionAdapter; +import dwt.events.SelectionEvent; +import dwt.graphics.Font; +import dwt.layout.GridData; +import dwt.layout.GridLayout; +import dwt.widgets.Button; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Group; +import dwtx.core.runtime.Assert; + +import dwt.dwthelper.utils; + +/** + * A field editor for an enumeration type preference. + * The choices are presented as a list of radio buttons. + */ +public class RadioGroupFieldEditor : FieldEditor { + + /** + * List of radio button entries of the form [label,value]. + */ + private String[][] labelsAndValues; + + /** + * Number of columns into which to arrange the radio buttons. + */ + private int numColumns; + + /** + * Indent used for the first column of the radion button matrix. + */ + private int indent = HORIZONTAL_GAP; + + /** + * The current value, or null if none. + */ + private String value; + + /** + * The box of radio buttons, or null if none + * (before creation and after disposal). + */ + private Composite radioBox; + + /** + * The radio buttons, or null if none + * (before creation and after disposal). + */ + private Button[] radioButtons; + + /** + * Whether to use a Group control. + */ + private bool useGroup; + + /** + * Creates a new radio group field editor + */ + protected this() { + } + + /** + * Creates a radio group field editor. + * This constructor does not use a Group to contain the radio buttons. + * It is equivalent to using the following constructor with false + * for the useGroup argument. + *

+ * Example usage: + *

+     *      RadioGroupFieldEditor editor= new RadioGroupFieldEditor(
+     *          "GeneralPage.DoubleClick", resName, 1,
+     *          new String[][] {
+     *              {"Open Browser", "open"},
+     *              {"Expand Tree", "expand"}
+     *          },
+     *          parent);
+     * 
+ *

+ * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param numColumns the number of columns for the radio button presentation + * @param labelAndValues list of radio button [label, value] entries; + * the value is returned when the radio button is selected + * @param parent the parent of the field editor's control + */ + public this(String name, String labelText, int numColumns, + String[][] labelAndValues, Composite parent) { + this(name, labelText, numColumns, labelAndValues, parent, false); + } + + /** + * Creates a radio group field editor. + *

+ * Example usage: + *

+     *      RadioGroupFieldEditor editor= new RadioGroupFieldEditor(
+     *          "GeneralPage.DoubleClick", resName, 1,
+     *          new String[][] {
+     *              {"Open Browser", "open"},
+     *              {"Expand Tree", "expand"}
+     *          },
+     *          parent,
+     *          true);
+     * 
+ *

+ * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param numColumns the number of columns for the radio button presentation + * @param labelAndValues list of radio button [label, value] entries; + * the value is returned when the radio button is selected + * @param parent the parent of the field editor's control + * @param useGroup whether to use a Group control to contain the radio buttons + */ + public this(String name, String labelText, int numColumns, + String[][] labelAndValues, Composite parent, bool useGroup) { + init(name, labelText); + Assert.isTrue(checkArray(labelAndValues)); + this.labelsAndValues = labelAndValues; + this.numColumns = numColumns; + this.useGroup = useGroup; + createControl(parent); + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void adjustForNumColumns(int numColumns) { + Control control = getLabelControl(); + if (control !is null) { + (cast(GridData) control.getLayoutData()).horizontalSpan = numColumns; + } + (cast(GridData) radioBox.getLayoutData()).horizontalSpan = numColumns; + } + + /** + * Checks whether given String[][] is of "type" + * String[][2]. + * @param table + * + * @return true if it is ok, and false otherwise + */ + private bool checkArray(String[][] table) { + if (table is null) { + return false; + } + for (int i = 0; i < table.length; i++) { + String[] array = table[i]; + if (array is null || array.length !is 2) { + return false; + } + } + return true; + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doFillIntoGrid(Composite parent, int numColumns) { + if (useGroup) { + Control control = getRadioBoxControl(parent); + GridData gd = new GridData(GridData.FILL_HORIZONTAL); + control.setLayoutData(gd); + } else { + Control control = getLabelControl(parent); + GridData gd = new GridData(); + gd.horizontalSpan = numColumns; + control.setLayoutData(gd); + control = getRadioBoxControl(parent); + gd = new GridData(); + gd.horizontalSpan = numColumns; + gd.horizontalIndent = indent; + control.setLayoutData(gd); + } + + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doLoad() { + updateValue(getPreferenceStore().getString(getPreferenceName())); + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doLoadDefault() { + updateValue(getPreferenceStore().getDefaultString(getPreferenceName())); + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doStore() { + if (value is null) { + getPreferenceStore().setToDefault(getPreferenceName()); + return; + } + + getPreferenceStore().setValue(getPreferenceName(), value); + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + public int getNumberOfControls() { + return 1; + } + + /** + * Returns this field editor's radio group control. + * @param parent The parent to create the radioBox in + * @return the radio group control + */ + public Composite getRadioBoxControl(Composite parent) { + if (radioBox is null) { + + Font font = parent.getFont(); + + if (useGroup) { + Group group = new Group(parent, DWT.NONE); + group.setFont(font); + String text = getLabelText(); + if (text !is null) { + group.setText(text); + } + radioBox = group; + GridLayout layout = new GridLayout(); + layout.horizontalSpacing = HORIZONTAL_GAP; + layout.numColumns = numColumns; + radioBox.setLayout(layout); + } else { + radioBox = new Composite(parent, DWT.NONE); + GridLayout layout = new GridLayout(); + layout.marginWidth = 0; + layout.marginHeight = 0; + layout.horizontalSpacing = HORIZONTAL_GAP; + layout.numColumns = numColumns; + radioBox.setLayout(layout); + radioBox.setFont(font); + } + + radioButtons = new Button[labelsAndValues.length]; + for (int i = 0; i < labelsAndValues.length; i++) { + Button radio = new Button(radioBox, DWT.RADIO | DWT.LEFT); + radioButtons[i] = radio; + String[] labelAndValue = labelsAndValues[i]; + radio.setText(labelAndValue[0]); + radio.setData(stringcast(labelAndValue[1])); + radio.setFont(font); + radio.addSelectionListener(new class SelectionAdapter { + public void widgetSelected(SelectionEvent event) { + String oldValue = value; + value = stringcast( event.widget.getData() ); + setPresentsDefaultValue(false); + fireValueChanged(VALUE, stringcast(oldValue), stringcast(value)); + } + }); + } + radioBox.addDisposeListener(new class DisposeListener { + public void widgetDisposed(DisposeEvent event) { + radioBox = null; + radioButtons = null; + } + }); + } else { + checkParent(radioBox, parent); + } + return radioBox; + } + + /** + * Sets the indent used for the first column of the radion button matrix. + * + * @param indent the indent (in pixels) + */ + public void setIndent(int indent) { + if (indent < 0) { + this.indent = 0; + } else { + this.indent = indent; + } + } + + /** + * Select the radio button that conforms to the given value. + * + * @param selectedValue the selected value + */ + private void updateValue(String selectedValue) { + this.value = selectedValue; + if (radioButtons is null) { + return; + } + + if (this.value !is null) { + bool found = false; + for (int i = 0; i < radioButtons.length; i++) { + Button radio = radioButtons[i]; + bool selection = false; + if (stringcast( radio.getData()).equals(this.value)) { + selection = true; + found = true; + } + radio.setSelection(selection); + } + if (found) { + return; + } + } + + // We weren't able to find the value. So we select the first + // radio button as a default. + if (radioButtons.length > 0) { + radioButtons[0].setSelection(true); + this.value = stringcast( radioButtons[0].getData()); + } + return; + } + + /* + * @see FieldEditor.setEnabled(bool,Composite). + */ + public void setEnabled(bool enabled, Composite parent) { + if (!useGroup) { + super.setEnabled(enabled, parent); + } + for (int i = 0; i < radioButtons.length; i++) { + radioButtons[i].setEnabled(enabled); + } + + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/ScaleFieldEditor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/ScaleFieldEditor.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,386 @@ +/******************************************************************************* + * 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.preference.ScaleFieldEditor; + +import dwtx.jface.preference.FieldEditor; + +import dwt.DWT; +import dwt.events.DisposeEvent; +import dwt.events.DisposeListener; +import dwt.events.SelectionAdapter; +import dwt.events.SelectionEvent; +import dwt.layout.GridData; +import dwt.widgets.Composite; +import dwt.widgets.Control; +import dwt.widgets.Scale; + +import dwt.dwthelper.utils; + +/** + * A field editor for an integer type preference. This class may be used as is, + * or subclassed as required. + * + * @since 3.0 + */ +public class ScaleFieldEditor : FieldEditor { + + /** + * Value that will feed Scale.setIncrement(int). + */ + private int incrementValue; + + /** + * Value that will feed Scale.setMaximum(int). + */ + private int maxValue; + + /** + * Value that will feed Scale.setMinimum(int). + */ + private int minValue; + + /** + * Old integer value. + */ + private int oldValue; + + /** + * Value that will feed Scale.setPageIncrement(int). + */ + private int pageIncrementValue; + + /** + * The scale, or null if none. + */ + protected Scale scale; + + /** + * Creates a scale field editor. + * + * @param name + * the name of the preference this field editor works on + * @param labelText + * the label text of the field editor + * @param parent + * the parent of the field editor's control + */ + public this(String name, String labelText, Composite parent) { + super(name, labelText, parent); + setDefaultValues(); + } + + /** + * Creates a scale field editor with particular scale values. + * + * @param name + * the name of the preference this field editor works on + * @param labelText + * the label text of the field editor + * @param parent + * the parent of the field editor's control + * @param min + * the value used for Scale.setMinimum(int). + * @param max + * the value used for Scale.setMaximum(int). + * @param increment + * the value used for Scale.setIncrement(int). + * @param pageIncrement + * the value used for Scale.setPageIncrement(int). + */ + public this(String name, String labelText, Composite parent, + int min, int max, int increment, int pageIncrement) { + super(name, labelText, parent); + setValues(min, max, increment, pageIncrement); + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.preference.FieldEditor#adjustForNumColumns(int) + */ + protected void adjustForNumColumns(int numColumns) { + (cast(GridData) scale.getLayoutData()).horizontalSpan = numColumns - 1; + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.preference.FieldEditor#doFillIntoGrid(dwt.widgets.Composite, + * int) + */ + protected void doFillIntoGrid(Composite parent, int numColumns) { + Control control = getLabelControl(parent); + GridData gd = new GridData(); + control.setLayoutData(gd); + + scale = getScaleControl(parent); + gd = new GridData(GridData.FILL_HORIZONTAL); + gd.verticalAlignment = GridData.FILL; + gd.horizontalSpan = numColumns - 1; + gd.grabExcessHorizontalSpace = true; + scale.setLayoutData(gd); + updateScale(); + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.preference.FieldEditor#doLoad() + */ + protected void doLoad() { + if (scale !is null) { + int value = getPreferenceStore().getInt(getPreferenceName()); + scale.setSelection(value); + oldValue = value; + } + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.preference.FieldEditor#doLoadDefault() + */ + protected void doLoadDefault() { + if (scale !is null) { + int value = getPreferenceStore().getDefaultInt(getPreferenceName()); + scale.setSelection(value); + } + valueChanged(); + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.preference.FieldEditor#doStore() + */ + protected void doStore() { + getPreferenceStore() + .setValue(getPreferenceName(), scale.getSelection()); + } + + /** + * Returns the value that will be used for Scale.setIncrement(int). + * + * @return the value. + * @see dwt.widgets.Scale#setIncrement(int) + */ + public int getIncrement() { + return incrementValue; + } + + /** + * Returns the value that will be used for Scale.setMaximum(int). + * + * @return the value. + * @see dwt.widgets.Scale#setMaximum(int) + */ + public int getMaximum() { + return maxValue; + } + + /** + * Returns the value that will be used for Scale.setMinimum(int). + * + * @return the value. + * @see dwt.widgets.Scale#setMinimum(int) + */ + public int getMinimum() { + return minValue; + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.preference.FieldEditor#getNumberOfControls() + */ + public int getNumberOfControls() { + return 2; + } + + /** + * Returns the value that will be used for Scale.setPageIncrement(int). + * + * @return the value. + * @see dwt.widgets.Scale#setPageIncrement(int) + */ + public int getPageIncrement() { + return pageIncrementValue; + } + + /** + * Returns this field editor's scale control. + * + * @return the scale control, or null if no scale field is + * created yet + */ + public Scale getScaleControl() { + return scale; + } + + /** + * Returns this field editor's scale control. The control is created if it + * does not yet exist. + * + * @param parent + * the parent + * @return the scale control + */ + private Scale getScaleControl(Composite parent) { + if (scale is null) { + scale = new Scale(parent, DWT.HORIZONTAL); + scale.setFont(parent.getFont()); + scale.addSelectionListener(new class SelectionAdapter { + public void widgetSelected(SelectionEvent event) { + valueChanged(); + } + }); + scale.addDisposeListener(new class DisposeListener { + public void widgetDisposed(DisposeEvent event) { + scale = null; + } + }); + } else { + checkParent(scale, parent); + } + return scale; + } + + /** + * Set default values for the various scale fields. These defaults are:
+ *
    + *
  • Minimum = 0 + *
  • Maximim = 10 + *
  • Increment = 1 + *
  • Page Increment = 1 + *
+ */ + private void setDefaultValues() { + setValues(0, 10, 1, 1); + } + + /* + * (non-Javadoc) + * + * @see dwtx.jface.preference.FieldEditor#setFocus() + */ + public void setFocus() { + if (scale !is null && !scale.isDisposed()) { + scale.setFocus(); + } + } + + /** + * Set the value to be used for Scale.setIncrement(int) and update the + * scale. + * + * @param increment + * a value greater than 0. + * @see dwt.widgets.Scale#setIncrement(int) + */ + public void setIncrement(int increment) { + this.incrementValue = increment; + updateScale(); + } + + /** + * Set the value to be used for Scale.setMaximum(int) and update the + * scale. + * + * @param max + * a value greater than 0. + * @see dwt.widgets.Scale#setMaximum(int) + */ + public void setMaximum(int max) { + this.maxValue = max; + updateScale(); + } + + /** + * Set the value to be used for Scale.setMinumum(int) and update the + * scale. + * + * @param min + * a value greater than 0. + * @see dwt.widgets.Scale#setMinimum(int) + */ + public void setMinimum(int min) { + this.minValue = min; + updateScale(); + } + + /** + * Set the value to be used for Scale.setPageIncrement(int) and update the + * scale. + * + * @param pageIncrement + * a value greater than 0. + * @see dwt.widgets.Scale#setPageIncrement(int) + */ + public void setPageIncrement(int pageIncrement) { + this.pageIncrementValue = pageIncrement; + updateScale(); + } + + /** + * Set all Scale values. + * + * @param min + * the value used for Scale.setMinimum(int). + * @param max + * the value used for Scale.setMaximum(int). + * @param increment + * the value used for Scale.setIncrement(int). + * @param pageIncrement + * the value used for Scale.setPageIncrement(int). + */ + private void setValues(int min, int max, int increment, int pageIncrement) { + this.incrementValue = increment; + this.maxValue = max; + this.minValue = min; + this.pageIncrementValue = pageIncrement; + updateScale(); + } + + /** + * Update the scale particulars with set values. + */ + private void updateScale() { + if (scale !is null && !scale.isDisposed()) { + scale.setMinimum(getMinimum()); + scale.setMaximum(getMaximum()); + scale.setIncrement(getIncrement()); + scale.setPageIncrement(getPageIncrement()); + } + } + + /** + * Informs this field editor's listener, if it has one, about a change to + * the value (VALUE property) provided that the old and new + * values are different. + *

+ * This hook is not called when the scale is initialized (or + * reset to the default value) from the preference store. + *

+ */ + protected void valueChanged() { + setPresentsDefaultValue(false); + + int newValue = scale.getSelection(); + if (newValue !is oldValue) { + fireStateChanged(IS_VALID, false, true); + fireValueChanged(VALUE, new ValueWrapperInt(oldValue), + new ValueWrapperInt(newValue)); + oldValue = newValue; + } + } +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/StringButtonFieldEditor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/StringButtonFieldEditor.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,185 @@ +/******************************************************************************* + * 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 + * Thierry Lach - thierry.lach@bbdodetroit.com - Fix for Bug 37155 + * Port to the D programming language: + * Frank Benoit + *******************************************************************************/ +module dwtx.jface.preference.StringButtonFieldEditor; + +import dwtx.jface.preference.StringFieldEditor; + +import dwt.DWT; +import dwt.events.DisposeEvent; +import dwt.events.DisposeListener; +import dwt.events.SelectionAdapter; +import dwt.events.SelectionEvent; +import dwt.graphics.Point; +import dwt.layout.GridData; +import dwt.widgets.Button; +import dwt.widgets.Composite; +import dwt.widgets.Shell; +import dwtx.core.runtime.Assert; +import dwtx.jface.dialogs.IDialogConstants; +import dwtx.jface.resource.JFaceResources; + +import dwt.dwthelper.utils; + +/** + * An abstract field editor for a string type preference that presents + * a string input field with a change button to its right to edit the + * input field's content. When the user presses the change button, the + * abstract framework method changePressed() gets called + * to compute a new string. + */ +public abstract class StringButtonFieldEditor : StringFieldEditor { + + /** + * The change button, or null if none + * (before creation and after disposal). + */ + private Button changeButton; + + /** + * The text for the change button, or null if missing. + */ + private String changeButtonText; + + /** + * Creates a new string button field editor + */ + protected this() { + } + + /** + * Creates a string button field editor. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param parent the parent of the field editor's control + */ + protected this(String name, String labelText, + Composite parent) { + init(name, labelText); + createControl(parent); + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void adjustForNumColumns(int numColumns) { + (cast(GridData) getTextControl().getLayoutData()).horizontalSpan = numColumns - 2; + } + + /** + * Notifies that this field editor's change button has been pressed. + *

+ * Subclasses must implement this method to provide a corresponding + * new string for the text field. If the returned value is null, + * the currently displayed value remains. + *

+ * + * @return the new string to display, or null to leave the + * old string showing + */ + protected abstract String changePressed(); + + /* (non-Javadoc) + * Method declared on StringFieldEditor (and FieldEditor). + */ + protected void doFillIntoGrid(Composite parent, int numColumns) { + super.doFillIntoGrid(parent, numColumns - 1); + changeButton = getChangeControl(parent); + GridData gd = new GridData(); + gd.horizontalAlignment = GridData.FILL; + int widthHint = convertHorizontalDLUsToPixels(changeButton, + IDialogConstants.BUTTON_WIDTH); + gd.widthHint = Math.max(widthHint, changeButton.computeSize( + DWT.DEFAULT, DWT.DEFAULT, true).x); + changeButton.setLayoutData(gd); + } + + /** + * Get the change control. Create it in parent if required. + * @param parent + * @return Button + */ + protected Button getChangeControl(Composite parent) { + if (changeButton is null) { + changeButton = new Button(parent, DWT.PUSH); + if (changeButtonText is null) { + changeButtonText = JFaceResources.getString("openChange"); //$NON-NLS-1$ + } + changeButton.setText(changeButtonText); + changeButton.setFont(parent.getFont()); + changeButton.addSelectionListener(new class SelectionAdapter { + public void widgetSelected(SelectionEvent evt) { + String newValue = changePressed(); + if (newValue !is null) { + setStringValue(newValue); + } + } + }); + changeButton.addDisposeListener(new class DisposeListener { + public void widgetDisposed(DisposeEvent event) { + changeButton = null; + } + }); + } else { + checkParent(changeButton, parent); + } + return changeButton; + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + public int getNumberOfControls() { + return 3; + } + + /** + * Returns this field editor's shell. + * + * @return the shell + */ + protected Shell getShell() { + if (changeButton is null) { + return null; + } + return changeButton.getShell(); + } + + /** + * Sets the text of the change button. + * + * @param text the new text + */ + public void setChangeButtonText(String text) { + Assert.isNotNull(text); + changeButtonText = text; + if (changeButton !is null) { + changeButton.setText(text); + Point prefSize = changeButton.computeSize(DWT.DEFAULT, DWT.DEFAULT); + GridData data = cast(GridData)changeButton.getLayoutData(); + data.widthHint = Math.max(DWT.DEFAULT, prefSize.x); + } + } + + /* (non-Javadoc) + * @see dwtx.jface.preference.FieldEditor#setEnabled(bool, dwt.widgets.Composite) + */ + public void setEnabled(bool enabled, Composite parent) { + super.setEnabled(enabled, parent); + if (changeButton !is null) { + changeButton.setEnabled(enabled); + } + } + +} diff -r f25582573129 -r b3c8e32d406f dwtx/jface/preference/StringFieldEditor.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dwtx/jface/preference/StringFieldEditor.d Sat Apr 05 01:45:47 2008 +0200 @@ -0,0 +1,532 @@ +/******************************************************************************* + * 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.StringFieldEditor; + +import dwtx.jface.preference.FieldEditor; + +import dwt.DWT; +import dwt.events.DisposeEvent; +import dwt.events.DisposeListener; +import dwt.events.FocusAdapter; +import dwt.events.FocusEvent; +import dwt.events.KeyAdapter; +import dwt.events.KeyEvent; +import dwt.graphics.GC; +import dwt.graphics.Point; +import dwt.layout.GridData; +import dwt.widgets.Composite; +import dwt.widgets.Text; +import dwtx.core.runtime.Assert; +import dwtx.jface.resource.JFaceResources; + +import dwt.dwthelper.utils; + +/** + * A field editor for a string type preference. + *

+ * This class may be used as is, or subclassed as required. + *

+ */ +public class StringFieldEditor : FieldEditor { + + alias FieldEditor.showErrorMessage showErrorMessage; + /** + * Validation strategy constant (value 0) indicating that + * the editor should perform validation after every key stroke. + * + * @see #setValidateStrategy + */ + public static const int VALIDATE_ON_KEY_STROKE = 0; + + /** + * Validation strategy constant (value 1) indicating that + * the editor should perform validation only when the text widget + * loses focus. + * + * @see #setValidateStrategy + */ + public static const int VALIDATE_ON_FOCUS_LOST = 1; + + /** + * Text limit constant (value -1) indicating unlimited + * text limit and width. + */ + public static int UNLIMITED = -1; + + /** + * Cached valid state. + */ + private bool isValid_; + + /** + * Old text value. + */ + private String oldValue; + + /** + * The text field, or null if none. + */ + Text textField; + + /** + * Width of text field in characters; initially unlimited. + */ + private int widthInChars; + + /** + * Text limit of text field in characters; initially unlimited. + */ + private int textLimit; + + /** + * The error message, or null if none. + */ + private String errorMessage; + + /** + * Indicates whether the empty string is legal; + * true by default. + */ + private bool emptyStringAllowed = true; + + /** + * The validation strategy; + * VALIDATE_ON_KEY_STROKE by default. + */ + private int validateStrategy; + + /** + * Creates a new string field editor + */ + protected this() { + widthInChars = UNLIMITED; + textLimit = UNLIMITED; + validateStrategy = VALIDATE_ON_KEY_STROKE; + } + + /** + * Creates a string field editor. + * Use the method setTextLimit to limit the text. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param width the width of the text input field in characters, + * or UNLIMITED for no limit + * @param strategy either VALIDATE_ON_KEY_STROKE to perform + * on the fly checking (the default), or VALIDATE_ON_FOCUS_LOST to + * perform validation only after the text has been typed in + * @param parent the parent of the field editor's control + * @since 2.0 + */ + public this(String name, String labelText, int width, + int strategy, Composite parent) { + this(); + init(name, labelText); + widthInChars = width; + setValidateStrategy(strategy); + isValid_ = false; + errorMessage = JFaceResources + .getString("StringFieldEditor.errorMessage");//$NON-NLS-1$ + createControl(parent); + } + + /** + * Creates a string field editor. + * Use the method setTextLimit to limit the text. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param width the width of the text input field in characters, + * or UNLIMITED for no limit + * @param parent the parent of the field editor's control + */ + public this(String name, String labelText, int width, + Composite parent) { + this(name, labelText, width, VALIDATE_ON_KEY_STROKE, parent); + } + + /** + * Creates a string field editor of unlimited width. + * Use the method setTextLimit to limit the text. + * + * @param name the name of the preference this field editor works on + * @param labelText the label text of the field editor + * @param parent the parent of the field editor's control + */ + public this(String name, String labelText, Composite parent) { + this(name, labelText, UNLIMITED, parent); + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void adjustForNumColumns(int numColumns) { + GridData gd = cast(GridData) textField.getLayoutData(); + gd.horizontalSpan = numColumns - 1; + // We only grab excess space if we have to + // If another field editor has more columns then + // we assume it is setting the width. + gd.grabExcessHorizontalSpace = gd.horizontalSpan is 1; + } + + /** + * Checks whether the text input field contains a valid value or not. + * + * @return true if the field value is valid, + * and false if invalid + */ + protected bool checkState() { + bool result = false; + if (emptyStringAllowed) { + result = true; + } + + if (textField is null) { + result = false; + } + + String txt = textField.getText(); + + result = (txt.trim().length > 0) || emptyStringAllowed; + + // call hook for subclasses + result = result && doCheckState(); + + if (result) { + clearErrorMessage(); + } else { + showErrorMessage(errorMessage); + } + + return result; + } + + /** + * Hook for subclasses to do specific state checks. + *

+ * The default implementation of this framework method does + * nothing and returns true. Subclasses should + * override this method to specific state checks. + *

+ * + * @return true if the field value is valid, + * and false if invalid + */ + protected bool doCheckState() { + return true; + } + + /** + * Fills this field editor's basic controls into the given parent. + *

+ * The string field implementation of this FieldEditor + * framework method contributes the text field. Subclasses may override + * but must call super.doFillIntoGrid. + *

+ */ + protected void doFillIntoGrid(Composite parent, int numColumns) { + getLabelControl(parent); + + textField = getTextControl(parent); + GridData gd = new GridData(); + gd.horizontalSpan = numColumns - 1; + if (widthInChars !is UNLIMITED) { + GC gc = new GC(textField); + try { + Point extent = gc.textExtent("X");//$NON-NLS-1$ + gd.widthHint = widthInChars * extent.x; + } finally { + gc.dispose(); + } + } else { + gd.horizontalAlignment = GridData.FILL; + gd.grabExcessHorizontalSpace = true; + } + textField.setLayoutData(gd); + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doLoad() { + if (textField !is null) { + String value = getPreferenceStore().getString(getPreferenceName()); + textField.setText(value); + oldValue = value; + } + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doLoadDefault() { + if (textField !is null) { + String value = getPreferenceStore().getDefaultString( + getPreferenceName()); + textField.setText(value); + } + valueChanged(); + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void doStore() { + getPreferenceStore().setValue(getPreferenceName(), textField.getText()); + } + + /** + * Returns the error message that will be displayed when and if + * an error occurs. + * + * @return the error message, or null if none + */ + public String getErrorMessage() { + return errorMessage; + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + public int getNumberOfControls() { + return 2; + } + + /** + * Returns the field editor's value. + * + * @return the current value + */ + public String getStringValue() { + if (textField !is null) { + return textField.getText(); + } + + return getPreferenceStore().getString(getPreferenceName()); + } + + /** + * Returns this field editor's text control. + * + * @return the text control, or null if no + * text field is created yet + */ + protected Text getTextControl() { + return textField; + } + + /** + * Returns this field editor's text control. + *

+ * The control is created if it does not yet exist + *

+ * + * @param parent the parent + * @return the text control + */ + public Text getTextControl(Composite parent) { + if (textField is null) { + textField = new Text(parent, DWT.SINGLE | DWT.BORDER); + textField.setFont(parent.getFont()); + switch (validateStrategy) { + case VALIDATE_ON_KEY_STROKE: + textField.addKeyListener(new class KeyAdapter { + + /* (non-Javadoc) + * @see dwt.events.KeyAdapter#keyReleased(dwt.events.KeyEvent) + */ + public void keyReleased(KeyEvent e) { + valueChanged(); + } + }); + + break; + case VALIDATE_ON_FOCUS_LOST: + textField.addKeyListener(new class KeyAdapter { + public void keyPressed(KeyEvent e) { + clearErrorMessage(); + } + }); + textField.addFocusListener(new class FocusAdapter { + public void focusGained(FocusEvent e) { + refreshValidState(); + } + + public void focusLost(FocusEvent e) { + valueChanged(); + clearErrorMessage(); + } + }); + break; + default: + Assert.isTrue(false, "Unknown validate strategy");//$NON-NLS-1$ + } + textField.addDisposeListener(new class DisposeListener { + public void widgetDisposed(DisposeEvent event) { + textField = null; + } + }); + if (textLimit > 0) {//Only set limits above 0 - see DWT spec + textField.setTextLimit(textLimit); + } + } else { + checkParent(textField, parent); + } + return textField; + } + + /** + * Returns whether an empty string is a valid value. + * + * @return true if an empty string is a valid value, and + * false if an empty string is invalid + * @see #setEmptyStringAllowed + */ + public bool isEmptyStringAllowed() { + return emptyStringAllowed; + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + public bool isValid() { + return isValid_; + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + protected void refreshValidState() { + isValid_ = checkState(); + } + + /** + * Sets whether the empty string is a valid value or not. + * + * @param b true if the empty string is allowed, + * and false if it is considered invalid + */ + public void setEmptyStringAllowed(bool b) { + emptyStringAllowed = b; + } + + /** + * Sets the error message that will be displayed when and if + * an error occurs. + * + * @param message the error message + */ + public void setErrorMessage(String message) { + errorMessage = message; + } + + /* (non-Javadoc) + * Method declared on FieldEditor. + */ + public void setFocus() { + if (textField !is null) { + textField.setFocus(); + } + } + + /** + * Sets this field editor's value. + * + * @param value the new value, or null meaning the empty string + */ + public void setStringValue(String value) { + if (textField !is null) { + if (value is null) { + value = "";//$NON-NLS-1$ + } + oldValue = textField.getText(); + if (!oldValue.equals(value)) { + textField.setText(value); + valueChanged(); + } + } + } + + /** + * Sets this text field's text limit. + * + * @param limit the limit on the number of character in the text + * input field, or UNLIMITED for no limit + + */ + public void setTextLimit(int limit) { + textLimit = limit; + if (textField !is null) { + textField.setTextLimit(limit); + } + } + + /** + * Sets the strategy for validating the text. + *

+ * Calling this method has no effect after createPartControl + * is called. Thus this method is really only useful for subclasses to call + * in their constructor. However, it has public visibility for backward + * compatibility. + *

+ * + * @param value either VALIDATE_ON_KEY_STROKE to perform + * on the fly checking (the default), or VALIDATE_ON_FOCUS_LOST to + * perform validation only after the text has been typed in + */ + public void setValidateStrategy(int value) { + Assert.isTrue(value is VALIDATE_ON_FOCUS_LOST + || value is VALIDATE_ON_KEY_STROKE); + validateStrategy = value; + } + + /** + * Shows the error message set via setErrorMessage. + */ + public void showErrorMessage() { + showErrorMessage(errorMessage); + } + + /** + * Informs this field editor's listener, if it has one, about a change + * to the value (VALUE property) provided that the old and + * new values are different. + *

+ * This hook is not called when the text is initialized + * (or reset to the default value) from the preference store. + *

+ */ + protected void valueChanged() { + setPresentsDefaultValue(false); + bool oldState = isValid_; + refreshValidState(); + + if (isValid_ !is oldState) { + fireStateChanged(IS_VALID, oldState, isValid_); + } + + String newValue = textField.getText(); + if (!newValue.equals(oldValue)) { + fireValueChanged(VALUE, stringcast(oldValue), stringcast(newValue)); + oldValue = newValue; + } + } + + /* + * @see FieldEditor.setEnabled(bool,Composite). + */ + public void setEnabled(bool enabled, Composite parent) { + super.setEnabled(enabled, parent); + getTextControl(parent).setEnabled(enabled); + } +}