crashanalysercmd/PerfToolsSharedLibraries/Engine/SymbianUtils/Settings/XmlSettings.cs
author Matti Laitinen <matti.t.laitinen@nokia.com>
Thu, 11 Feb 2010 15:50:58 +0200
changeset 0 818e61de6cd1
permissions -rw-r--r--
Add initial version of Crash Analyser cmdline under EPL

/*
* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
* 
* Description:
*
*/
using System;
using System.Xml;
using System.Text;
using System.IO;
using System.Collections.Generic;
using System.Diagnostics;
using System.Collections;
using System.Windows.Forms;
using System.Drawing;
using Microsoft.Win32;

namespace SymbianUtils.Settings
{
	public class XmlSettings : IEnumerable<XmlSettingCategory>
	{
		#region Constructors
		public XmlSettings( string aFileName )
		{
			FullyQualifiedFileName = aFileName;
		}
		#endregion

		#region Store & Restore API
		public void Restore()
		{
			string file = FullyQualifiedFileName;
			if (System.IO.File.Exists(file))
			{
				XmlTextReader reader = new XmlTextReader(file);
				try
				{
					reader.WhitespaceHandling = WhitespaceHandling.None;
					reader.MoveToContent();
					ReadData(reader);
				}
				catch (XmlException)
				{
					// Ignore for now
				}
				finally
				{
					reader.Close();
				}
			}
		}

		public void Store()
		{
			string file = FullyQualifiedFileName;
			XmlTextWriter writer = new XmlTextWriter(file, System.Text.Encoding.UTF8);
			try
			{
				writer.Formatting = Formatting.Indented;
				WriteData(writer);
			}
			catch (XmlException)
			{
				// Ignore for now
			}
			finally
			{
				writer.Close();
			}
		}
		#endregion

		#region API
        public void Clear()
        {
            iCategories.Clear();
        }

        public void Add( XmlSettingCategory aCategory )
        {
            iCategories.Add( aCategory.Name, aCategory );
        }

		public bool Exists( string aCategory )
		{
            return iCategories.ContainsKey( aCategory );
		}

        public bool Exists( string aCategory, string aKey )
        {
            bool ret = false;
            //
            if ( Exists( aCategory ) )
            {
                XmlSettingCategory category = this[ aCategory ];
                ret = category.Exists( aKey );
            }
            //
            return ret;
        }

		public void Remove( string aCategory )
		{
            if ( Exists( aCategory ) )
            {
                iCategories.Remove( aCategory );
			}
		}

		public void Remove( string aCategory, string aKey )
		{
            if ( Exists( aCategory ) )
            {
                XmlSettingCategory category = this[ aCategory ];
                category.Remove( aKey );
            }
		}
        #endregion

        #region Loading & Saving
        public void Save( string aCategory, object aObject )
        {
            if ( aObject is TextBox )
            {
                DoSave( aCategory, aObject as TextBox );
            }
            else if ( aObject is RadioButton )
            {
                DoSave( aCategory, aObject as RadioButton );
            }
            else if ( aObject is CheckBox )
            {
                DoSave( aCategory, aObject as CheckBox );
            }
            else if ( aObject is ComboBox )
            {
                DoSave( aCategory, aObject as ComboBox );
            }
            else if ( aObject is IXmlSettingsSimple )
            {
                DoSave( aCategory, aObject as IXmlSettingsSimple );
            }
            else if ( aObject is IXmlSettingsExtended )
            {
                DoSave( aCategory, aObject as IXmlSettingsExtended );
            }
            else if ( aObject is Form )
            {
                DoSave( aCategory, aObject as Form );
            }
        }

