Mercurial > repos > IBBoard
annotate Preferences.cs @ 44:8725c5440606
* Add custom XMLResolver that lets developers map relative URIs to actual URIs (e.g. for mapping XHTML DTD to local file to stop remote fetch)
Required for warfoundry:#144
no-open-ticket
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Sun, 04 Oct 2009 15:50:58 +0000 |
parents | cc7fae81afec |
children | 0f88d32b22cc |
rev | line source |
---|---|
16 | 1 // This file (Preferences.cs) is a part of the IBBoard library and is copyright 2009 IBBoard. |
2 // | |
3 // The file and the library/program it is in are licensed under the GNU LGPL license, either version 3 of the License or (at your option) any later version. Please see COPYING.LGPL for more information and the full license. | |
4 | |
37 | 5 using System; |
6 using System.Collections; | |
7 using System.IO; | |
8 using System.Xml; | |
0
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
9 using System.Reflection; |
37 | 10 using IBBoard.IO; |
0
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
11 |
37 | 12 //TODO: Add import/export |
13 namespace IBBoard | |
14 { | |
15 /// <summary> | |
16 /// Summary description for Preferences. | |
17 /// </summary> | |
18 public class Preferences | |
19 { | |
20 private static Type stringType = typeof(string); | |
21 private static Type hashtableType = typeof(Hashtable); | |
22 private Hashtable htGlobal; | |
23 private Hashtable htLocal; | |
24 | |
25 private string app; | |
0
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
26 private bool modified = false; |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
27 |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
28 |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
29 public Preferences(string appName) |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
30 { |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
31 app = appName; |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
32 LoadPreferences(); |
37 | 33 } |
34 | |
35 /*public Preferences(string appExecPath, string appName, string fullUserDataDir) | |
36 { | |
37 LoadPreferences(appExecPath.TrimEnd(Constants.DirectoryChar) + Constants.DirectoryChar + appName + "Pref.xml", fullUserDataDir.TrimEnd(Constants.DirectoryChar)); | |
38 } | |
39 | |
40 public Preferences(string filepath, string appDir) | |
41 { | |
42 LoadPreferences(filepath, appDir); | |
43 }*/ | |
44 | |
45 private void LoadPreferences() | |
46 { | |
47 htGlobal = new Hashtable(); | |
0
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
48 htLocal = new Hashtable(); |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
49 |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
50 string globalPath = Constants.ExecutablePath + Constants.DirectoryChar + app + "Pref.xml"; |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
51 |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
52 if (File.Exists(globalPath)) |
37 | 53 { |
54 XmlDocument xmld = new XmlDocument(); | |
55 xmld.Load(globalPath); | |
56 XmlNodeList nl = xmld.LastChild.ChildNodes; | |
57 XmlNodeList nlHash; | |
58 MethodInfo m; | |
59 Type t; | |
60 Hashtable htTemp; | |
61 | |
62 if (nl == null || nl.Count==0) | |
63 { | |
64 throw new InvalidFileException("Preference file "+globalPath+" did not contain any preferences"); | |
65 } | |
66 | |
67 for (int i = 0; i<nl.Count; i++) | |
68 { | |
69 t = Type.GetType(nl[i].Attributes["type"].Value, true); | |
70 | |
71 if (t!=stringType) | |
72 { | |
73 if (t==hashtableType) | |
74 { | |
75 htTemp = new Hashtable(); | |
76 nlHash = nl[i].ChildNodes; | |
77 | |
78 for (int j = 0; j<nlHash.Count; j++) | |
79 { | |
80 if (nlHash[j].NodeType.GetType()==typeof(XmlElement)) | |
81 { | |
82 t = Type.GetType(nlHash[j].Attributes["type"].Value, true); | |
83 m = t.GetMethod("Parse", new Type[]{stringType}); | |
84 htTemp[nlHash[j].Attributes["key"].Value] = m.Invoke(null, new object[]{nlHash[j].InnerText}); | |
85 } | |
86 } | |
87 | |
88 htGlobal[nl[i].Attributes["id"].Value] = htTemp; | |
89 } | |
90 else if (t.IsEnum) | |
91 { | |
92 htGlobal[nl[i].Attributes["id"].Value] = Enum.Parse(t, nl[i].InnerText, true); | |
93 } | |
94 else | |
95 { | |
96 m = t.GetMethod("Parse", new Type[]{stringType}); | |
97 htGlobal[nl[i].Attributes["id"].Value] = m.Invoke(null, new object[]{nl[i].InnerText}); | |
98 } | |
99 } | |
100 else | |
101 { | |
102 htGlobal[nl[i].Attributes["id"].Value] = nl[i].InnerText; | |
103 } | |
104 } | |
105 | |
106 LoadLocalPreferences(); | |
107 } | |
108 else | |
109 { | |
110 throw new FileNotFoundException("Could not find default preferences at "+globalPath); | |
111 } | |
0
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
112 } |
37 | 113 |
114 private void LoadLocalPreferences() | |
115 { | |
116 string path = Constants.UserDataPath + Constants.DirectoryString + "preferences.xml"; | |
117 | |
118 if (File.Exists(path)) | |
119 { | |
120 XmlDocument xmld = new XmlDocument(); | |
121 xmld.Load(path); | |
122 XmlNodeList nl = xmld.LastChild.ChildNodes; | |
123 XmlNodeList nlHash; | |
124 MethodInfo m; | |
125 Type t; | |
126 Hashtable htTemp = new Hashtable(); | |
127 | |
128 nl = xmld.LastChild.ChildNodes; | |
129 | |
130 for (int i = 0; i<nl.Count; i++) | |
131 { | |
132 if (!htGlobal.ContainsKey(nl[i].Attributes["id"].Value)) | |
133 { | |
134 throw new InvalidFileException("User preferences file contains a value for key \""+nl[i].Attributes["id"].Value+"\" which is not contained in the main preferences"); | |
135 } | |
136 | |
137 t = Type.GetType(nl[i].Attributes["type"].Value, true); | |
138 if (t!=stringType) | |
139 { | |
140 if (t==hashtableType) | |
141 { | |
142 htTemp = new Hashtable(); | |
143 nlHash = nl[i].ChildNodes; | |
144 Hashtable htTempInner = new Hashtable(); | |
145 | |
146 for (int j = 0; j<nlHash.Count; j++) | |
147 { | |
148 if (nlHash[j].NodeType==XmlNodeType.Element) | |
149 { | |
150 t = Type.GetType(nlHash[j].Attributes["type"].Value, true); | |
151 m = t.GetMethod("Parse", new Type[]{stringType}); | |
152 htTempInner[nlHash[j].Attributes["key"].Value] = m.Invoke(null, new object[]{nlHash[j].InnerText}); | |
153 } | |
154 } | |
155 | |
156 htTemp[nl[i].Attributes["id"].Value] = htTempInner; | |
157 } | |
158 else if (t.IsEnum) | |
159 { | |
160 htTemp[nl[i].Attributes["id"].Value] = Enum.Parse(t, nl[i].InnerText, true); | |
161 } | |
162 else | |
163 { | |
0
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
164 m = t.GetMethod("Parse", new Type[]{stringType}); |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
165 |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
166 if (m!=null) |
37 | 167 { |
0
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
168 htTemp[nl[i].Attributes["id"].Value] = m.Invoke(null, new object[]{nl[i].InnerText}); |
37 | 169 } |
170 } | |
171 } | |
172 else | |
173 { | |
174 htTemp[nl[i].Attributes["id"].Value] = nl[i].InnerText; | |
175 } | |
176 } | |
177 | |
178 htLocal = htTemp; | |
179 } | |
180 } | |
181 | |
182 public void ReloadPreferences() | |
183 { | |
184 htLocal.Clear(); | |
185 LoadLocalPreferences(); | |
186 } | |
187 | |
188 public object this[string key] | |
0
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
189 { |
37 | 190 get { return this[key, true]; } |
191 | |
192 set | |
193 { | |
194 if (!htGlobal.ContainsKey(key)) | |
195 { | |
196 throw new InvalidOperationException("Preference must already exist in the Global Preferences"); | |
197 } | |
198 | |
199 if (htGlobal[key].GetType()!=value.GetType()) | |
200 { | |
201 throw new InvalidOperationException("Preferences must be set with an object of the same type as the existing preference"); | |
202 } | |
203 | |
204 if (value is Hashtable) | |
205 { | |
206 throw new InvalidOperationException("Hashtables in Preferences cannot be set, they can only be added to or removed from."); | |
207 } | |
208 | |
209 if (htGlobal[key].Equals(value)) | |
210 { | |
211 if (htLocal.ContainsKey(key)) | |
212 { | |
213 htLocal.Remove(key); | |
214 modified = true; | |
215 } | |
216 } | |
217 else if (!((htLocal[key]==null && value==null) || value.Equals(htLocal[key]))) | |
218 { | |
219 htLocal[key] = value; | |
220 modified = true; | |
221 } | |
222 //else nothing actually needs modifying | |
0
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
223 } |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
224 } |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
225 |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
226 public object this[string key, bool errorOnNoVal] |
37 | 227 { |
228 get | |
229 { | |
230 if (htLocal.ContainsKey(key)) | |
231 { | |
232 return htLocal[key]; | |
233 } | |
234 else if (htGlobal.ContainsKey(key)) | |
235 { | |
236 if (htGlobal[key] is Hashtable) | |
237 { | |
238 htLocal[key] = ((Hashtable)htGlobal[key]).Clone(); | |
239 return htLocal[key]; | |
240 } | |
241 else | |
242 { | |
243 return htGlobal[key]; | |
244 } | |
245 } | |
246 else if (errorOnNoVal) | |
247 { | |
248 throw new InvalidOperationException("Key \""+key+"\" was not associated with a preference value"); | |
0
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
249 } |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
250 |
37 | 251 return null; |
252 } | |
0
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
253 } |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
254 |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
255 public bool GetBooleanProperty(string key) |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
256 { |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
257 object obj = this[key, false]; |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
258 bool val = false; |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
259 |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
260 if (obj is bool) |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
261 { |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
262 obj = (bool)obj; |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
263 } |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
264 |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
265 return val; |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
266 } |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
267 |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
268 public string GetStringProperty(string key) |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
269 { |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
270 object obj = this[key, false]; |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
271 string str = null; |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
272 |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
273 if (obj is String) |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
274 { |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
275 str = (String)obj; |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
276 } |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
277 |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
278 return str; |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
279 } |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
280 |
37 | 281 //public String |
282 | |
283 public bool IsModified() | |
284 { | |
285 return modified; | |
286 } | |
287 | |
288 public void Save() | |
289 { | |
290 if (htLocal.Count>0) | |
291 { | |
292 XmlDocument xmld = new XmlDocument(); | |
293 xmld.LoadXml("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>"+ | |
294 "<!DOCTYPE prefs["+ | |
295 "<!ELEMENT preferences (preferece*)> "+ | |
296 "<!ELEMENT preference (CDATA|prefsub)> "+ | |
297 "<!ELEMENT prefsub (CDATA)> "+ | |
298 "<!ATTLIST preference id ID #REQUIRED>"+ | |
299 "<!ATTLIST preference type CDATA #REQUIRED>"+ | |
300 "<!ATTLIST prefsub key CDATA #REQUIRED>"+ | |
301 "<!ATTLIST prefsub type CDATA #REQUIRED>"+ | |
302 "]>"+"<preferences></preferences>"); | |
303 XmlNode xmln = xmld.LastChild; | |
304 XmlNode pref; | |
305 XmlAttribute attr; | |
306 XmlNode prefSub; | |
307 XmlAttribute attrSub; | |
308 object o; | |
309 Hashtable htTemp; | |
310 Hashtable htGlobalTemp; | |
311 | |
312 foreach (string key in htLocal.Keys) | |
313 { | |
314 pref = xmld.CreateNode(XmlNodeType.Element, "preference",""); | |
315 attr = xmld.CreateAttribute("id"); | |
316 attr.Value = key; | |
317 pref.Attributes.Append(attr); | |
318 attr = xmld.CreateAttribute("type"); | |
319 o = htLocal[key]; | |
320 | |
321 attr.Value = o.GetType().AssemblyQualifiedName; | |
322 | |
323 if (o.GetType().ToString() == "System.Collections.Hashtable") | |
324 { | |
325 htTemp = (Hashtable)o; | |
326 htGlobalTemp = (Hashtable)htGlobal[key]; | |
327 | |
328 foreach(object subkey in htTemp.Keys) | |
329 { | |
330 if (!htGlobalTemp.ContainsKey(subkey) || !htGlobalTemp[subkey].Equals(htTemp[subkey])) | |
331 { | |
332 prefSub = xmld.CreateNode(XmlNodeType.Element, "prefsub", ""); | |
333 attrSub = xmld.CreateAttribute("key"); | |
334 attrSub.Value = subkey.ToString(); | |
335 prefSub.Attributes.Append(attrSub); | |
336 attrSub = xmld.CreateAttribute("type"); | |
337 attrSub.Value = htTemp[subkey].GetType().AssemblyQualifiedName; | |
338 prefSub.Attributes.Append(attrSub); | |
339 prefSub.InnerText = htTemp[subkey].ToString(); | |
340 pref.AppendChild(prefSub); | |
341 } | |
342 } | |
343 } | |
344 else | |
345 { | |
346 pref.InnerText = o.ToString(); | |
347 } | |
348 | |
349 pref.Attributes.Append(attr); | |
350 xmln.AppendChild(pref); | |
0
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
351 } |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
352 |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
353 if (!Directory.Exists(Constants.UserDataPath)) |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
354 { |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
355 Directory.CreateDirectory(Constants.UserDataPath); |
961030992bd2
Initial commit of IBBoard libraries
IBBoard <dev@ibboard.co.uk>
parents:
diff
changeset
|
356 } |
37 | 357 |
358 xmld.Save(Constants.UserDataPath + Constants.DirectoryString + "preferences.xml"); | |
359 } | |
360 else if (File.Exists(Constants.UserDataPath + Constants.DirectoryString + "preferences.xml")) | |
361 { | |
362 File.Delete(Constants.UserDataPath + Constants.DirectoryString + "preferences.xml"); | |
363 } | |
364 | |
365 modified = false; | |
366 } | |
367 } | |
368 } |