[gbrainy] Use Generics in preference class, extract storage in another class, and unit testing



commit 5b9fd3178450b185b6b8bdf1aa66e4d98922e6bf
Author: Jordi Mas <jmas softcatala org>
Date:   Sat Apr 2 15:54:56 2011 +0200

    Use Generics in preference class, extract storage in another class, and unit testing

 src/Clients/Classical/Dialogs/PdfExportDialog.cs   |    2 +-
 src/Clients/Classical/Dialogs/PreferencesDialog.cs |   34 ++--
 src/Clients/Classical/gbrainy.cs                   |   30 ++--
 src/Core/Core.csproj                               |    1 +
 src/Core/Main/CairoContextEx.cs                    |    4 +-
 src/Core/Main/Memory.cs                            |    4 +-
 src/Core/Main/PlayerHistory.cs                     |    4 +-
 src/Core/Main/Preferences.cs                       |  188 ++++++++------------
 src/Core/Main/PreferencesStorage.cs                |  107 +++++++++++
 src/Core/Makefile.am                               |    1 +
 tests/Clients/Classical/gbrainyTest.cs             |   19 +--
 tests/Core/PlayerHistoryTest.cs                    |    7 +-
 tests/Core/PlayerPersonalRecordTest.cs             |    5 +-
 tests/Makefile.am                                  |    4 +-
 tests/UnitTests.csproj                             |    1 +
 15 files changed, 239 insertions(+), 172 deletions(-)
---
diff --git a/src/Clients/Classical/Dialogs/PdfExportDialog.cs b/src/Clients/Classical/Dialogs/PdfExportDialog.cs
index a89f6d7..b78d113 100644
--- a/src/Clients/Classical/Dialogs/PdfExportDialog.cs
+++ b/src/Clients/Classical/Dialogs/PdfExportDialog.cs
@@ -50,7 +50,7 @@ namespace gbrainy.Clients.Classical.Dialogs
 			checkbox_logic.Active = checkbox_calculation.Active = checkbox_verbal.Active = true;
 
 			// Use defaults from Preferences