        public void Load( string aCategory, object aObject )
        {
            if ( aObject is TextBox )
            {
                DoLoad( aCategory, aObject as TextBox );
            }
            else if ( aObject is RadioButton )
            {
                DoLoad( aCategory, aObject as RadioButton );
            }
            else if ( aObject is CheckBox )
            {
                DoLoad( aCategory, aObject as CheckBox );
            }
            else if ( aObject is ComboBox )
            {
                DoLoad( aCategory, aObject as ComboBox );
            }
            else if ( aObject is IXmlSettingsSimple )
            {
                DoLoad( aCategory, aObject as IXmlSettingsSimple );
            }
            else if ( aObject is IXmlSettingsExtended )
            {
                DoLoad( aCategory, aObject as IXmlSettingsExtended );
            }
            else if ( aObject is Form )
            {
                DoLoad( aCategory, aObject as Form );
            }
        }

        #region Basic types
        public void Save( string aCategory, string aName, int aValue )
        {
            this[ aCategory, aName ] = aValue;
        }

        public void Save( string aCategory, string aName, uint aValue )
        {
            this[ aCategory, aName ] = aValue;
        }

        public void Save( string aCategory, string aName, long aValue )
        {
            this[ aCategory, aName ] = aValue;
        }

        public void Save( string aCategory, string aName, bool aValue )
        {
            this[ aCategory, aName ] = aValue;
        }

        public void Save( string aCategory, string aName, string aValue )
        {
            this[ aCategory, aName ] = aValue;
        }

        public void Save( string aCategory, string aName, object aValue )
        {
            this[ aCategory, aName ].Value = aValue;
        }

        public void Save( string aCategory, string aName, Point aValue )
        {
            this[ aCategory, aName ].Value = string.Format( "{0},{1}", aValue.X, aValue.Y );
        }

        public void Save( string aCategory, string aName, Size aValue )
        {
            this[ aCategory, aName ].Value = string.Format( "{0},{1}", aValue.Width, aValue.Height );
        }

        public int LoadInt( string aCategory, string aName )
        {
            return Load( aCategory, aName, 0 );
        }

        public int Load( string aCategory, string aName, int aDefault )
        {
            int ret = aDefault;
            if ( Exists( aCategory, aName ) )
            {
                ret = this[ aCategory, aName ];
            }
            return ret;
        }

        public uint LoadUint( string aCategory, string aName )
        {
            return Load( aCategory, aName, 0U );
        }

        public uint Load( string aCategory, string aName, uint aDefault )
        {
            uint ret = aDefault;
            if ( Exists( aCategory, aName ) )
            {
                ret = this[ aCategory, aName ];
            }
            return ret;
        }

        public long LoadLong( string aCategory, string aName )
        {
            return Load( aCategory, aName, 0L );
        }

        public long Load( string aCategory, string aName, long aDefault )
        {
            long ret = aDefault;
            if ( Exists( aCategory, aName ) )
            {
                ret = this[ aCategory, aName ];
            }
            return ret;
        }

        public bool LoadBool( string aCategory, string aName )
        {
            return Load( aCategory, aName, false );
        }

        public bool Load( string aCategory, string aName, bool aDefault )
        {
            bool ret = aDefault;
            if ( Exists( aCategory, aName ) )
            {
                ret = this[ aCategory, aName ];
            }
            return ret;
        }

        public string Load( string aCategory, string aName )
        {
            return Load( aCategory, aName, string.Empty );
        }

        public string Load( string aCategory, string aName, string aDefault )
        {
            string ret = aDefault;
            if ( Exists( aCategory, aName ) )
            {
                ret = this[ aCategory, aName ];
            }
            return ret;
        }

        public object LoadObject( string aCategory, string aName )
        {
            return Load( aCategory, aName, null );
        }

        public object Load( string aCategory, string aName, object aDefault )
        {
            object ret = aDefault;
            if ( Exists( aCategory, aName ) )
            {
                ret = this[ aCategory, aName ].Value;
            }
            return ret;
        }

        public Point Load( string aCategory, string aName, Point aDefault )
        {
            Point ret = aDefault;
            if ( Exists( aCategory, aName ) )
            {
                ret = this[ aCategory, aName ];
            }
            return ret;
        }

