Mercurial > projects > dwt-addons
comparison dwtx/jface/preference/FieldEditorPreferencePage.d @ 34:b3c8e32d406f
preference
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Sat, 05 Apr 2008 01:45:47 +0200 |
parents | |
children | ea8ff534f622 |
comparison
equal
deleted
inserted
replaced
33:f25582573129 | 34:b3c8e32d406f |
---|---|
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 } |