check point
This commit is contained in:
845
framework/Inspectron.Settings/InspectronSettings.cs
Normal file
845
framework/Inspectron.Settings/InspectronSettings.cs
Normal file
@@ -0,0 +1,845 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization.Formatters.Binary;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Xml;
|
||||
|
||||
namespace Inspectron.Settings
|
||||
{
|
||||
|
||||
public class InspectronSettings
|
||||
{
|
||||
|
||||
public InspectronSettings(string path=null)
|
||||
{
|
||||
Assembly assembly = Assembly.GetEntryAssembly() ?? Assembly.GetExecutingAssembly();
|
||||
|
||||
AssemblyName assemblyName = assembly.GetName();
|
||||
_applicationName = assemblyName.Name;
|
||||
Version version = assemblyName.Version;
|
||||
_versionString = version.Major + "." + version.Minor;
|
||||
|
||||
string startupPath = Path.GetDirectoryName(new Uri(assemblyName.CodeBase).LocalPath);
|
||||
_defaultSettingsPath = Path.Combine(startupPath, "DefaultSettings.xml");
|
||||
|
||||
|
||||
|
||||
if (path == null)
|
||||
{
|
||||
var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||
_settingsPath = string.Format("{0}\\{1}\\{2}\\AppSettings.xml", appDataPath, _applicationName, _versionString);
|
||||
}
|
||||
else
|
||||
{
|
||||
_settingsPath = Path.Combine(path,"AppSettings.xml");
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
internal Path<object> GetSettingsPath(string pathName)
|
||||
{
|
||||
string[] pathSegments = pathName.Split('/', 16);
|
||||
object[] path = new object[pathSegments.Length + 1];
|
||||
|
||||
// first node is the settings tree root
|
||||
Tree<object> node = (Tree<object>)_userSettings;
|
||||
path[0] = _userSettings;
|
||||
|
||||
// middle nodes are folders
|
||||
for (int i = 1; i < path.Length - 1; i++)
|
||||
{
|
||||
node = GetOrCreateFolder(pathSegments[i - 1], node);
|
||||
path[i] = node;
|
||||
}
|
||||
|
||||
// leaf node is user settings object
|
||||
foreach (Tree<object> leaf in node.Children)
|
||||
{
|
||||
UserSettingsInfo info = leaf.Value as UserSettingsInfo;
|
||||
if (info != null && info.Name == pathSegments[pathSegments.Length - 1])
|
||||
{
|
||||
path[path.Length - 1] = leaf;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new Path<object>(path);
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the current state of all properties (Memento pattern)</summary>
|
||||
public object State
|
||||
{
|
||||
get
|
||||
{
|
||||
MemoryStream stream = new MemoryStream();
|
||||
Serialize(stream);
|
||||
return stream;
|
||||
}
|
||||
set
|
||||
{
|
||||
MemoryStream stream = value as MemoryStream;
|
||||
if (stream == null)
|
||||
throw new ArgumentException("Not a valid memento");
|
||||
stream.Position = 0;
|
||||
Deserialize(stream);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<PropertyDescriptor> UserPropertyDescriptors
|
||||
{
|
||||
get
|
||||
{
|
||||
var userSettings = UserSettings as Tree<object>;
|
||||
if (userSettings == null)
|
||||
throw new InvalidOperationException("userSettings");
|
||||
var all = userSettings.LevelOrder.Where(x => x.Value is UserSettingsInfo);
|
||||
foreach (Tree<object> node in all)
|
||||
{
|
||||
UserSettingsInfo info = node.Value as UserSettingsInfo;
|
||||
if (info != null)
|
||||
{
|
||||
foreach (PropertyDescriptor property in info.Settings)
|
||||
yield return property;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private static readonly object _unusedComponent = new object();
|
||||
public void SetDefaults()
|
||||
{
|
||||
foreach (SettingsInfo info in _settings.Values)
|
||||
{
|
||||
foreach (SettingsInfo.Setting setting in info.Settings.Values)
|
||||
{
|
||||
if (setting.PropertyDescriptor != null &&
|
||||
setting.PropertyDescriptor.CanResetValue(_unusedComponent))
|
||||
{
|
||||
setting.PropertyDescriptor.ResetValue(_unusedComponent);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Load default settings if exist.
|
||||
if (File.Exists(_defaultSettingsPath))
|
||||
{
|
||||
using (Stream stream = File.OpenRead(_defaultSettingsPath))
|
||||
Deserialize(stream);
|
||||
}
|
||||
}
|
||||
internal List<PropertyDescriptor> GetProperties(Tree<object> tree)
|
||||
{
|
||||
var info = tree.Value as UserSettingsInfo;
|
||||
if (info != null)
|
||||
return info.Settings;
|
||||
|
||||
return null;
|
||||
}
|
||||
protected class SettingsInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor with name</summary>
|
||||
/// <param name="name">Name associated with this group of settings</param>
|
||||
public SettingsInfo(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a setting to group of settings as a name and value, replacing the previous value if present</summary>
|
||||
/// <param name="name">Setting name</param>
|
||||
/// <param name="valueString">Setting value</param>
|
||||
public void Add(string name, string valueString)
|
||||
{
|
||||
Setting setting;
|
||||
if (Settings.TryGetValue(name, out setting))
|
||||
{
|
||||
setting.Set(name, valueString);
|
||||
}
|
||||
else
|
||||
{
|
||||
Settings.Add(name, new Setting(name, valueString));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a setting to group of settings as a PropertyDescriptor, replacing the previous value if present</summary>
|
||||
/// <param name="descriptor">PropertyDescriptor describing setting</param>
|
||||
public void Add(PropertyDescriptor descriptor)
|
||||
{
|
||||
Setting setting;
|
||||
if (Settings.TryGetValue(descriptor.Name, out setting))
|
||||
{
|
||||
setting.Set(descriptor);
|
||||
}
|
||||
else
|
||||
{
|
||||
Settings.Add(descriptor.Name, new Setting(descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name associated with this group of settings</summary>
|
||||
public readonly string Name;
|
||||
/// <summary>
|
||||
/// Dictionary for names and values of settings in group</summary>
|
||||
public readonly SortedDictionary<string, Setting> Settings = new SortedDictionary<string, Setting>();
|
||||
|
||||
/// <summary>
|
||||
/// Class for handling individual setting information</summary>
|
||||
public class Setting
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor with PropertyDescriptor</summary>
|
||||
/// <param name="descriptor">PropertyDescriptor describing setting</param>
|
||||
public Setting(PropertyDescriptor descriptor)
|
||||
{
|
||||
PropertyDescriptor = descriptor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor with name and value of setting</summary>
|
||||
/// <param name="name">Setting name</param>
|
||||
/// <param name="valueString">Setting value</param>
|
||||
public Setting(string name, string valueString)
|
||||
{
|
||||
Name = name;
|
||||
ValueString = valueString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a setting's value with name and value of setting</summary>
|
||||
/// <param name="name">Setting name</param>
|
||||
/// <param name="valueString">Setting value</param>
|
||||
public void Set(string name, string valueString)
|
||||
{
|
||||
Name = name;
|
||||
ValueString = valueString;
|
||||
if (PropertyDescriptor != null)
|
||||
{
|
||||
SetValue();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a setting's value with PropertyDescriptor</summary>
|
||||
/// <param name="descriptor">PropertyDescriptor describing setting</param>
|
||||
public void Set(PropertyDescriptor descriptor)
|
||||
{
|
||||
PropertyDescriptor = descriptor;
|
||||
if (Name != null && ValueString != null)
|
||||
{
|
||||
SetValue();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetValue()
|
||||
{
|
||||
if (!CanMakeChanges)
|
||||
return;
|
||||
|
||||
object value = GetValue(PropertyDescriptor.PropertyType, ValueString);
|
||||
PropertyDescriptor.SetValue(null, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Setting name</summary>
|
||||
public string Name;
|
||||
/// <summary>
|
||||
/// Setting value</summary>
|
||||
public string ValueString;
|
||||
/// <summary>
|
||||
/// Setting PropertyDescriptor</summary>
|
||||
public PropertyDescriptor PropertyDescriptor;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set whether property descriptors are allowed to make changes</summary>
|
||||
/// <remarks>Used when persisted settings are being loaded from disk
|
||||
/// to prevent property descriptors from being set multiple times as
|
||||
/// in the case where DefaultSettings.xml and AppSettings.xml both exist</remarks>
|
||||
public static bool CanMakeChanges { private get; set; }
|
||||
}
|
||||
private static object GetValue(Type type, string valueString)
|
||||
{
|
||||
object value = null;
|
||||
try
|
||||
{
|
||||
TypeConverter converter = TypeDescriptor.GetConverter(type);
|
||||
if (CanConvertToAndFromString(converter))
|
||||
{
|
||||
value = converter.ConvertFromInvariantString(valueString);
|
||||
}
|
||||
else
|
||||
{
|
||||
// deserialize
|
||||
byte[] data = Convert.FromBase64String(valueString);
|
||||
using (MemoryStream stream = new MemoryStream(data))
|
||||
{
|
||||
BinaryFormatter formatter = new BinaryFormatter();
|
||||
value = formatter.Deserialize(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
value = null;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
private static bool CanConvertToAndFromString(TypeConverter converter)
|
||||
{
|
||||
return converter.CanConvertFrom(typeof(string)) &&
|
||||
converter.CanConvertTo(typeof(string));
|
||||
}
|
||||
/// <summary>
|
||||
/// Class for group of user settings</summary>
|
||||
public class UserSettingsInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor with name and PropertyDescriptors</summary>
|
||||
/// <param name="name">Name of group of user settings</param>
|
||||
/// <param name="settings">PropertyDescriptors with settings</param>
|
||||
public UserSettingsInfo(string name, PropertyDescriptor[] settings)
|
||||
{
|
||||
Name = name;
|
||||
Settings = new List<PropertyDescriptor>(settings);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Name of group of user settings</summary>
|
||||
public readonly string Name;
|
||||
/// <summary>
|
||||
/// PropertyDescriptors with settings</summary>
|
||||
public readonly List<PropertyDescriptor> Settings;
|
||||
}
|
||||
private readonly SortedDictionary<string, SettingsInfo> _settings = new SortedDictionary<string, SettingsInfo>();
|
||||
private ITreeView _userSettings = new TreeView(string.Empty);
|
||||
|
||||
public void RegisterSettings(string uid, params PropertyDescriptor[] settings)
|
||||
{
|
||||
SettingsInfo settingsInfo;
|
||||
if (!_settings.TryGetValue(uid, out settingsInfo))
|
||||
{
|
||||
settingsInfo = new SettingsInfo(uid);
|
||||
_settings.Add(uid, settingsInfo);
|
||||
}
|
||||
|
||||
foreach (PropertyDescriptor descriptor in settings)
|
||||
settingsInfo.Add(descriptor);
|
||||
}
|
||||
public ITreeView UserSettings
|
||||
{
|
||||
get { return _userSettings; }
|
||||
}
|
||||
|
||||
public void RegisterSimple(object owner,Expression<Func<object>> expression,string pathName,string name,string category="General",string description="")
|
||||
{
|
||||
var descriptor = new BoundPropertyDescriptor(owner,expression, name, category,
|
||||
description);
|
||||
|
||||
RegisterSettings(pathName,descriptor);
|
||||
|
||||
RegisterUserSettings(pathName,descriptor);
|
||||
}
|
||||
|
||||
public void RegisterUserSettings(string pathName, params PropertyDescriptor[] settings)
|
||||
{
|
||||
if (string.IsNullOrEmpty(pathName))
|
||||
throw new ArgumentException("pathName");
|
||||
|
||||
string[] path = pathName.Split('/', 16);
|
||||
|
||||
// get root folder
|
||||
Tree<object> folder = UserSettings as Tree<object>;
|
||||
if (folder == null)
|
||||
throw new InvalidOperationException("userSettings");
|
||||
|
||||
// for each subsequent segment of the path, get folder
|
||||
for (int i = 0; i < path.Length - 1; i++)
|
||||
folder = GetOrCreateFolder(path[i], folder);
|
||||
|
||||
// get the node that should hold the settings, if it already exists
|
||||
string name = path[path.Length - 1];
|
||||
UserSettingsInfo existing = null;
|
||||
int index = 0;
|
||||
foreach (Tree<object> node in folder.Children)
|
||||
{
|
||||
UserSettingsInfo info = node.Value as UserSettingsInfo;
|
||||
if (info != null)
|
||||
{
|
||||
if (info.Name == name)
|
||||
{
|
||||
existing = info;
|
||||
break;
|
||||
}
|
||||
if (info.Name.CompareTo(name) < 0)
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
// add the settings, either by merging with the existing node or creating a new one
|
||||
if (existing != null)
|
||||
{
|
||||
foreach (PropertyDescriptor pd in settings)
|
||||
existing.Settings.Add(pd);
|
||||
}
|
||||
else
|
||||
{
|
||||
Tree<object> node = new Tree<object>(new UserSettingsInfo(name, settings));
|
||||
folder.Children.Insert(index, node);
|
||||
}
|
||||
}
|
||||
private static string GetMutexName(string pathName)
|
||||
{
|
||||
string safeName = pathName;
|
||||
|
||||
//255 characters will break IpcChannel constructor. 250 works.
|
||||
if (safeName.Length > 250)
|
||||
safeName = safeName.Substring(safeName.Length - 250);
|
||||
|
||||
// The Mutex constructor will crash if given '\', unless it's part of a valid path.
|
||||
// NextInstanceMonitor.ActivateApplication() will crash if there are '/' characters.
|
||||
safeName = safeName.Replace('/', '-');
|
||||
safeName = safeName.Replace('\\', '-');
|
||||
|
||||
return safeName;
|
||||
}
|
||||
protected void Serialize(Stream stream)
|
||||
{
|
||||
Saving.Raise(this, EventArgs.Empty);
|
||||
|
||||
XmlDocument xmlDoc = new XmlDocument();
|
||||
xmlDoc.AppendChild(xmlDoc.CreateXmlDeclaration("1.0", "utf-8", "yes"));
|
||||
XmlElement root = xmlDoc.CreateElement("settings");
|
||||
xmlDoc.AppendChild(root);
|
||||
|
||||
// add application name and version to the root element.
|
||||
root.SetAttribute("appName", _applicationName);
|
||||
root.SetAttribute("appVersion", _versionString);
|
||||
|
||||
foreach (SettingsInfo info in _settings.Values)
|
||||
{
|
||||
XmlElement block = xmlDoc.CreateElement("block");
|
||||
block.SetAttribute("id", info.Name);
|
||||
|
||||
foreach (SettingsInfo.Setting setting in info.Settings.Values)
|
||||
{
|
||||
PropertyDescriptor descriptor = setting.PropertyDescriptor;
|
||||
if (descriptor != null)
|
||||
{
|
||||
object value = descriptor.GetValue(null);
|
||||
if (CanWriteValue(value))
|
||||
WriteValue(descriptor.Name, value, block);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteValue(setting.Name, setting.ValueString, block);
|
||||
}
|
||||
}
|
||||
// skip empty block
|
||||
if (block.ChildNodes.Count > 0)
|
||||
root.AppendChild(block);
|
||||
}
|
||||
|
||||
XmlWriterSettings settings = new XmlWriterSettings();
|
||||
settings.CloseOutput = false;
|
||||
settings.Indent = true;
|
||||
|
||||
using (XmlWriter writer = XmlWriter.Create(stream, settings))
|
||||
{
|
||||
xmlDoc.WriteTo(writer);
|
||||
}
|
||||
}
|
||||
private bool CanWriteValue(object value)
|
||||
{
|
||||
if (value == null)
|
||||
return false;
|
||||
|
||||
TypeConverter converter = TypeDescriptor.GetConverter(value.GetType());
|
||||
return CanConvertToAndFromString(converter) || value.GetType().IsSerializable;
|
||||
}
|
||||
private void WriteValue(string name, object value, XmlElement block)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
// skip persisting if any exception occurs
|
||||
string valueString = null;
|
||||
Type type = value.GetType();
|
||||
TypeConverter converter = TypeDescriptor.GetConverter(type);
|
||||
if (CanConvertToAndFromString(converter))
|
||||
{
|
||||
valueString = converter.ConvertToInvariantString(value);
|
||||
}
|
||||
else if (type.IsSerializable)
|
||||
{
|
||||
// serialize
|
||||
BinaryFormatter formatter = new BinaryFormatter();
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
formatter.Serialize(stream, value);
|
||||
valueString = Convert.ToBase64String(stream.GetBuffer());
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(valueString))
|
||||
return;
|
||||
|
||||
XmlDocument xmlDoc = block.OwnerDocument;
|
||||
XmlElement elmValue = xmlDoc.CreateElement("value");
|
||||
elmValue.SetAttribute("name", name);
|
||||
elmValue.SetAttribute("type", type.Name);
|
||||
|
||||
// if the valueString is xmlDoc then
|
||||
XmlDocument temp = StringToXmlDoc(valueString);
|
||||
if (temp != null)
|
||||
{
|
||||
// remove xml declaration if exists
|
||||
XmlDeclaration decl = temp.FirstChild as XmlDeclaration;
|
||||
if (decl != null)
|
||||
temp.RemoveChild(decl);
|
||||
elmValue.InnerXml = temp.DocumentElement.OuterXml;
|
||||
}
|
||||
else
|
||||
{
|
||||
elmValue.InnerText = valueString;
|
||||
}
|
||||
|
||||
block.AppendChild(elmValue);
|
||||
}
|
||||
private XmlDocument StringToXmlDoc(string strXml)
|
||||
{
|
||||
XmlDocument xmlDoc = null;
|
||||
try
|
||||
{
|
||||
int len = (strXml.Length > 20) ? 20 : strXml.Length;
|
||||
string test = RemoveAllWhiteSpace(strXml.Substring(0, len)).ToLower();
|
||||
if (test.Contains("<?xmlversion="))
|
||||
{
|
||||
xmlDoc = new XmlDocument();
|
||||
xmlDoc.LoadXml(strXml);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
xmlDoc = null;
|
||||
}
|
||||
return xmlDoc;
|
||||
|
||||
}
|
||||
public static string RemoveAllWhiteSpace(string s)
|
||||
{
|
||||
if (string.IsNullOrEmpty(s))
|
||||
return s;
|
||||
StringBuilder result = new StringBuilder(s.Length);
|
||||
for (int i = 0; i < s.Length; i++)
|
||||
{
|
||||
char c = s[i];
|
||||
if (!char.IsWhiteSpace(c))
|
||||
result.Append(c);
|
||||
}
|
||||
return result.ToString();
|
||||
}
|
||||
public void SaveSettings()
|
||||
{
|
||||
string tempNew = string.Empty;
|
||||
|
||||
string mutexName = GetMutexName(_settingsPath);
|
||||
using (Mutex saveMutex = new Mutex(false, mutexName))
|
||||
{
|
||||
try
|
||||
{
|
||||
saveMutex.WaitOne();
|
||||
|
||||
// Create zero-size file.
|
||||
tempNew = Path.GetTempFileName();
|
||||
|
||||
using (Stream stream = File.Create(tempNew))
|
||||
Serialize(stream);
|
||||
|
||||
// Make sure the settings directory exists. Do nothing if it already exists.
|
||||
string settingsDir = Path.GetDirectoryName(_settingsPath);
|
||||
Directory.CreateDirectory(settingsDir);
|
||||
|
||||
// Erase old backup (if any) and move current settings file (if any).
|
||||
string tempBackup = Path.Combine(settingsDir, "~Settings.xml");
|
||||
if (File.Exists(tempBackup)) // seems unnecessary, but Dan put this check in the WPF version --Ron
|
||||
File.Delete(tempBackup);
|
||||
if (File.Exists(_settingsPath))
|
||||
File.Move(_settingsPath, tempBackup);
|
||||
|
||||
// Move temporary file to be the new settings file, then delete backup.
|
||||
File.Move(tempNew, _settingsPath);
|
||||
File.Delete(tempBackup);
|
||||
}
|
||||
catch (TargetInvocationException)
|
||||
{
|
||||
// Catch and ignore TargetInvocationException happening if Windows
|
||||
// is shut down with the application still running.
|
||||
// TO DO: Find a way to successfully save settings and exit on shutdown.
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Attempt clean-up. No exception is thrown if file doesn't exist.
|
||||
File.Delete(tempNew);
|
||||
saveMutex.ReleaseMutex();
|
||||
}
|
||||
}
|
||||
}
|
||||
private Tree<object> GetOrCreateFolder(string name, Tree<object> tree)
|
||||
{
|
||||
// search for folder
|
||||
Tree<object> result = null;
|
||||
int index = 0;
|
||||
foreach (Tree<object> child in tree.Children)
|
||||
{
|
||||
string folderName = child.Value as string;
|
||||
if (folderName != null)
|
||||
{
|
||||
if (folderName == name)
|
||||
{
|
||||
result = child;
|
||||
break;
|
||||
}
|
||||
|
||||
if (folderName.CompareTo(name) < 0)
|
||||
index++;
|
||||
}
|
||||
else // child is UserSettingsInfo
|
||||
{
|
||||
index++; // folders should follow settings nodes
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// if not found, create it
|
||||
if (result == null)
|
||||
{
|
||||
result = new Tree<object>(name);
|
||||
tree.Children.Insert(index, result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public event EventHandler Saving;
|
||||
public event EventHandler Loading;
|
||||
public event EventHandler Reloaded;
|
||||
|
||||
|
||||
private class TreeView : Tree<object>, ITreeView
|
||||
{
|
||||
public TreeView(object root)
|
||||
: base(root)
|
||||
{
|
||||
}
|
||||
|
||||
#region ITreeView Members
|
||||
|
||||
public object Root
|
||||
{
|
||||
get { return this; }
|
||||
}
|
||||
|
||||
public IEnumerable<object> GetChildren(object parent)
|
||||
{
|
||||
foreach (object child in ((Tree<object>)parent).Children)
|
||||
yield return child;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region IItemView Members
|
||||
|
||||
/// <summary>
|
||||
/// Gets item's display information</summary>
|
||||
/// <param name="item">Item being displayed</param>
|
||||
/// <param name="info">Item info, to fill out</param>
|
||||
public void GetInfo(object item, ItemInfo info)
|
||||
{
|
||||
object value = ((Tree<object>)item).Value;
|
||||
if (value is string)
|
||||
{
|
||||
info.Label = (string)value;
|
||||
//info.ImageIndex = info.GetImageList().Images.IndexOfKey(Resources.FolderImage);
|
||||
info.AllowSelect = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
UserSettingsInfo settingsInfo = value as UserSettingsInfo;
|
||||
info.Label = settingsInfo.Name;
|
||||
info.AllowLabelEdit = false;
|
||||
//info.ImageIndex = info.GetImageList().Images.IndexOfKey(Resources.PreferencesImage);
|
||||
info.IsLeaf = true;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
||||
private string _settingsPath;
|
||||
private string _defaultSettingsPath;
|
||||
private string _applicationName;
|
||||
private string _versionString;
|
||||
private string _propertyViewState;
|
||||
|
||||
|
||||
public void LoadSettings()
|
||||
{
|
||||
Loading.Raise(this, EventArgs.Empty);
|
||||
|
||||
try
|
||||
{
|
||||
bool defaultSettingsExists = File.Exists(_defaultSettingsPath);
|
||||
bool appSettingsExists = File.Exists(_settingsPath);
|
||||
|
||||
// only update property descriptors during the DefaultSettings.xml pass
|
||||
// if DefaultSettings.xml exists and AppSettings.xml does not exist
|
||||
SettingsInfo.CanMakeChanges = defaultSettingsExists && !appSettingsExists;
|
||||
|
||||
// first, load default settings, if they exist:
|
||||
if (defaultSettingsExists)
|
||||
{
|
||||
using (Stream stream = File.OpenRead(_defaultSettingsPath))
|
||||
Deserialize(stream);
|
||||
}
|
||||
|
||||
// restore for AppSettings.xml pass
|
||||
SettingsInfo.CanMakeChanges = true;
|
||||
|
||||
// now load user settings, overriding defaults:
|
||||
if (appSettingsExists)
|
||||
{
|
||||
using (Stream stream = File.OpenRead(_settingsPath))
|
||||
Deserialize(stream);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
finally
|
||||
{
|
||||
// restore value
|
||||
SettingsInfo.CanMakeChanges = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected void ApplyStoredSettings()
|
||||
{
|
||||
foreach (SettingsInfo info in _settings.Values)
|
||||
{
|
||||
foreach (SettingsInfo.Setting setting in info.Settings.Values)
|
||||
{
|
||||
if (setting.PropertyDescriptor is BoundPropertyDescriptor pd)
|
||||
{
|
||||
if (setting.ValueString == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
object v;
|
||||
if (setting.PropertyDescriptor.PropertyType.IsEnum)
|
||||
{
|
||||
v = Enum.Parse(setting.PropertyDescriptor.PropertyType, setting.ValueString);
|
||||
}
|
||||
else
|
||||
{
|
||||
v = Convert.ChangeType(setting.ValueString, setting.PropertyDescriptor.PropertyType);
|
||||
}
|
||||
pd.SetValue(pd.Owner, v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected bool Deserialize(Stream stream)
|
||||
{
|
||||
// create XML DOM from stream
|
||||
// if failed, display message box and return
|
||||
try
|
||||
{
|
||||
XmlDocument xmlDoc = new XmlDocument();
|
||||
xmlDoc.Load(stream);
|
||||
|
||||
XmlElement root = xmlDoc.DocumentElement;
|
||||
|
||||
// get all the blocks
|
||||
XmlNodeList blocks = root.SelectNodes("block");
|
||||
if (blocks == null || blocks.Count == 0)
|
||||
throw new Exception("The setting file is empty");
|
||||
|
||||
foreach (XmlElement block in blocks)
|
||||
{
|
||||
try
|
||||
{
|
||||
string id = block.GetAttribute("id");
|
||||
|
||||
SettingsInfo info;
|
||||
if (!_settings.TryGetValue(id, out info))
|
||||
{
|
||||
info = new SettingsInfo(id);
|
||||
_settings.Add(id, info);
|
||||
}
|
||||
|
||||
// get a list of value element in each block
|
||||
XmlNodeList valueNodes = block.SelectNodes("value");
|
||||
|
||||
// skip over empty block
|
||||
if (valueNodes == null || valueNodes.Count == 0)
|
||||
continue;
|
||||
|
||||
foreach (XmlElement xmlElement in valueNodes)
|
||||
{
|
||||
string name = xmlElement.GetAttribute("name");
|
||||
string valueString = GetElementValueString(xmlElement);
|
||||
|
||||
info.Add(name, valueString);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
ApplyStoredSettings();
|
||||
Reloaded.Raise(this, EventArgs.Empty);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
private static string GetElementValueString(XmlElement element)
|
||||
{
|
||||
string valueString = element.InnerText;
|
||||
if (string.IsNullOrEmpty(valueString))
|
||||
valueString = element.InnerXml;
|
||||
|
||||
return valueString;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user