Mercurial > projects > dwt-addons
comparison dwtx/jface/dialogs/DialogSettings.d @ 19:2b36428a5ce4
DialogSettings
author | Frank Benoit <benoit@tionex.de> |
---|---|
date | Thu, 03 Apr 2008 00:25:45 +0200 |
parents | |
children | da5ad8eedf5d |
comparison
equal
deleted
inserted
replaced
18:7615869f89e6 | 19:2b36428a5ce4 |
---|---|
1 /******************************************************************************* | |
2 * Copyright (c) 2000, 2006 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 * Port to the D programming language: | |
11 * Frank Benoit <benoit@tionex.de> | |
12 *******************************************************************************/ | |
13 module dwtx.jface.dialogs.DialogSettings; | |
14 | |
15 import dwtx.jface.dialogs.IDialogSettings; | |
16 | |
17 import tango.util.collection.model.Map; | |
18 import tango.util.collection.model.Seq; | |
19 import tango.util.collection.HashMap; | |
20 import tango.util.collection.ArraySeq; | |
21 | |
22 static import tango.text.xml.Document; | |
23 static import tango.text.xml.SaxParser; | |
24 static import tango.text.xml.PullParser; | |
25 static import tango.text.xml.XmlPrinter; | |
26 | |
27 | |
28 import dwt.dwthelper.utils; | |
29 static import dwt.dwthelper.OutputStream; | |
30 static import tango.text.convert.Integer; | |
31 static import tango.text.convert.Float; | |
32 static import tango.text.Text; | |
33 static import tango.io.File; | |
34 static import tango.io.Print; | |
35 static import tango.io.model.IConduit; | |
36 static import tango.io.stream.FileStream; | |
37 static import tango.text.convert.Format; | |
38 import tango.core.Exception; | |
39 alias tango.text.Text.Text!(char) StringBuffer; | |
40 | |
41 /** | |
42 * Concrete implementation of a dialog settings (<code>IDialogSettings</code>) | |
43 * using a hash table and XML. The dialog store can be read | |
44 * from and saved to a stream. All keys and values must be strings or array of | |
45 * strings. Primitive types are converted to strings. | |
46 * <p> | |
47 * This class was not designed to be subclassed. | |
48 * | |
49 * Here is an example of using a DialogSettings: | |
50 * </p> | |
51 * <pre> | |
52 * <code> | |
53 * DialogSettings settings = new DialogSettings("root"); | |
54 * settings.put("Boolean1",true); | |
55 * settings.put("Long1",100); | |
56 * settings.put("Array1",new String[]{"aaaa1","bbbb1","cccc1"}); | |
57 * DialogSettings section = new DialogSettings("sectionName"); | |
58 * settings.addSection(section); | |
59 * section.put("Int2",200); | |
60 * section.put("Float2",1.1); | |
61 * section.put("Array2",new String[]{"aaaa2","bbbb2","cccc2"}); | |
62 * settings.save("c:\\temp\\test\\dialog.xml"); | |
63 * </code> | |
64 * </pre> | |
65 */ | |
66 | |
67 public class DialogSettings : IDialogSettings { | |
68 alias tango.text.xml.Document.Document!(char) Document; | |
69 alias tango.text.xml.Document.Document!(char).Node Element; | |
70 alias tango.text.xml.XmlPrinter.XmlPrinter!(char) XmlPrinter; | |
71 // The name of the DialogSettings. | |
72 private String name; | |
73 | |
74 /* A Map of DialogSettings representing each sections in a DialogSettings. | |
75 It maps the DialogSettings' name to the DialogSettings */ | |
76 private Map!(String,IDialogSettings) sections; | |
77 | |
78 /* A Map with all the keys and values of this sections. | |
79 Either the keys an values are restricted to strings. */ | |
80 private Map!(String,String) items; | |
81 | |
82 // A Map with all the keys mapped to array of strings. | |
83 private Map!(String,String[]) arrayItems; | |
84 | |
85 private static const String TAG_SECTION = "section";//$NON-NLS-1$ | |
86 | |
87 private static const String TAG_NAME = "name";//$NON-NLS-1$ | |
88 | |
89 private static const String TAG_KEY = "key";//$NON-NLS-1$ | |
90 | |
91 private static const String TAG_VALUE = "value";//$NON-NLS-1$ | |
92 | |
93 private static const String TAG_LIST = "list";//$NON-NLS-1$ | |
94 | |
95 private static const String TAG_ITEM = "item";//$NON-NLS-1$ | |
96 | |
97 /** | |
98 * Create an empty dialog settings which loads and saves its | |
99 * content to a file. | |
100 * Use the methods <code>load(String)</code> and <code>store(String)</code> | |
101 * to load and store this dialog settings. | |
102 * | |
103 * @param sectionName the name of the section in the settings. | |
104 */ | |
105 public this(String sectionName) { | |
106 name = sectionName; | |
107 items = new HashMap!(String,String); | |
108 arrayItems = new HashMap!(String,String[]); | |
109 sections = new HashMap!(String,IDialogSettings); | |
110 } | |
111 | |
112 /* (non-Javadoc) | |
113 * Method declared on IDialogSettings. | |
114 */ | |
115 public IDialogSettings addNewSection(String sectionName) { | |
116 DialogSettings section = new DialogSettings(sectionName); | |
117 addSection(section); | |
118 return section; | |
119 } | |
120 | |
121 /* (non-Javadoc) | |
122 * Method declared on IDialogSettings. | |
123 */ | |
124 public void addSection(IDialogSettings section) { | |
125 sections.add(section.getName(), section); | |
126 } | |
127 | |
128 /* (non-Javadoc) | |
129 * Method declared on IDialogSettings. | |
130 */ | |
131 public String get(String key) { | |
132 return items.get(key); | |
133 } | |
134 | |
135 /* (non-Javadoc) | |
136 * Method declared on IDialogSettings. | |
137 */ | |
138 public String[] getArray(String key) { | |
139 return arrayItems.get(key); | |
140 } | |
141 | |
142 /* (non-Javadoc) | |
143 * Method declared on IDialogSettings. | |
144 */ | |
145 public bool getBoolean(String key) { | |
146 return items.get(key) == "true"; | |
147 } | |
148 | |
149 /* (non-Javadoc) | |
150 * Method declared on IDialogSettings. | |
151 */ | |
152 public double getDouble(String key) { | |
153 String setting = items.get(key); | |
154 if (setting is null) { | |
155 throw new NumberFormatException( | |
156 "There is no setting associated with the key \"" ~ key ~ "\"");//$NON-NLS-1$ //$NON-NLS-2$ | |
157 } | |
158 | |
159 return tango.text.convert.Float.toFloat(setting); | |
160 } | |
161 | |
162 /* (non-Javadoc) | |
163 * Method declared on IDialogSettings. | |
164 */ | |
165 public float getFloat(String key) { | |
166 String setting = items.get(key); | |
167 if (setting is null) { | |
168 throw new NumberFormatException( | |
169 "There is no setting associated with the key \"" ~ key ~ "\"");//$NON-NLS-1$ //$NON-NLS-2$ | |
170 } | |
171 | |
172 return tango.text.convert.Float.toFloat(setting); | |
173 } | |
174 | |
175 /* (non-Javadoc) | |
176 * Method declared on IDialogSettings. | |
177 */ | |
178 public int getInt(String key) { | |
179 String setting = items.get(key); | |
180 if (setting is null) { | |
181 //new Integer(null) will throw a NumberFormatException and meet our spec, but this message | |
182 //is clearer. | |
183 throw new NumberFormatException( | |
184 "There is no setting associated with the key \"" ~ key ~ "\"");//$NON-NLS-1$ //$NON-NLS-2$ | |
185 } | |
186 | |
187 return tango.text.convert.Integer.toInt(setting); | |
188 } | |
189 | |
190 /* (non-Javadoc) | |
191 * Method declared on IDialogSettings. | |
192 */ | |
193 public long getLong(String key) { | |
194 String setting = items.get(key); | |
195 if (setting is null) { | |
196 //new Long(null) will throw a NumberFormatException and meet our spec, but this message | |
197 //is clearer. | |
198 throw new NumberFormatException( | |
199 "There is no setting associated with the key \"" ~ key ~ "\"");//$NON-NLS-1$ //$NON-NLS-2$ | |
200 } | |
201 | |
202 return tango.text.convert.Integer.toLong(setting); | |
203 } | |
204 | |
205 /* (non-Javadoc) | |
206 * Method declared on IDialogSettings. | |
207 */ | |
208 public String getName() { | |
209 return name; | |
210 } | |
211 | |
212 /* (non-Javadoc) | |
213 * Method declared on IDialogSettings. | |
214 */ | |
215 public IDialogSettings getSection(String sectionName) { | |
216 return sections.get(sectionName); | |
217 } | |
218 | |
219 /* (non-Javadoc) | |
220 * Method declared on IDialogSettings. | |
221 */ | |
222 public IDialogSettings[] getSections() { | |
223 return sections.toArray(); | |
224 } | |
225 | |
226 /* (non-Javadoc) | |
227 * Method declared on IDialogSettings. | |
228 */ | |
229 public void load( tango.io.model.IConduit.InputStream input) { | |
230 Document document = new Document(); | |
231 try { | |
232 char[] content; | |
233 char[1024] readbuf; | |
234 int chunksize = 0; | |
235 while( (chunksize=input.read(readbuf)) !is tango.io.model.IConduit.InputStream.Eof ){ | |
236 content ~= readbuf[ 0 .. chunksize ]; | |
237 } | |
238 document.parse( content ); | |
239 | |
240 //Strip out any comments first | |
241 foreach( n; document.query[].filter( delegate bool(Element n) { | |
242 return n.type is tango.text.xml.PullParser.XmlNodeType.Comment ; | |
243 })){ | |
244 //TODO: remove() was added after tango 0.99.5 | |
245 //n.remove(); | |
246 } | |
247 load(document, document.root.firstChild ); | |
248 } catch (IOException e) { | |
249 // ignore | |
250 } catch (TextException e) { | |
251 // ignore | |
252 } | |
253 } | |
254 | |
255 /* (non-Javadoc) | |
256 * Method declared on IDialogSettings. | |
257 */ | |
258 //TODO: solve overload load(char[]) | |
259 public void load(String fileName) { | |
260 auto f = new tango.io.stream.FileStream.FileInput( fileName ); | |
261 load( f.input ); | |
262 f.close; | |
263 } | |
264 | |
265 /* (non-Javadoc) | |
266 * Load the setting from the <code>document</code> | |
267 */ | |
268 private void load(Document document, Element root) { | |
269 | |
270 name = root.getAttribute(TAG_NAME).value(); | |
271 | |
272 foreach( n; root.query[TAG_ITEM] ){ | |
273 if( root is n.parent() ){ | |
274 String key = n.getAttribute(TAG_KEY).value().dup; | |
275 String value = n.getAttribute(TAG_VALUE).value().dup; | |
276 items.add(key, value); | |
277 } | |
278 } | |
279 foreach( n; root.query[TAG_LIST].dup ){ | |
280 if( root is n.parent() ){ | |
281 auto child = n; | |
282 String key = child.getAttribute(TAG_KEY).value().dup; | |
283 char[][] valueList; | |
284 foreach( node; root.query[TAG_ITEM].dup ){ | |
285 if (child is node.parent()) { | |
286 valueList ~= node.getAttribute(TAG_VALUE).value().dup; | |
287 } | |
288 } | |
289 arrayItems.add(key, valueList ); | |
290 } | |
291 } | |
292 foreach( n; root.query[TAG_SECTION].dup ){ | |
293 if( root is n.parent() ){ | |
294 DialogSettings s = new DialogSettings("NoName");//$NON-NLS-1$ | |
295 s.load(document, n); | |
296 addSection(s); | |
297 } | |
298 } | |
299 } | |
300 | |
301 /* (non-Javadoc) | |
302 * Method declared on IDialogSettings. | |
303 */ | |
304 public void put(String key, String[] value) { | |
305 arrayItems.add(key, value); | |
306 } | |
307 | |
308 /* (non-Javadoc) | |
309 * Method declared on IDialogSettings. | |
310 */ | |
311 public void put(String key, double value) { | |
312 put(key, tango.text.convert.Float.toString(value)); | |
313 } | |
314 | |
315 /* (non-Javadoc) | |
316 * Method declared on IDialogSettings. | |
317 */ | |
318 public void put(String key, float value) { | |
319 put(key, tango.text.convert.Float.toString(value)); | |
320 } | |
321 | |
322 /* (non-Javadoc) | |
323 * Method declared on IDialogSettings. | |
324 */ | |
325 public void put(String key, int value) { | |
326 put(key, tango.text.convert.Integer.toString(value)); | |
327 } | |
328 | |
329 /* (non-Javadoc) | |
330 * Method declared on IDialogSettings. | |
331 */ | |
332 public void put(String key, long value) { | |
333 put(key, tango.text.convert.Integer.toString(value)); | |
334 } | |
335 | |
336 /* (non-Javadoc) | |
337 * Method declared on IDialogSettings. | |
338 */ | |
339 public void put(String key, String value) { | |
340 items.add(key, value); | |
341 } | |
342 | |
343 /* (non-Javadoc) | |
344 * Method declared on IDialogSettings. | |
345 */ | |
346 public void put(String key, bool value) { | |
347 put(key, value ? "true" : "false" ); | |
348 } | |
349 | |
350 /* (non-Javadoc) | |
351 * Method declared on IDialogSettings. | |
352 */ | |
353 public void save(tango.io.model.IConduit.OutputStream writer) { | |
354 save(new XMLWriter(writer)); | |
355 } | |
356 | |
357 | |
358 /* (non-Javadoc) | |
359 * Method declared on IDialogSettings. | |
360 */ | |
361 public void save(String fileName) { | |
362 auto stream = new tango.io.stream.FileStream.FileOutput(fileName); | |
363 XMLWriter writer = new XMLWriter(stream.output); | |
364 save(writer); | |
365 writer.close(); | |
366 } | |
367 | |
368 /* (non-Javadoc) | |
369 * Save the settings in the <code>document</code>. | |
370 */ | |
371 private void save(XMLWriter out_) { | |
372 HashMap!(String,String) attributes = new HashMap!(String,String); | |
373 attributes.add(TAG_NAME, name is null ? "" : name); //$NON-NLS-1$ | |
374 out_.startTag(TAG_SECTION, attributes); | |
375 attributes.clear(); | |
376 | |
377 foreach( key,value; items ){ | |
378 attributes.add(TAG_KEY, key is null ? "" : key); //$NON-NLS-1$ | |
379 String string = value;cast(String) items.get(key); | |
380 attributes.add(TAG_VALUE, string is null ? "" : string); //$NON-NLS-1$ | |
381 out_.printTag(TAG_ITEM, attributes, true); | |
382 } | |
383 | |
384 attributes.clear(); | |
385 foreach( key,value; arrayItems ){ | |
386 attributes.add(TAG_KEY, key is null ? "" : key); //$NON-NLS-1$ | |
387 out_.startTag(TAG_LIST, attributes); | |
388 attributes.clear(); | |
389 if (value !is null) { | |
390 for (int index = 0; index < value.length; index++) { | |
391 String string = value[index]; | |
392 attributes.add(TAG_VALUE, string is null ? "" : string); //$NON-NLS-1$ | |
393 out_.printTag(TAG_ITEM, attributes, true); | |
394 } | |
395 } | |
396 out_.endTag(TAG_LIST); | |
397 attributes.clear(); | |
398 } | |
399 foreach( name, section; sections ){ | |
400 section.save(out_); | |
401 } | |
402 out_.endTag(TAG_SECTION); | |
403 } | |
404 | |
405 | |
406 /** | |
407 * A simple XML writer. Using this instead of the javax.xml.transform classes allows | |
408 * compilation against JCL Foundation (bug 80059). | |
409 */ | |
410 private static class XMLWriter : tango.io.Print.Print!(char) { | |
411 /** current number of tabs to use for ident */ | |
412 protected int tab; | |
413 | |
414 /** the xml header */ | |
415 protected static const String XML_VERSION = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; //$NON-NLS-1$ | |
416 | |
417 /** | |
418 * Create a new XMLWriter | |
419 * @param output the write to used when writing to | |
420 */ | |
421 public this(tango.io.model.IConduit.OutputStream output) { | |
422 super( tango.text.convert.Format.Format, output); | |
423 tab = 0; | |
424 print(XML_VERSION); | |
425 newline; | |
426 } | |
427 | |
428 /** | |
429 * write the intended end tag | |
430 * @param name the name of the tag to end | |
431 */ | |
432 public void endTag(String name) { | |
433 tab--; | |
434 printTag("/" ~ name, null, false); //$NON-NLS-1$ | |
435 } | |
436 | |
437 private void printTabulation() { | |
438 for (int i = 0; i < tab; i++) { | |
439 super.print('\t'); | |
440 } | |
441 } | |
442 | |
443 /** | |
444 * write the tag to the stream and format it by itending it and add new line after the tag | |
445 * @param name the name of the tag | |
446 * @param parameters map of parameters | |
447 * @param close should the tag be ended automatically (=> empty tag) | |
448 */ | |
449 public void printTag(String name, HashMap!(String,String) parameters, bool close) { | |
450 printTag(name, parameters, true, true, close); | |
451 } | |
452 | |
453 private void printTag(String name, HashMap!(String,String) parameters, bool shouldTab, bool newLine, bool close) { | |
454 StringBuffer sb = new StringBuffer(); | |
455 sb.append('<'); | |
456 sb.append(name); | |
457 if (parameters !is null) { | |
458 foreach( key, value; parameters ){ | |
459 sb.append(" "); //$NON-NLS-1$ | |
460 sb.append(key); | |
461 sb.append("=\""); //$NON-NLS-1$ | |
462 sb.append(xmlEscape(value.dup)); | |
463 sb.append("\""); //$NON-NLS-1$ | |
464 } | |
465 } | |
466 if (close) { | |
467 sb.append('/'); | |
468 } | |
469 sb.append('>'); | |
470 if (shouldTab) { | |
471 printTabulation(); | |
472 } | |
473 if (newLine) { | |
474 print(sb.toString()); | |
475 newline; | |
476 } else { | |
477 print(sb.toString()); | |
478 } | |
479 } | |
480 | |
481 /** | |
482 * start the tag | |
483 * @param name the name of the tag | |
484 * @param parameters map of parameters | |
485 */ | |
486 public void startTag(String name, HashMap!(String,String) parameters) { | |
487 startTag(name, parameters, true); | |
488 tab++; | |
489 } | |
490 | |
491 private void startTag(String name, HashMap!(String,String) parameters, bool newLine) { | |
492 printTag(name, parameters, true, newLine, false); | |
493 } | |
494 } | |
495 | |
496 } |