34
|
1 /*******************************************************************************
|
|
2 * Copyright (c) 2000, 2007 IBM Corporation and others.
|
|
3 * All rights reserved. This program and the accompanying materials
|
|
4 * are made available under the terms of the Eclipse Public License v1.0
|
|
5 * which accompanies this distribution, and is available at
|
|
6 * http://www.eclipse.org/legal/epl-v10.html
|
|
7 *
|
|
8 * Contributors:
|
|
9 * IBM Corporation - initial API and implementation
|
|
10 * Chris Tilt (chris@tilts.net) - Bug 38547 - [Preferences] Changing preferences
|
|
11 * ignored after "Restore defaults" pressed.
|
|
12 * Port to the D programming language:
|
|
13 * Frank Benoit <benoit@tionex.de>
|
|
14 *******************************************************************************/
|
|
15 module dwtx.jface.preference.FieldEditorPreferencePage;
|
|
16
|
|
17 import dwtx.jface.preference.PreferencePage;
|
|
18 import dwtx.jface.preference.FieldEditor;
|
|
19 import dwtx.jface.preference.FieldEditorPreferencePage;
|
|
20
|
|
21 import tango.util.collection.ArraySeq;
|
|
22 import tango.util.collection.model.Seq;
|
|
23 // import java.util.Iterator;
|
|
24 // import java.util.List;
|
|
25
|
|
26 import dwt.DWT;
|
|
27 import dwt.layout.GridData;
|
|
28 import dwt.layout.GridLayout;
|
|
29 import dwt.widgets.Composite;
|
|
30 import dwt.widgets.Control;
|
|
31 import dwtx.jface.resource.ImageDescriptor;
|
|
32 import dwtx.jface.util.IPropertyChangeListener;
|
|
33 import dwtx.jface.util.PropertyChangeEvent;
|
|
34
|
|
35 import dwt.dwthelper.utils;
|
|
36
|
|
37 /**
|
|
38 * A special abstract preference page to host field editors.
|
|
39 * <p>
|
|
40 * Subclasses must implement the <code>createFieldEditors</code> method
|
|
41 * and should override <code>createLayout</code> if a special layout of the field
|
|
42 * editors is needed.
|
|
43 * </p>
|
|
44 */
|
|
45 public abstract class FieldEditorPreferencePage : PreferencePage,
|
|
46 IPropertyChangeListener {
|
|
47
|
|
48 /**
|
|
49 * Layout constant (value <code>0</code>) indicating that
|
|
50 * each field editor is handled as a single component.
|
|
51 */
|
|
52 public static const int FLAT = 0;
|
|
53
|
|
54 /**
|
|
55 * Layout constant (value <code>1</code>) indicating that
|
|
56 * the field editors' basic controls are put into a grid layout.
|
|
57 */
|
|
58 public static const int GRID = 1;
|
|
59
|
|
60 /**
|
|
61 * The vertical spacing used by layout styles <code>FLAT</code>
|
|
62 * and <code>GRID</code>.
|
|
63 */
|
|
64 protected static const int VERTICAL_SPACING = 10;
|
|
65
|
|
66 /**
|
|
67 * The margin width used by layout styles <code>FLAT</code>
|
|
68 * and <code>GRID</code>.
|
|
69 */
|
|
70 protected static const int MARGIN_WIDTH = 0;
|
|
71
|
|
72 /**
|
|
73 * The margin height used by layout styles <code>FLAT</code>
|
|
74 * and <code>GRID</code>.
|
|
75 */
|
|
76 protected static const int MARGIN_HEIGHT = 0;
|
|
77
|
|
78 /**
|
|
79 * The field editors, or <code>null</code> if not created yet.
|
|
80 */
|
|
81 private Seq!(Object) fields = null;
|
|
82
|
|
83 /**
|
|
84 * The layout style; either <code>FLAT</code> or <code>GRID</code>.
|
|
85 */
|
|
86 private int style;
|
|
87
|
|
88 /**
|
|
89 * The first invalid field editor, or <code>null</code>
|
|
90 * if all field editors are valid.
|
|
91 */
|
|
92 private FieldEditor invalidFieldEditor = null;
|
|
93
|
|
94 /**
|
|
95 * The parent composite for field editors
|
|
96 */
|
|
97 private Composite fieldEditorParent;
|
|
98
|
|
99 /**
|
|
100 * Create a new instance of the reciever.
|
|
101 */
|
|
102 public this() {
|
|
103 this(FLAT);
|
|
104 }
|
|
105
|
|
106 /**
|
|
107 * Creates a new field editor preference page with the given style,
|
|
108 * an empty title, and no image.
|
|
109 *
|
|
110 * @param style either <code>GRID</code> or <code>FLAT</code>
|
|
111 */
|
|
112 protected this(int style) {
|
|
113 super();
|
|
114 this.style = style;
|
|
115 }
|
|
116
|
|
117 /**
|
|
118 * Creates a new field editor preference page with the given title
|
|
119 * and style, but no image.
|
|
120 *
|
|
121 * @param title the title of this preference page
|
|
122 * @param style either <code>GRID</code> or <code>FLAT</code>
|
|
123 */
|
|
124 protected this(String title, int style) {
|
|
125 super(title);
|
|
126 this.style = style;
|
|
127 }
|
|
128
|
|
129 /**
|
|
130 * Creates a new field editor preference page with the given title,
|
|
131 * image, and style.
|
|
132 *
|
|
133 * @param title the title of this preference page
|
|
134 * @param image the image for this preference page, or
|
|
135 * <code>null</code> if none
|
|
136 * @param style either <code>GRID</code> or <code>FLAT</code>
|
|
137 */
|
|
138 protected this(String title, ImageDescriptor image,
|
|
139 int style) {
|
|
140 super(title, image);
|
|
141 this.style = style;
|
|
142 }
|
|
143
|
|
144 /**
|
|
145 * Adds the given field editor to this page.
|
|
146 *
|
|
147 * @param editor the field editor
|
|
148 */
|
|
149 protected void addField(FieldEditor editor) {
|
|
150 if (fields is null) {
|
|
151 fields = new ArraySeq!(Object);
|
|
152 }
|
|
153 fields.append(editor);
|
|
154 }
|
|
155
|
|
156 /**
|
|
157 * Adjust the layout of the field editors so that
|
|
158 * they are properly aligned.
|
|
159 */
|
|
160 protected void adjustGridLayout() {
|
|
161 int numColumns = calcNumberOfColumns();
|
|
162 (cast(GridLayout) fieldEditorParent.getLayout()).numColumns = numColumns;
|
|
163 if (fields !is null) {
|
|
164 for (int i = 0; i < fields.size(); i++) {
|
|
165 FieldEditor fieldEditor = cast(FieldEditor) fields.get(i);
|
|
166 fieldEditor.adjustForNumColumns_package(numColumns);
|
|
167 }
|
|
168 }
|
|
169 }
|
|
170
|
|
171 /**
|
|
172 * Applys the font to the field editors managed by this page.
|
|
173 */
|
|
174 protected void applyFont() {
|
|
175 if (fields !is null) {
|
|
176 foreach( e; fields ){
|
|
177 FieldEditor pe = cast(FieldEditor) e;
|
|
178 pe.applyFont_package();
|
|
179 }
|
|
180 }
|
|
181 }
|
|
182
|
|
183 /**
|
|
184 * Calculates the number of columns needed to host all field editors.
|
|
185 *
|
|
186 * @return the number of columns
|
|
187 */
|
|
188 private int calcNumberOfColumns() {
|
|
189 int result = 0;
|
|
190 if (fields !is null) {
|
|
191 foreach( e; fields ){
|
|
192 FieldEditor pe = cast(FieldEditor) e;
|
|
193 result = Math.max(result, pe.getNumberOfControls());
|
|
194 }
|
|
195 }
|
|
196 return result;
|
|
197 }
|
|
198
|
|
199 /**
|
|
200 * Recomputes the page's error state by calling <code>isValid</code> for
|
|
201 * every field editor.
|
|
202 */
|
|
203 protected void checkState() {
|
|
204 bool valid = true;
|
|
205 invalidFieldEditor = null;
|
|
206 // The state can only be set to true if all
|
|
207 // field editors contain a valid value. So we must check them all
|
|
208 if (fields !is null) {
|
|
209 int size = fields.size();
|
|
210 for (int i = 0; i < size; i++) {
|
|
211 FieldEditor editor = cast(FieldEditor) fields.get(i);
|
|
212 valid = valid && editor.isValid();
|
|
213 if (!valid) {
|
|
214 invalidFieldEditor = editor;
|
|
215 break;
|
|
216 }
|
|
217 }
|
|
218 }
|
|
219 setValid(valid);
|
|
220 }
|
|
221
|
|
222 /* (non-Javadoc)
|
|
223 * Method declared on PreferencePage.
|
|
224 */
|
|
225 protected Control createContents(Composite parent) {
|
|
226 fieldEditorParent = new Composite(parent, DWT.NULL);
|
|
227 GridLayout layout = new GridLayout();
|
|
228 layout.numColumns = 1;
|
|
229 layout.marginHeight = 0;
|
|
230 layout.marginWidth = 0;
|
|
231 fieldEditorParent.setLayout(layout);
|
|
232 fieldEditorParent.setFont(parent.getFont());
|
|
233
|
|
234 createFieldEditors();
|
|
235
|
|
236 if (style is GRID) {
|
|
237 adjustGridLayout();
|
|
238 }
|
|
239
|
|
240 initialize();
|
|
241 checkState();
|
|
242 return fieldEditorParent;
|
|
243 }
|
|
244
|
|
245 /**
|
|
246 * Creates the page's field editors.
|
|
247 * <p>
|
|
248 * The default implementation of this framework method
|
|
249 * does nothing. Subclass must implement this method to
|
|
250 * create the field editors.
|
|
251 * </p>
|
|
252 * <p>
|
|
253 * Subclasses should call <code>getFieldEditorParent</code>
|
|
254 * to obtain the parent control for each field editor.
|
|
255 * This same parent should not be used for more than
|
|
256 * one editor as the parent may change for each field
|
|
257 * editor depending on the layout style of the page
|
|
258 * </p>
|
|
259 */
|
|
260 protected abstract void createFieldEditors();
|
|
261
|
|
262 /**
|
|
263 * The field editor preference page implementation of an <code>IDialogPage</code>
|
|
264 * method disposes of this page's controls and images.
|
|
265 * Subclasses may override to release their own allocated DWT
|
|
266 * resources, but must call <code>super.dispose</code>.
|
|
267 */
|
|
268 public void dispose() {
|
|
269 super.dispose();
|
|
270 if (fields !is null) {
|
|
271 foreach( e; fields ){
|
|
272 FieldEditor pe = cast(FieldEditor) e;
|
|
273 pe.setPage(null);
|
|
274 pe.setPropertyChangeListener(null);
|
|
275 pe.setPreferenceStore(null);
|
|
276 }
|
|
277 }
|
|
278 }
|
|
279
|
|
280 /**
|
|
281 * Returns a parent composite for a field editor.
|
|
282 * <p>
|
|
283 * This value must not be cached since a new parent
|
|
284 * may be created each time this method called. Thus
|
|
285 * this method must be called each time a field editor
|
|
286 * is constructed.
|
|
287 * </p>
|
|
288 *
|
|
289 * @return a parent
|
|
290 */
|
|
291 protected Composite getFieldEditorParent() {
|
|
292 if (style is FLAT) {
|
|
293 // Create a new parent for each field editor
|
|
294 Composite parent = new Composite(fieldEditorParent, DWT.NULL);
|
|
295 parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
|
|
296 return parent;
|
|
297 }
|
|
298 // Just return the parent
|
|
299 return fieldEditorParent;
|
|
300 }
|
|
301
|
|
302 /**
|
|
303 * Initializes all field editors.
|
|
304 */
|
|
305 protected void initialize() {
|
|
306 if (fields !is null) {
|
|
307 foreach( e; fields ){
|
|
308 FieldEditor pe = cast(FieldEditor) e;
|
|
309 pe.setPage(this);
|
|
310 pe.setPropertyChangeListener(this);
|
|
311 pe.setPreferenceStore(getPreferenceStore());
|
|
312 pe.load();
|
|
313 }
|
|
314 }
|
|
315 }
|
|
316
|
|
317 /**
|
|
318 * The field editor preference page implementation of a <code>PreferencePage</code>
|
|
319 * method loads all the field editors with their default values.
|
|
320 */
|
|
321 protected void performDefaults() {
|
|
322 if (fields !is null) {
|
|
323 foreach( e; fields ){
|
|
324 FieldEditor pe = cast(FieldEditor) e;
|
|
325 pe.loadDefault();
|
|
326 }
|
|
327 }
|
|
328 // Force a recalculation of my error state.
|
|
329 checkState();
|
|
330 super.performDefaults();
|
|
331 }
|
|
332
|
|
333 /**
|
|
334 * The field editor preference page implementation of this
|
|
335 * <code>PreferencePage</code> method saves all field editors by
|
|
336 * calling <code>FieldEditor.store</code>. Note that this method
|
|
337 * does not save the preference store itself; it just stores the
|
|
338 * values back into the preference store.
|
|
339 *
|
|
340 * @see FieldEditor#store()
|
|
341 */
|
|
342 public bool performOk() {
|
|
343 if (fields !is null) {
|
|
344 foreach( e; fields ){
|
|
345 FieldEditor pe = cast(FieldEditor) e;
|
|
346 pe.store();
|
|
347 pe.setPresentsDefaultValue_package(false);
|
|
348 }
|
|
349 }
|
|
350 return true;
|
|
351 }
|
|
352
|
|
353 /**
|
|
354 * The field editor preference page implementation of this <code>IPreferencePage</code>
|
|
355 * (and <code>IPropertyChangeListener</code>) method intercepts <code>IS_VALID</code>
|
|
356 * events but passes other events on to its superclass.
|
|
357 */
|
|
358 public void propertyChange(PropertyChangeEvent event) {
|
|
359
|
|
360 if (event.getProperty().equals(FieldEditor.IS_VALID)) {
|
|
361 bool newValue = (cast(ValueWrapperBool) event.getNewValue()).value;
|
|
362 // If the new value is true then we must check all field editors.
|
|
363 // If it is false, then the page is invalid in any case.
|
|
364 if (newValue) {
|
|
365 checkState();
|
|
366 } else {
|
|
367 invalidFieldEditor = cast(FieldEditor) event.getSource();
|
|
368 setValid(newValue);
|
|
369 }
|
|
370 }
|
|
371 }
|
|
372
|
|
373 /* (non-Javadoc)
|
|
374 * Method declared on IDialog.
|
|
375 */
|
|
376 public void setVisible(bool visible) {
|
|
377 super.setVisible(visible);
|
|
378 if (visible && invalidFieldEditor !is null) {
|
|
379 invalidFieldEditor.setFocus();
|
|
380 }
|
|
381 }
|
|
382 }
|