-		 	switch ((GameDifficulty) Preferences.GetIntValue (Preferences.DifficultyKey)) {
+		 	switch ((GameDifficulty) Preferences.Get <int> (Preferences.DifficultyKey)) {
 			case GameDifficulty.Easy:
 				rb_easy.Active = rb_easy.HasFocus = true;
 				break;
diff --git a/src/Clients/Classical/Dialogs/PreferencesDialog.cs b/src/Clients/Classical/Dialogs/PreferencesDialog.cs
index 03f7a5a..172abe3 100644
--- a/src/Clients/Classical/Dialogs/PreferencesDialog.cs
+++ b/src/Clients/Classical/Dialogs/PreferencesDialog.cs
@@ -44,14 +44,14 @@ namespace gbrainy.Clients.Classical.Dialogs
 		public PreferencesDialog (PlayerHistory history) : base ("PreferencesDialog.ui", "preferences")
 		{
 			this.history = history;
-			prefspinbutton.Value = Preferences.GetIntValue (Preferences.MemQuestionTimeKey);
-			prefcheckbutton.Active = Preferences.GetBoolValue (Preferences.MemQuestionWarnKey);
-			maxstoredspinbutton.Value = Preferences.GetIntValue (Preferences.MaxStoredGamesKey);
-			minplayedspinbutton.Value = Preferences.GetIntValue (Preferences.MinPlayedGamesKey);
-			colorblindcheckbutton.Active = Preferences.GetBoolValue (Preferences.ColorBlindKey);
-			english_checkbutton.Active = Preferences.GetBoolValue (Preferences.EnglishKey);
-
-			switch ((GameDifficulty) Preferences.GetIntValue (Preferences.DifficultyKey)) {
+			prefspinbutton.Value = Preferences.Get <int> (Preferences.MemQuestionTimeKey);
+			prefcheckbutton.Active = Preferences.Get <bool> (Preferences.MemQuestionWarnKey);
+			maxstoredspinbutton.Value = Preferences.Get <int> (Preferences.MaxStoredGamesKey);
+			minplayedspinbutton.Value = Preferences.Get <int> (Preferences.MinPlayedGamesKey);
+			colorblindcheckbutton.Active = Preferences.Get <bool> (Preferences.ColorBlindKey);
+			english_checkbutton.Active = Preferences.Get <bool> (Preferences.EnglishKey);
+
+			switch ((GameDifficulty) Preferences.Get <int> (Preferences.DifficultyKey)) {
 			case GameDifficulty.Easy:
 				rb_easy.Active = rb_easy.HasFocus = true;
 				break;
@@ -79,7 +79,7 @@ namespace gbrainy.Clients.Classical.Dialogs
 			{
 				Theme theme = (Theme) store.GetValue (iter, COLUMN_VALUE);
 
-				if (String.Compare (theme.Name, Preferences.GetStringValue (Preferences.ThemeKey), true) == 0)
+				if (String.Compare (theme.Name, Preferences.Get <string> (Preferences.ThemeKey), true) == 0)
 				{
 					themes_combobox.SetActiveIter (iter);
 					break;
@@ -116,18 +116,18 @@ namespace gbrainy.Clients.Classical.Dialogs
 
 		private void OnOK (object sender, EventArgs args)
 		{
-			Preferences.SetIntValue (Preferences.MemQuestionTimeKey, (int) prefspinbutton.Value);
-			Preferences.SetBoolValue (Preferences.MemQuestionWarnKey, prefcheckbutton.Active);
-			Preferences.SetIntValue (Preferences.DifficultyKey, (int) Difficulty);
-			Preferences.SetIntValue (Preferences.MaxStoredGamesKey, (int) maxstoredspinbutton.Value);
-			Preferences.SetIntValue (Preferences.MinPlayedGamesKey, (int) minplayedspinbutton.Value);
-			Preferences.SetBoolValue (Preferences.ColorBlindKey, colorblindcheckbutton.Active);
-			Preferences.SetBoolValue (Preferences.EnglishKey, english_checkbutton.Active);
+			Preferences.Set <int>  (Preferences.MemQuestionTimeKey, (int) prefspinbutton.Value);
+			Preferences.Set <bool> (Preferences.MemQuestionWarnKey, prefcheckbutton.Active);
+			Preferences.Set <int>  (Preferences.DifficultyKey, (int) Difficulty);
+			Preferences.Set <int>  (Preferences.MaxStoredGamesKey, (int) maxstoredspinbutton.Value);
+			Preferences.Set <int>  (Preferences.MinPlayedGamesKey, (int) minplayedspinbutton.Value);
+			Preferences.Set <bool> (Preferences.ColorBlindKey, colorblindcheckbutton.Active);
+			Preferences.Set <bool> (Preferences.EnglishKey, english_checkbutton.Active);
 
 			TreeIter iter;
 			themes_combobox.GetActiveIter (out iter);
 			Theme theme = (Theme) themes_combobox.Model.GetValue (iter, COLUMN_VALUE);
-			Preferences.SetStringValue (Preferences.ThemeKey, theme.Name);
+			Preferences.Set <string> (Preferences.ThemeKey, theme.Name);
 
 			Preferences.Save ();
 		}
diff --git a/src/Clients/Classical/gbrainy.cs b/src/Clients/Classical/gbrainy.cs
index 6678dea..2222508 100644
--- a/src/Clients/Classical/gbrainy.cs
+++ b/src/Clients/Classical/gbrainy.cs
@@ -87,7 +87,7 @@ namespace gbrainy.Clients.Classical
 		: base ("gbrainy", Defines.VERSION, Modules.UI, new string [0])
 #endif
 		{
-			if (Preferences.GetBoolValue (Preferences.EnglishKey) == false)
+			if (Preferences.Get <bool> (Preferences.EnglishKey) == false)
 			{
 				Catalog.Init ("gbrainy", Defines.GNOME_LOCALE_DIR);
 			}
@@ -110,11 +110,11 @@ namespace gbrainy.Clients.Classical
 			GameManagerPreload (session.GameManager);
 			Console.WriteLine (session.GameManager.GetGamesSummary ());
 
-			session.GameManager.ColorBlind = Preferences.GetBoolValue (Preferences.ColorBlindKey);
+			session.GameManager.ColorBlind = Preferences.Get <bool> (Preferences.ColorBlindKey);
 			session.DrawRequest += SessionDrawRequest;
 			session.UpdateUIElement += SessionUpdateUIElement;
 			session.SynchronizingObject = new GtkSynchronize ();
-			session.Difficulty = (GameDifficulty) Preferences.GetIntValue (Preferences.DifficultyKey);
+			session.Difficulty = (GameDifficulty) Preferences.Get <int> (Preferences.DifficultyKey);
 
 			BuildUI ();
 		}
@@ -134,11 +134,11 @@ namespace gbrainy.Clients.Classical
 			GtkBeans.Builder builder = new GtkBeans.Builder ("gbrainy.ui");
 			builder.Autoconnect (this);
 
-			show_toolbar = Preferences.GetBoolValue (Preferences.ToolbarShowKey) == true && low_res == false;
+			show_toolbar = Preferences.Get <bool> (Preferences.ToolbarShowKey) == true && low_res == false;
 
 			// Toolbar creation
 			toolbar = new Widgets.Toolbar (main_hbox, framework_vbox);
-			toolbar.Attach ((Gtk.Orientation) Preferences.GetIntValue (Preferences.ToolbarOrientationKey));
+			toolbar.Attach ((Gtk.Orientation) Preferences.Get <int> (Preferences.ToolbarOrientationKey));
 			toolbar.AllButton.Clicked += OnAllGames;
 			toolbar.LogicButton.Clicked += OnLogicOnly;
 			toolbar.CalculationButton.Clicked += OnMathOnly;
@@ -169,7 +169,7 @@ namespace gbrainy.Clients.Classical
 			eb.MotionNotifyEvent += OnMouseMotionEvent;
 			eb.ButtonPressEvent += OnHandleButtonPress;
 
-			show_toolbar = Preferences.GetBoolValue (Preferences.ToolbarShowKey) == true && low_res == false;
+			show_toolbar = Preferences.Get <bool> (Preferences.ToolbarShowKey) == true && low_res == false;
 
 			// We only disable the Arrow if we are going to show the toolbar.
 			// It has an impact on the total window width size even if we do not show it
@@ -495,7 +495,7 @@ namespace gbrainy.Clients.Classical
 		public bool ShowTranslationWarning ()
 		{
 			// Notify the user once per version only
-			if (String.Compare (Preferences.GetStringValue (Preferences.EnglishVersionKey), Defines.VERSION, 0) == 0)
+			if (String.Compare (Preferences.Get <string> (Preferences.EnglishVersionKey), Defines.VERSION, 0) == 0)
 				return false;
 
 			bool show;
@@ -504,7 +504,7 @@ namespace gbrainy.Clients.Classical
 
 			if (show == true)
 			{
-				Preferences.SetStringValue (Preferences.EnglishVersionKey, Defines.VERSION);
+				Preferences.Set <string> (Preferences.EnglishVersionKey, Defines.VERSION);
 				Preferences.Save ();
 			}
 			return show;
@@ -558,7 +558,7 @@ namespace gbrainy.Clients.Classical
 
 			dialog = new PreferencesDialog (session.PlayerHistory);
 			if ((Gtk.ResponseType) dialog.Run () == ResponseType.Ok) {
-				session.Difficulty = (GameDifficulty) Preferences.GetIntValue (Preferences.DifficultyKey);
+				session.Difficulty = (GameDifficulty) Preferences.Get <int> (Preferences.DifficultyKey);
 			}
 			dialog.Destroy ();
 		}
@@ -651,9 +651,9 @@ namespace gbrainy.Clients.Classical
 
 			toolbar_orientation_menuitem.Sensitive = toolbar.Visible;
 
-			if (Preferences.GetBoolValue (Preferences.ToolbarShowKey) != toolbar.Visible)
+			if (Preferences.Get <bool> (Preferences.ToolbarShowKey) != toolbar.Visible)
 			{
-				Preferences.SetBoolValue (Preferences.ToolbarShowKey, toolbar.Visible);
+				Preferences.Set <bool> (Preferences.ToolbarShowKey, toolbar.Visible);
 				Preferences.Save ();
 			}
 			app_window.Resize (width, height - requisition.Height);
@@ -666,9 +666,9 @@ namespace gbrainy.Clients.Classical
 
 			const Gtk.Orientation orientation = Gtk.Orientation.Vertical;
 
-			if ((Gtk.Orientation) Preferences.GetIntValue (Preferences.ToolbarOrientationKey) != orientation)
+			if ((Gtk.Orientation) Preferences.Get <int> (Preferences.ToolbarOrientationKey) != orientation)
 			{
-				Preferences.SetIntValue (Preferences.ToolbarOrientationKey, (int) orientation);
+				Preferences.Set <int> (Preferences.ToolbarOrientationKey, (int) orientation);
 				Preferences.Save ();
 			}
 			toolbar.Attach (orientation);
@@ -681,9 +681,9 @@ namespace gbrainy.Clients.Classical
 
 			const Gtk.Orientation orientation = Gtk.Orientation.Horizontal;
 
-			if ((Gtk.Orientation) Preferences.GetIntValue (Preferences.ToolbarOrientationKey) != orientation)
+			if ((Gtk.Orientation) Preferences.Get <int> (Preferences.ToolbarOrientationKey) != orientation)
 			{
-				Preferences.SetIntValue (Preferences.ToolbarOrientationKey, (int) Gtk.Orientation.Horizontal);
+				Preferences.Set <int>  (Preferences.ToolbarOrientationKey, (int) Gtk.Orientation.Horizontal);
 				Preferences.Save ();
 			}
 			toolbar.Attach (orientation);
diff --git a/src/Core/Core.csproj b/src/Core/Core.csproj
index 1c6aff5..556b8f0 100644
--- a/src/Core/Core.csproj
+++ b/src/Core/Core.csproj
@@ -117,6 +117,7 @@
     <Compile Include="Libraries\CSharpCompiler.cs" />
     <Compile Include="Services\DefaultServices.cs" />
     <Compile Include="Services\ICSharpCompiler.cs" />
+    <Compile Include="Main\PreferencesStorage.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ProjectExtensions>
diff --git a/src/Core/Main/CairoContextEx.cs b/src/Core/Main/CairoContextEx.cs
index 3ca7302..d8f9fed 100644
--- a/src/Core/Main/CairoContextEx.cs
+++ b/src/Core/Main/CairoContextEx.cs
@@ -44,7 +44,7 @@ namespace gbrainy.Core.Main
 		{
 			Theme theme;
 	
-			theme = ThemeManager.FromName (Preferences.GetStringValue (Preferences.ThemeKey));
+			theme = ThemeManager.FromName (Preferences.Get <string> (Preferences.ThemeKey));
 			FontFace = theme.FontFace;
 
 			SetPangoNormalFontSize ();
@@ -57,7 +57,7 @@ namespace gbrainy.Core.Main
 				{
 					Theme theme;
 	
-					theme = ThemeManager.FromName (Preferences.GetStringValue (Preferences.ThemeKey));
+					theme = ThemeManager.FromName (Preferences.Get <string> (Preferences.ThemeKey));
 					image = new SVGImage (System.IO.Path.Combine (Defines.DATA_DIR, theme.BackgroundImage));
 				}
 
diff --git a/src/Core/Main/Memory.cs b/src/Core/Main/Memory.cs
index 8e1c521..ba7db50 100644
--- a/src/Core/Main/Memory.cs
+++ b/src/Core/Main/Memory.cs
@@ -68,7 +68,7 @@ namespace gbrainy.Core.Main
 
 		protected override void Initialize ()
 		{
-			if (Preferences.GetBoolValue (Preferences.MemQuestionWarnKey) == false || 
+			if (Preferences.Get <bool> (Preferences.MemQuestionWarnKey) == false || 
 				IsPreviewMode == true) {
 				InitializeGame ();
 				return;
@@ -109,7 +109,7 @@ namespace gbrainy.Core.Main
 			alpha = 1;
 			draw_timer = false;
 
-			time_left = total_time = Preferences.GetIntValue (Preferences.MemQuestionTimeKey) * 10; // Seconds
+			time_left = total_time = Preferences.Get <int> (Preferences.MemQuestionTimeKey) * 10; // Seconds
 
 			StartTimer ();
 		}
diff --git a/src/Core/Main/PlayerHistory.cs b/src/Core/Main/PlayerHistory.cs
index e5c47a3..665f0a1 100644
--- a/src/Core/Main/PlayerHistory.cs
+++ b/src/Core/Main/PlayerHistory.cs
@@ -65,12 +65,12 @@ namespace gbrainy.Core.Main
 
 		public void SaveGameSession (GameSessionHistory score)
 		{
-			if (score.GamesPlayed < Preferences.GetIntValue (Preferences.MinPlayedGamesKey)) {
+			if (score.GamesPlayed < Preferences.Get <int> (Preferences.MinPlayedGamesKey)) {
 				last_game = -1;
 				return;
 			}
 
-			if (Games.Count >= Preferences.GetIntValue (Preferences.MaxStoredGamesKey))
+			if (Games.Count >= Preferences.Get <int> (Preferences.MaxStoredGamesKey))
 				Games.RemoveAt (0);
 
 			// Storing a copy to allow the input object to be modified
diff --git a/src/Core/Main/Preferences.cs b/src/Core/Main/Preferences.cs
index 20bb4e3..9e1723a 100644
--- a/src/Core/Main/Preferences.cs
+++ b/src/Core/Main/Preferences.cs
@@ -23,13 +23,15 @@ using System.IO;
 using System.Xml;
 using System.Xml.Serialization;
 using System.Text;
+using System.ComponentModel;
 
 namespace gbrainy.Core.Main
 {
 	public static class Preferences
 	{
 		static string file, config_path;
-		static SerializableDictionary <string, string > properties;
+		static PreferencesStorage <string, string> storage;
+		static Dictionary <string, string> defaults;
 
 		public const string MemQuestionWarnKey = "MemQuestionWarn";
 		public const string MemQuestionTimeKey = "MemQuestionTime";
@@ -43,82 +45,22 @@ namespace gbrainy.Core.Main
 		public const string EnglishKey = "English";
 		public const string EnglishVersionKey = "EnglishVersion";
 
-		const string element_item = "item";
-		const string element_key = "key";
-		const string element_value = "value";
-		const string element_collection = "collection";
-
-	    	public class SerializableDictionary <TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
+		static Preferences ()
 		{
-			public System.Xml.Schema.XmlSchema GetSchema ()
-			{
-				return null;
-			}
-
-			public void ReadXml (System.Xml.XmlReader reader)
-			{
-				XmlSerializer key_serializer = new XmlSerializer (typeof (TKey));
-				XmlSerializer value_serializer = new XmlSerializer (typeof (TValue));
-		 		bool wasEmpty = reader.IsEmptyElement;
-
-			    	reader.Read ();
-
-				if (wasEmpty)
-					return;
-			
-				reader.ReadStartElement (element_collection);
-				while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
-				{
-					reader.ReadStartElement (element_item);
-
-					reader.ReadStartElement (element_key);
-					TKey key = (TKey) key_serializer.Deserialize (reader);
-					reader.ReadEndElement ();
+			storage = new PreferencesStorage <string, string> ();
+			defaults = new Dictionary <string, string> ();
+			ConfigPath = Path.Combine (Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData),
+				 Defines.CONFIG_DIR);
 
-					reader.ReadStartElement (element_value);
-					TValue value = (TValue) value_serializer.Deserialize (reader);
-					reader.ReadEndElement();
-
-					this[key] = value; // already created in DefaultValues
-					reader.ReadEndElement();
-
-					reader.MoveToContent();
-				}
-				reader.ReadEndElement();
-			}
+			LoadDefaultValues ();
+			Load ();
+		}
 
-			public void WriteXml (System.Xml.XmlWriter writer)
-			{
-				XmlSerializer key_serializer = new XmlSerializer (typeof(TKey));
-				XmlSerializer value_serializer = new XmlSerializer (typeof(TValue));
-
-				writer.WriteStartElement (element_collection);
-				foreach (TKey key in this.Keys)
-				{
-					writer.WriteStartElement (element_item);
-					writer.WriteStartElement (element_key);
-
-					key_serializer.Serialize (writer, key);
-					writer.WriteEndElement ();
-					writer.WriteStartElement (element_value);
-
-					TValue value = this[key];
-					value_serializer.Serialize (writer, value);
-					writer.WriteEndElement ();
-					writer.WriteEndElement ();
-				}
-				writer.WriteEndElement ();
+		static public string ConfigPath {
+			set {
+				config_path = value;
+				file = Path.Combine (config_path, "Preferences.xml");
 			}
-
-	    	}
-
-		static Preferences ()
-		{
-			properties = new SerializableDictionary <string, string> ();
-			config_path = Environment.GetFolderPath (Environment.SpecialFolder.ApplicationData);
-			config_path = Path.Combine (config_path, Defines.CONFIG_DIR);
-			file = Path.Combine (config_path, "Preferences.xml");
-			Load ();
 		}
 
 		public static void Save ()
@@ -130,77 +72,97 @@ namespace gbrainy.Core.Main
 				XmlTextWriter writer = new XmlTextWriter (file, Encoding.UTF8);
 				writer.Formatting = Formatting.Indented;
 
-				properties.WriteXml (writer);
+				storage.WriteXml (writer);
 				writer.Close ();
-			}		
+			}
 			catch (Exception e)
 			{
 				Console.WriteLine ("Preferences.Save. Could not save file {0}. Error {1}", file, e);
 			}
 		}
-	
-		public static int GetIntValue (string key)
-		{
-			return Int32.Parse (properties [key]);
-		}
 
-		public static bool GetBoolValue (string key)
-		{
-			return Boolean.Parse (properties [key]);
-		}
 
-		public static string GetStringValue (string key)
+		public static T Get<T> (string key)
 		{
-			return properties [key];
-		}
+			string val;
 
-		public static void SetIntValue (string key, int value)
-		{
-			properties[key] = value.ToString ();
+			if (storage.TryGetValue (key, out val) == true)
+			{
+				return storage.Convert <T> (val);
+			}
+			return storage.Convert <T> (defaults [key]);
 		}
 
-		public static void SetBoolValue (string key, bool value)
+		public static void Set<T> (string key, object val)
 		{
-			properties [key] = value.ToString ();
+			string v;
+			T current;
+			
+			if (val is string)
+				v = (string) val;
+			else
+				v = val.ToString ();
+
+			current = Get <T> (key);
+
+			// It is the same that the current stored
+			if (current.Equals (val))
+				return;
+
+			// The new setting is equal to default
+			if (v.Equals (defaults[key]) == true)
+			{
+				// Remove any previous value if existed
+				storage.Remove (key);
+				return;
+			}
+
+			storage [key] = v;
 		}
 
-		public static void SetStringValue (string key, string value)
+		static public void Clear ()
 		{
-			properties [key] = value;
+			storage.Clear ();
 		}
 
-		public static void LoadDefaultValues ()
+		static void LoadDefaultValues ()
 		{
-			properties.Clear ();
-			properties.Add (MemQuestionWarnKey, true.ToString ());
-			properties.Add (MemQuestionTimeKey, "6");
-			properties.Add (DifficultyKey, ((int)(GameDifficulty.Medium)).ToString ());
-			properties.Add (MinPlayedGamesKey, "5");
-			properties.Add (MaxStoredGamesKey, "20");
-			properties.Add (ToolbarShowKey, true.ToString ());
-			properties.Add (ToolbarOrientationKey, "0");
-			properties.Add (ColorBlindKey, false.ToString ());
-			properties.Add (ThemeKey, "classic");
-			properties.Add (EnglishVersionKey, string.Empty);
-			properties.Add (EnglishKey, false.ToString ());
+			if (defaults.Count > 0)
+				throw new InvalidOperationException ("The defaults should only be loaded once");
+
+			defaults.Add (MemQuestionWarnKey, true.ToString ());
+			defaults.Add (MemQuestionTimeKey, "6");
+			defaults.Add (DifficultyKey, ((int)(GameDifficulty.Medium)).ToString ());
+			defaults.Add (MinPlayedGamesKey, "5");
+			defaults.Add (MaxStoredGamesKey, "20");
+			defaults.Add (ToolbarShowKey, true.ToString ());
+			defaults.Add (ToolbarOrientationKey, "0");
+			defaults.Add (ColorBlindKey, false.ToString ());
+			defaults.Add (ThemeKey, "classic");
+			defaults.Add (EnglishVersionKey, string.Empty);
+			defaults.Add (EnglishKey, false.ToString ());
 		}
 
-		static void Load ()
+		public static void Load ()
 		{
+			XmlTextReader reader = null;
+
 			try {
-				LoadDefaultValues ();
-				
 				if (File.Exists (file) == false)
 					return;
 
-				XmlTextReader reader = new XmlTextReader (file);
-				properties.ReadXml (reader);
-				reader.Close ();
+				reader = new XmlTextReader (file);
+				storage.ReadXml (reader);
 			}
 			catch (Exception e)
 			{
 				Console.WriteLine ("Preferences.Load. Could not load file {0}. Error {1}", file, e);
 			}
+			finally
+			{
+				if (reader != null)
+					reader.Close ();
+			}
 		}
 	}
 }
diff --git a/src/Core/Main/PreferencesStorage.cs b/src/Core/Main/PreferencesStorage.cs
new file mode 100644
index 0000000..f7ab10f
--- /dev/null
+++ b/src/Core/Main/PreferencesStorage.cs
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2008-2011 Jordi Mas i Hernàndez <jmas softcatala org>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+using System.Xml.Serialization;
+using System.Text;
+using System.ComponentModel;
+
+namespace gbrainy.Core.Main
+{
+   	internal class PreferencesStorage <TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
+	{
+		const string element_item = "item";
+		const string element_key = "key";
+		const string element_value = "value";
+		const string element_collection = "collection";
+
+		public System.Xml.Schema.XmlSchema GetSchema ()
+		{
+			return null;
+		}
+
+		public void ReadXml (System.Xml.XmlReader reader)
+		{
+			XmlSerializer key_serializer = new XmlSerializer (typeof (TKey));
+			XmlSerializer value_serializer = new XmlSerializer (typeof (string));
+	 		bool wasEmpty = reader.IsEmptyElement;
+
+		    	reader.Read ();
+
+			if (wasEmpty)
+				return;
+
+			reader.ReadStartElement (element_collection);
+			while (reader.NodeType != System.Xml.XmlNodeType.EndElement && reader.NodeType != System.Xml.XmlNodeType.None)
+			{
+				reader.ReadStartElement (element_item);
+				reader.ReadStartElement (element_key);
+				TKey key = (TKey) key_serializer.Deserialize (reader);
+				reader.ReadEndElement ();
+
+				reader.ReadStartElement (element_value);
+				TValue val = (TValue) value_serializer.Deserialize (reader);
+				reader.ReadEndElement();
+
+				this[key] = val; // already created in DefaultValues
+				reader.ReadEndElement();
+
+				reader.MoveToContent();
+			}
+		}
+
+		public void WriteXml (System.Xml.XmlWriter writer)
+		{
+			XmlSerializer key_serializer = new XmlSerializer (typeof(TKey));
+			XmlSerializer value_serializer = new XmlSerializer (typeof(TValue));
+
+			writer.WriteStartElement (element_collection);
+
+			foreach (TKey key in Keys)
+			{
+				writer.WriteStartElement (element_item);
+				writer.WriteStartElement (element_key);
+
+				key_serializer.Serialize (writer, key);
+				writer.WriteEndElement ();
+				writer.WriteStartElement (element_value);
+
+				TValue val = this[key];
+				value_serializer.Serialize (writer, val);
+				writer.WriteEndElement ();
+				writer.WriteEndElement ();
+			}
+			writer.WriteEndElement ();
+		}
+
+		public T Convert<T> (string o)
+		{
+			TypeConverter converter = TypeDescriptor.GetConverter (typeof (T));
+
+			try {
+				return (T)converter.ConvertFromInvariantString (o.ToString ());
+			} catch (Exception) {
+				return default (T);
+			}
+		}
+    	}
+}
diff --git a/src/Core/Makefile.am b/src/Core/Makefile.am
index e7258a2..fb0cb29 100644
--- a/src/Core/Makefile.am
+++ b/src/Core/Makefile.am
@@ -36,6 +36,7 @@ CSDISTFILES =  \
 		$(srcdir)/Main/PlayerHistory.cs		\
 		$(srcdir)/Main/PlayerPersonalRecord.cs	\
 		$(srcdir)/Main/Preferences.cs		\
+		$(srcdir)/Main/PreferencesStorage.cs	\
 		$(srcdir)/Main/Score.cs			\
 		$(srcdir)/Main/Theme.cs			\
 		$(srcdir)/Main/ThemeManager.cs		\
diff --git a/tests/Clients/Classical/gbrainyTest.cs b/tests/Clients/Classical/gbrainyTest.cs
index c52fa0f..57af614 100644
--- a/tests/Clients/Classical/gbrainyTest.cs
+++ b/tests/Clients/Classical/gbrainyTest.cs
@@ -50,17 +50,14 @@ namespace gbrainyTest
 			RegisterDefaultServices ();
 			translations =  new TranslationsTest ();
 			ServiceLocator.Instance.RegisterService (typeof (ITranslations), translations);
-
-
 		}
 
 		[Test]
 		public void ShowTranslationMessageHonorPercentage ()
 		{
 			GtkClient client = new GtkClient ();
-
-			// Ignore gbrainy instance preferences
-			Preferences.LoadDefaultValues ();
+			Preferences.ConfigPath = ".";
+			Preferences.Clear ();
 
 			translations.Percentage = client.MIN_TRANSLATION;
 			Assert.AreEqual (false, client.ShowTranslationWarning ());
@@ -70,9 +67,8 @@ namespace gbrainyTest
 		public void ShowTranslationMessageOnlyOnce ()
 		{
 			GtkClient client = new GtkClient ();
-
-			// Ignore gbrainy instance preferences
-			Preferences.LoadDefaultValues ();
+			Preferences.ConfigPath = ".";
+			Preferences.Clear ();
 
 			translations.Percentage = client.MIN_TRANSLATION - 1;
 			Assert.AreEqual (true, client.ShowTranslationWarning ());
@@ -83,13 +79,12 @@ namespace gbrainyTest
 		public void ShowTranslationMessageWhenChangingVersion ()
 		{
 			GtkClient client = new GtkClient ();
-
-			// Ignore gbrainy instance preferences
-			Preferences.LoadDefaultValues ();
+			Preferences.ConfigPath = ".";
+			Preferences.Clear ();
 
 			translations.Percentage = client.MIN_TRANSLATION - 1;
 			Assert.AreEqual (true, client.ShowTranslationWarning ());
-			Preferences.SetStringValue (Preferences.EnglishVersionKey, "n.n.n");
+			Preferences.Set <string> (Preferences.EnglishVersionKey, "n.n.n");
 			Assert.AreEqual (true, client.ShowTranslationWarning ());
 		}
 	}
diff --git a/tests/Core/PlayerHistoryTest.cs b/tests/Core/PlayerHistoryTest.cs
index 104a1f1..3dd670c 100644
--- a/tests/Core/PlayerHistoryTest.cs
+++ b/tests/Core/PlayerHistoryTest.cs
@@ -34,15 +34,14 @@ namespace gbrainyTest
 		public void Construct ()
 		{
 			RegisterDefaultServices ();
-			// Ignore gbrainy instance preferences
-			Preferences.LoadDefaultValues ();
+			Preferences.Clear ();
 		}
 
 		[Test]
 		public void Clean ()
 		{
 			GameSessionHistory game = new GameSessionHistory ();
-			game.GamesPlayed = Preferences.GetIntValue (Preferences.MinPlayedGamesKey);
+			game.GamesPlayed = Preferences.Get <int> (Preferences.MinPlayedGamesKey);
 
 			history = new PlayerHistory ();
 			history.ConfigPath = ".";
@@ -58,7 +57,7 @@ namespace gbrainyTest
 		public void SaveLoad ()
 		{
 			GameSessionHistory game = new GameSessionHistory ();
-			game.GamesPlayed = Preferences.GetIntValue (Preferences.MinPlayedGamesKey);
+			game.GamesPlayed = Preferences.Get <int> (Preferences.MinPlayedGamesKey);
 			game.MemoryScore = 20;
 
 			history = new PlayerHistory ();
diff --git a/tests/Core/PlayerPersonalRecordTest.cs b/tests/Core/PlayerPersonalRecordTest.cs
index aca384c..cc7b926 100644
--- a/tests/Core/PlayerPersonalRecordTest.cs
+++ b/tests/Core/PlayerPersonalRecordTest.cs
@@ -32,8 +32,7 @@ namespace gbrainyTest
 		public void Construct ()
 		{
 			RegisterDefaultServices ();
-			// Ignore gbrainy instance preferences
-			Preferences.LoadDefaultValues ();
+			Preferences.Clear ();
 		}
 
 		[Test]
@@ -42,7 +41,7 @@ namespace gbrainyTest
 			PlayerHistory history;
 
 			GameSessionHistory game = new GameSessionHistory ();
-			game.GamesPlayed = Preferences.GetIntValue (Preferences.MinPlayedGamesKey);
+			game.GamesPlayed = Preferences.Get <int> (Preferences.MinPlayedGamesKey);
 
 			history = new PlayerHistory ();
 			history.ConfigPath = ".";
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 965f181..52defa9 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -15,7 +15,8 @@ CSFILES_CORE =					\
 	$(srcdir)/Core/GameSessionTest.cs \
 	$(srcdir)/Core/GameManagerTest.cs \
 	$(srcdir)/Core/GameAnswerTest.cs \
-	$(srcdir)/Core/GameXmlFactoryTest.cs
+	$(srcdir)/Core/GameXmlFactoryTest.cs \
+	$(srcdir)/Core/PreferencesTest.cs
 
 CSFILES_CLASSICAL =					\
 	$(srcdir)/TestSupport/UnitTestSupport.cs \
@@ -71,6 +72,7 @@ CLEANFILES = 				\
 	gbrainy.exe			\
 	gbrainy.Games.dll		\
 	PlayerHistory.xml		\
+	Preferences.xml			\
 	TestResult.xml
 
 
diff --git a/tests/UnitTests.csproj b/tests/UnitTests.csproj
index abeeeda..35c19f2 100644
--- a/tests/UnitTests.csproj
+++ b/tests/UnitTests.csproj
@@ -52,6 +52,7 @@
     <Compile Include="TestSupport\UnitTestSupport.cs" />
     <Compile Include="Core\GameAnswerTest.cs" />
     <Compile Include="Clients\Classical\gbrainyTest.cs" />
+    <Compile Include="Core\PreferencesTest.cs" />
   </ItemGroup>
   <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
   <ProjectExtensions>



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]