        public Size Load( string aCategory, string aName, Size aDefault )
        {
            Size ret = aDefault;
            if ( Exists( aCategory, aName ) )
            {
                ret = this[ aCategory, aName ];
            }
            return ret;
        }
        #endregion

        #endregion

		#region Properties
        public int Count
        {
            get { return iCategories.Count; }
        }

		public string FileName
		{
			get
			{
				FileInfo info = new FileInfo(FullyQualifiedFileName);
				return info.Name;
			}
			set
			{
				FileInfo newNameInfo = new FileInfo(value);
				FileInfo fullNameInfo = new FileInfo(FullyQualifiedFileName);
				string fileName = fullNameInfo.DirectoryName;
				fileName += newNameInfo.Name;
				FullyQualifiedFileName = fileName;
			}
		}

		public string FullyQualifiedFileName
		{
			get { return iFullyQualifiedFileName; }
			set
			{
				string path = string.Empty;
				try
				{
					path = Path.GetDirectoryName(value);

				}
				catch(ArgumentException)
				{
				}

				if	(path == null || path.Length == 0)
				{
					// Get the path from the current app domain
					iFullyQualifiedFileName = Path.Combine(System.Windows.Forms.Application.StartupPath, Path.GetFileName(value));
				}
				else
				{
					iFullyQualifiedFileName = value; 
				}
			}
		}

		public static Version CurrentSettingsVersion
		{
			get { return iCurrentSettingsVersion; }
		}
		#endregion

        #region From IEnumerable<XmlSettingCategory>
        public IEnumerator<XmlSettingCategory> GetEnumerator()
        {
            foreach ( KeyValuePair<string, XmlSettingCategory> pair in iCategories )
            {
                yield return pair.Value;
            }
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            foreach ( KeyValuePair<string, XmlSettingCategory> pair in iCategories )
            {
                yield return pair.Value;
            }
        }
        #endregion

		#region Indexers
        public XmlSettingCategory this[ int aIndex ]
        {
            get
            {
                string key = iCategories.Keys[ aIndex ];
                return iCategories[ key ];
            }
        }

        public XmlSettingCategory this[ string aCategory ]
        {
            get
            {
                XmlSettingCategory ret = new XmlSettingCategory( aCategory );
                if ( Exists( aCategory ) )
                {
                    ret = iCategories[ aCategory ];
                }
                else
                {
                    iCategories.Add( aCategory, ret );
                }
                //
                return ret;
            }
        }
        
		public XmlSettingsValue this[ string aCategory, string aKey ]
		{
			get
			{
                XmlSettingCategory category = this[ aCategory ];
                XmlSettingsValue value = category[ aKey ];
                return value;
            }
			set
			{
                XmlSettingCategory category = this[ aCategory ];
                category[ aKey ] = value;
			}
		}

        public XmlSettingsValue this[ string aCategory, object aObject ]
        {
            get
            {
                string key = aObject.ToString();
                if ( aObject is System.Windows.Forms.Control )
                {
                    key = ( aObject as Control ).Name;
                }
                return this[ aCategory, key ];
            }
            set
            {
                string key = aObject.ToString();
                if ( aObject is System.Windows.Forms.Control )
                {
                    key = ( aObject as Control ).Name;
                }
                this[ aCategory, key ] = value;
            }
        }
		#endregion

        #region Internal write helpers
        private void WriteData(XmlWriter aWriter)
		{
			aWriter.WriteStartElement( null, "configuration", null );
            //
			WriteConfigSections( aWriter );
			WriteSectionItems( aWriter );
            //
			aWriter.WriteEndElement();
		}

		private void WriteConfigSections(XmlWriter aWriter)
		{
			aWriter.WriteStartElement( null, "configSections", null );
			//
            foreach( XmlSettingCategory cat in this )
			{
				aWriter.WriteStartElement("section", null);
				aWriter.WriteAttributeString("name", cat.Name);
				aWriter.WriteAttributeString("version", cat.Version.ToString());
				aWriter.WriteRaw(" ");
				aWriter.WriteEndElement();
			}
            //
			aWriter.WriteEndElement();
		}

