Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
SettingsProfile.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.Collections.Generic;
5 using System.IO;
6 
7 using SiliconStudio.Core.IO;
8 using SiliconStudio.Presentation.Core;
9 
10 namespace SiliconStudio.Presentation.Settings
11 {
12  /// <summary>
13  /// This class represents a collection of values for all registered <see cref="SettingsKey"/>. It may also contains values for settings keys that
14  /// are not currently registered, if they exist in the file from which the profile was loaded.
15  /// </summary>
16  public class SettingsProfile : IDisposable
17  {
18  internal ActionStack.ActionStack ActionStack = new ActionStack.ActionStack(-1);
19  internal bool Saving;
20  private readonly SortedList<UFile, SettingsEntry> settings = new SortedList<UFile, SettingsEntry>();
21  private readonly HashSet<UFile> modifiedSettings = new HashSet<UFile>();
22  private readonly SettingsProfile parentProfile;
23  private FileSystemWatcher fileWatcher;
24  private UFile filePath;
25  private bool monitorFileModification;
26 
27  /// <summary>
28  /// Initializes a new instance of the <see cref="SettingsProfile"/> class.
29  /// </summary>
30  /// <param name="parentProfile">The parent profile.</param>
31  internal SettingsProfile(SettingsProfile parentProfile)
32  {
33  this.parentProfile = parentProfile;
34  }
35 
36  /// <summary>
37  /// Gets the path of the file in which this profile has been saved.
38  /// </summary>
39  public UFile FilePath { get { return filePath; } internal set { Utils.SetAndInvokeIfChanged(ref filePath, value, UpdateMonitoring); } }
40 
41  /// <summary>
42  /// Gets or sets whether to monitor external modification of the file in which this profile is stored. If <c>true</c>, The <see cref="FileModified"/> event might be raised.
43  /// </summary>
44  public bool MonitorFileModification { get { return monitorFileModification; } set { Utils.SetAndInvokeIfChanged(ref monitorFileModification, value, UpdateMonitoring); } }
45 
46  /// <summary>
47  /// Raised when the file corresponding to this profile is modified on the disk, and <see cref="MonitorFileModification"/> is <c>true</c>.
48  /// </summary>
49  public event EventHandler<FileModifiedEventArgs> FileModified;
50 
51  /// <summary>
52  /// Gets the collection of <see cref="SettingsEntry"/> currently existing in this <see cref="SettingsProfile"/>.
53  /// </summary>
54  internal IDictionary<UFile, SettingsEntry> Settings { get { return settings; } }
55 
56  internal bool IsDiscarding { get; private set; }
57 
58  /// <inheritdoc/>
59  public void Dispose()
60  {
61  if (fileWatcher != null)
62  {
63  fileWatcher.Changed -= SettingsFileChanged;
64  fileWatcher.Dispose();
65  }
66  }
67 
69  {
70  var keys = SettingsService.GetAllSettingsKeys(true);
71  foreach (var key in keys)
72  {
73  if (modifiedSettings.Contains(key.Name))
74  key.NotifyChangesValidated(this);
75  }
76  ActionStack.Clear();
77  modifiedSettings.Clear();
78  }
79 
80  public void DiscardSettingsChanges()
81  {
82  IsDiscarding = true;
83  while (ActionStack.CanUndo)
84  {
85  ActionStack.Undo();
86  }
87  ActionStack.Clear();
88  modifiedSettings.Clear();
89  IsDiscarding = false;
90  }
91 
92  /// <summary>
93  /// Registers an entry that has not been registered before.
94  /// </summary>
95  /// <param name="entry">The entry to register.</param>
96  internal void RegisterEntry(SettingsEntry entry)
97  {
98  if (entry == null) throw new ArgumentNullException("entry");
99  Settings.Add(entry.Name, entry);
100  }
101 
102  /// <summary>
103  /// Gets the settings value that matches the given name.
104  /// </summary>
105  /// <param name="name">The name of the <see cref="SettingsEntry"/> to fetch.</param>
106  /// <param name="value">The resulting value if the name is found, <c>null</c> otherwise.</param>
107  /// <param name="searchInParent">Indicates whether to search in the parent profile, if the name is not found in this profile.</param>
108  /// <param name="createInCurrentProfile">If true, the list will be created in the current profile, from the value of its parent profile.</param>
109  /// <returns><c>true</c> if an entry matching the name is found, <c>false</c> otherwise.</returns>
110  internal bool GetValue(UFile name, out object value, bool searchInParent, bool createInCurrentProfile)
111  {
112  if (name == null) throw new ArgumentNullException("name");
113  SettingsEntry entry = GetEntry(name, searchInParent, createInCurrentProfile);
114  if (entry != null)
115  {
116  value = entry.Value;
117  return true;
118  }
119  value = null;
120  return false;
121  }
122 
123  /// <summary>
124  /// Set the value of the entry that match the given name.
125  /// </summary>
126  /// <param name="name">The name to match.</param>
127  /// <param name="value">The value to set.</param>
128  internal void SetValue(UFile name, object value)
129  {
130  if (name == null) throw new ArgumentNullException("name");
131 
132  SettingsEntry entry;
133  if (!Settings.TryGetValue(name, out entry))
134  {
135  entry = SettingsEntry.CreateFromValue(this, name, value);
136  Settings[name] = entry;
137  }
138  else
139  {
140  Settings[name].Value = value;
141  }
142  }
143 
144  /// <summary>
145  /// Notifies that the entry with the given name has changed.
146  /// </summary>
147  /// <param name="name">The name of the entry that has changed.</param>
148  internal void NotifyEntryChanged(UFile name)
149  {
150  modifiedSettings.Add(name);
151  }
152 
153  /// <summary>
154  /// Gets the <see cref="SettingsEntry"/> that matches the given name.
155  /// </summary>
156  /// <param name="name">The name of the <see cref="SettingsEntry"/> to fetch.</param>
157  /// <param name="searchInParent">Indicates whether to search in the parent profile, if the name is not found in this profile.</param>
158  /// <param name="createInCurrentProfile"></param>
159  /// <returns>An instance of <see cref="SettingsEntry"/> that matches the name, or <c>null</c>.</returns>
160  private SettingsEntry GetEntry(UFile name, bool searchInParent, bool createInCurrentProfile)
161  {
162  if (name == null) throw new ArgumentNullException("name");
163 
164  SettingsEntry entry;
165  if (Settings.TryGetValue(name, out entry))
166  return entry;
167 
168  if (createInCurrentProfile)
169  {
170  entry = parentProfile.GetEntry(name, true, false);
171  entry = SettingsEntry.CreateFromValue(this, name, entry.Value);
172  RegisterEntry(entry);
173  return entry;
174  }
175 
176  return parentProfile != null && searchInParent ? parentProfile.GetEntry(name, true, false) : null;
177  }
178 
179  private void UpdateMonitoring()
180  {
181  if (fileWatcher != null)
182  {
183  fileWatcher.Changed -= SettingsFileChanged;
184  fileWatcher.Dispose();
185  }
186  if (MonitorFileModification && FilePath != null && File.Exists(FilePath))
187  {
188  fileWatcher = new FileSystemWatcher(Path.Combine(Environment.CurrentDirectory, FilePath.GetFullDirectory()), FilePath.GetFileNameWithExtension());
189  fileWatcher.Changed += SettingsFileChanged;
190  fileWatcher.EnableRaisingEvents = true;
191  }
192  }
193 
194  private void SettingsFileChanged(object sender, FileSystemEventArgs e)
195  {
196  if (Saving)
197  return;
198 
199  var handler = FileModified;
200  if (handler != null)
201  {
202  var args = new FileModifiedEventArgs(this);
203  handler(null, args);
204  if (args.ReloadFile)
205  {
206  SettingsService.ReloadSettingsProfile(this);
207  }
208  }
209  }
210  }
211 }
This class represents a collection of values for all registered SettingsKey. It may also contains val...
EventHandler< FileModifiedEventArgs > FileModified
Raised when the file corresponding to this profile is modified on the disk, and MonitorFileModificati...
System.IO.File File
This class represents a thread-safe stack of action items that can be undone/redone.
Definition: ActionStack.cs:12
Defines a normalized file path. See UPath for details. This class cannot be inherited.
Definition: UFile.cs:13