		private void WriteSectionItems(XmlWriter aWriter)
		{
			aWriter.WriteStartElement(null, "sectionItems", null);
            //
            foreach ( XmlSettingCategory cat in this )
			{
				cat.WriteSettings( aWriter );
			}
            //
			aWriter.WriteEndElement();
		}
		#endregion

		#region Internal read helpers
		private void ReadData(XmlReader aReader)
		{
			aReader.ReadStartElement("configuration");
			//
			ReadConfigSections( aReader );
			ReadSectionItems( aReader );
			//
			aReader.ReadEndElement(); // configuration
		}

		private void ReadConfigSections(XmlReader aReader)
		{
			aReader.ReadStartElement("configSections");
			//
			while (!aReader.EOF && aReader.Name == "section")
			{
				if (aReader.NodeType != XmlNodeType.EndElement)
				{
                    XmlSettingCategory category = new XmlSettingCategory( aReader );
                    iCategories.Add( category.Name, category );
				}
				aReader.Read();
			}
            //
			aReader.ReadEndElement(); // configSections
		}

		private void ReadSingleSection( XmlReader aReader )
		{
			string sectionName = aReader.Name;

			// Advance to first section key & pair
            if ( aReader.IsEmptyElement )
            {
                // It's empty - doesn't contain any content
            }
            else
            {
                bool readOkay = aReader.Read();

                // Search for the existing section definition
                if ( readOkay && Exists( sectionName ) )
                {
                    XmlSettingCategory cat = this[ sectionName ];
                    cat.ReadSettings( aReader );
                }
            }
		}

		private void ReadSectionItems(XmlReader aReader)
		{
			aReader.ReadStartElement( "sectionItems" );
            //
            while ( !aReader.EOF && !( aReader.NodeType == XmlNodeType.EndElement && aReader.Name == "sectionItems" ) )
			{
				ReadSingleSection( aReader );
				aReader.Read();
			}
            //
			aReader.ReadEndElement(); // sectionItems
		}
		#endregion

        #region Internal settings savers
        private void DoSave( string aCategory, IXmlSettingsSimple aObject )
        {
            string name = aObject.XmlSettingsPersistableName;
            string value = aObject.XmlSettingPersistableValue;
            this[ aCategory, name ] = value;
        }

        private void DoLoad( string aCategory, IXmlSettingsSimple aObject )
        {
            string name = aObject.XmlSettingsPersistableName;
            string value = this[ aCategory, name ];
            aObject.XmlSettingPersistableValue = value;
        }

        private void DoSave( string aCategory, IXmlSettingsExtended aObject )
        {
            aObject.XmlSettingsSave( this, aCategory );
        }

        private void DoLoad( string aCategory, IXmlSettingsExtended aObject )
        {
            aObject.XmlSettingsLoad( this, aCategory );
        }

        private void DoSave( string aCategory, TextBox aControl )
        {
            this[ aCategory, aControl.Name ] = aControl.Text;
        }

        private void DoLoad( string aCategory, TextBox aControl )
        {
            DoLoad( aCategory, aControl, string.Empty );
        }

        private void DoLoad( string aCategory, TextBox aControl, string aDefault )
        {
            string val = this[ aCategory, aControl.Name ];
            if ( val.Length > 0 )
            {
                aControl.Text = val;
            }
            else
            {
                aControl.Text = aDefault;
            }
        }

        private void DoSave( string aCategory, CheckBox aControl )
        {
            this[ aCategory, aControl.Name ] = aControl.Checked;
        }

        private void DoLoad( string aCategory, CheckBox aControl )
        {
            aControl.Checked = this[ aCategory, aControl ];
        }

        private void DoSave( string aCategory, RadioButton aControl )
        {
            this[ aCategory, aControl.Name ] = aControl.Checked;
        }

        private void DoLoad( string aCategory, RadioButton aControl )
        {
            aControl.Checked = this[ aCategory, aControl ];
        }

        private void DoSave( string aCategory, ComboBox aControl )
        {
            XmlSettingCategory category = this[ aCategory ];
 
            // Basic prefix
            string baseName = string.Format( "{0}###Item###", aControl.Name );
            
            // Write count, selection
            category[ baseName + "Count" ] = aControl.Items.Count;
            category[ baseName + "SelectedIndex" ] = aControl.SelectedIndex;

            // Write items
            int itemIndex = 0;
            foreach ( object item in aControl.Items )
            {
                string itemName = string.Format( "{0}{1:d6}", baseName, itemIndex++ );
                category[ itemName ] = item.ToString();
            }
        }

        private void DoLoad( string aCategory, ComboBox aControl )
        {
            XmlSettingCategory category = this[ aCategory ];

            aControl.BeginUpdate();

            // Basic prefix
            string baseName = string.Format( "{0}###Item###", aControl.Name );

            // Get count, selection
            int count = category[ baseName + "Count" ].ToInt( 0 );
            int selectedIndex = category[ baseName + "SelectedIndex" ].ToInt( 0 );

            // Get items
            for ( int itemIndex = 0; itemIndex < count; itemIndex++ )
            {
                string itemName = string.Format( "{0}{1:d6}", baseName, itemIndex++ );
                string itemText = category[ itemName ];
                bool alreadyExists = aControl.Items.Contains( itemText );
                if ( !alreadyExists )
                {
                    aControl.Items.Add( itemText );
                }
            }

            // Set selection if possible
            if ( selectedIndex >= 0 && selectedIndex < aControl.Items.Count )
            {
                aControl.SelectedIndex = selectedIndex;
            }
            aControl.EndUpdate();
        }

        private void DoSave( string aCategory, Form aForm )
        {
            XmlSettingCategory category = this[ aCategory ];

            // Save location (if relevant)
            Point location = new Point();
            if ( aForm.WindowState == FormWindowState.Normal )
            {
                location = aForm.Location;
            }
            Save( aCategory, "__#Location#__", location );

            // Save size 
            Size size = new Size();
            if ( aForm.WindowState == FormWindowState.Normal )
            {
                size = aForm.Size;
            }
            Save( aCategory, "__#Size#__", size );

            // Save window state
            category[ "__#State#__" ] = aForm.WindowState.ToString();
        }

        private void DoLoad( string aCategory, Form aForm )
        {
            aForm.StartPosition = FormStartPosition.Manual;

            if ( Exists( aCategory ) )
            {
                XmlSettingCategory category = this[ aCategory ];
                
                // Get initial string setting values
                string stringState = category[ "__#State#__" ];
                string stringLocation = category[ "__#Location#__" ];
                string stringSize = category[ "__#Size#__" ];
                
                // Convert to correct types
                FormWindowState state = (FormWindowState) System.Enum.Parse( typeof( FormWindowState ), stringState );
                Point location = Load( aCategory, "__#Location#__" , new Point( 0, 0 ) );
                Size size = Load( aCategory, "__#Size#__", aForm.MinimumSize );
                //
                aForm.Location = location;
                aForm.WindowState = state;
                if ( aForm.WindowState == FormWindowState.Normal )
                {
                    aForm.Size = size;
                }
            }
            else
            {
                // Go with defaults for everything
                aForm.WindowState = FormWindowState.Maximized;
            }
        }
        #endregion

		#region Data members
		private static Version iCurrentSettingsVersion = new Version( 2, 0, 0 );
        private string iFullyQualifiedFileName = string.Empty;
        private SortedList<string, XmlSettingCategory> iCategories = new SortedList<string, XmlSettingCategory>();
		#endregion
    }
}