Browse Source

Rewritten ICSharpCode.Core.Properties:

- The meaning of "Get" is no longer overloaded, GetList and NestedProperties are now seperate methods.
- "Get" and "GetList" no longer cause the default value to be written into the properties container.
- Use DataContractSerializer instead of XmlSerializer.
newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
7aea1ca75e
  1. 8
      data/options/SharpDevelopProperties.xml
  2. 5
      src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs
  3. 3
      src/AddIns/BackendBindings/CSharpBinding/Tests/CSharpBinding.Tests.csproj
  4. 6
      src/AddIns/BackendBindings/CSharpBinding/Tests/app.config
  5. 2
      src/AddIns/BackendBindings/CppBinding/CppBinding/CppBinding.csproj
  6. 2
      src/AddIns/BackendBindings/FSharpBinding/FSharpBinding.csproj
  7. 2
      src/AddIns/BackendBindings/XamlBinding/XamlBinding/Options/XamlBindingOptions.cs
  8. 6
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/EditorActionsProvider.cs
  9. 14
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CustomizedHighlightingColor.cs
  10. 2
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Options/HighlightingOptions.xaml.cs
  11. 4
      src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetManager.cs
  12. 2
      src/AddIns/DisplayBindings/HexEditor/Project/HexEditor.csproj
  13. 2
      src/AddIns/DisplayBindings/HexEditor/Project/Src/Util/Settings.cs
  14. 8
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XPathQueryControl.cs
  15. 4
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XPathQueryPad.cs
  16. 4
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlEditorOptions.cs
  17. 2
      src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlEditorService.cs
  18. 2
      src/AddIns/DisplayBindings/XmlEditor/Project/XmlEditor.csproj
  19. 2
      src/AddIns/Misc/AddInManager/Project/AddInManager.csproj
  20. 2
      src/AddIns/Misc/FiletypeRegisterer/Project/FiletypeRegisterer.csproj
  21. 3
      src/AddIns/Misc/FiletypeRegisterer/Project/FiletypeRegisterer.csproj.user
  22. 2
      src/AddIns/Misc/HelpViewer/HelpViewer.csproj
  23. 2
      src/AddIns/Misc/RegExpTk/Project/RegExpTk.csproj
  24. 3
      src/AddIns/Misc/RegExpTk/Project/RegExpTk.csproj.user
  25. 2
      src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchManager.cs
  26. 32
      src/AddIns/Misc/SearchAndReplace/Project/SearchOptions.cs
  27. 6
      src/AddIns/Misc/UsageDataCollector/UsageDataCollector.AddIn/AnalyticsMonitor.cs
  28. 1
      src/AddIns/Misc/UsageDataCollector/UsageDataCollector.AddIn/StartPageMessage.xaml.cs
  29. 2
      src/AddIns/Misc/UsageDataCollector/UsageDataCollector.AddIn/UsageDataCollector.AddIn.csproj
  30. 2
      src/AddIns/VersionControl/SubversionAddIn/Src/AddInOptions.cs
  31. 2
      src/Main/Base/Project/Src/Commands/AutostartCommands.cs
  32. 8
      src/Main/Base/Project/Src/Gui/BrowserDisplayBinding/HtmlViewPane.cs
  33. 5
      src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/CodeGenerationPanel.cs
  34. 5
      src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/OutputWindowOptionsPanel.cs
  35. 46
      src/Main/Base/Project/Src/Gui/Dialogs/SharpDevelopColorDialog.cs
  36. 7
      src/Main/Base/Project/Src/Gui/Pads/CompilerMessageView/CompilerMessageView.cs
  37. 2
      src/Main/Base/Project/Src/Gui/Pads/ErrorList/ErrorListPad.cs
  38. 7
      src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs
  39. 2
      src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs
  40. 2
      src/Main/Base/Project/Src/Project/AbstractProject.cs
  41. 10
      src/Main/Base/Project/Src/Project/Behaviors/DefaultProjectBehavior.cs
  42. 2
      src/Main/Base/Project/Src/Services/AmbienceService/AmbienceService.cs
  43. 8
      src/Main/Base/Project/Src/Services/DisplayBinding/DisplayBindingService.cs
  44. 4
      src/Main/Base/Project/Src/Services/File/FileService.cs
  45. 14
      src/Main/Base/Project/Src/Services/File/RecentOpen.cs
  46. 4
      src/Main/Base/Project/Src/Services/ParserService/CodeCompletionOptions.cs
  47. 9
      src/Main/Base/Project/Src/Services/ParserService/ParserService.cs
  48. 23
      src/Main/Base/Project/Src/Util/ExtensionMethods.cs
  49. 1
      src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj
  50. 78
      src/Main/Base/Test/SharpDevelopColorDialogTests.cs
  51. 2
      src/Main/Base/Test/Utils/MockTextMarker.cs
  52. 10
      src/Main/Core/Project/ICSharpCode.Core.csproj
  53. 1
      src/Main/Core/Project/Src/AddInTree/CoreStartup.cs
  54. 748
      src/Main/Core/Project/Src/Services/PropertyService/Properties.cs
  55. 61
      src/Main/Core/Project/Src/Services/PropertyService/PropertyChangedEvent.cs
  56. 169
      src/Main/Core/Project/Src/Services/PropertyService/PropertyService.cs
  57. 5
      src/Main/Core/Project/Src/Services/ResourceService/ResourceService.cs
  58. 13
      src/Main/Core/Project/Src/Services/StringParser/StringParser.cs
  59. 3
      src/Main/Core/Test/ICSharpCode.Core.Tests.csproj
  60. 3
      src/Main/ICSharpCode.Core.Presentation/ICSharpCode.Core.Presentation.csproj
  61. 3
      src/Main/ICSharpCode.Core.WinForms/ICSharpCode.Core.WinForms.csproj
  62. 3
      src/Main/ICSharpCode.SharpDevelop.Widgets/Project/ICSharpCode.SharpDevelop.Widgets.csproj

8
data/options/SharpDevelopProperties.xml

@ -1,8 +0,0 @@
<SharpDevelopProperties>
<ShowTipsAtStartup value="True" />
<Properties name="WorkbenchMemento">
<bounds value="10,10,780,560" />
<windowstate value="Maximized" />
<defaultstate value="Maximized" />
</Properties>
</SharpDevelopProperties>

5
src/AddIns/BackendBindings/CSharpBinding/Project/Src/Refactoring/IssueManager.cs

@ -70,7 +70,7 @@ namespace CSharpBinding.Refactoring
{ {
// TODO: cache the result // TODO: cache the result
var dict = new Dictionary<Type, Severity>(); var dict = new Dictionary<Type, Severity>();
var prop = PropertyService.Get("CSharpIssueSeveritySettings", new Properties()); var prop = PropertyService.NestedProperties("CSharpIssueSeveritySettings");
foreach (var provider in issueProviders.Value) { foreach (var provider in issueProviders.Value) {
dict[provider.ProviderType] = prop.Get(provider.ProviderType.FullName, provider.DefaultSeverity); dict[provider.ProviderType] = prop.Get(provider.ProviderType.FullName, provider.DefaultSeverity);
} }
@ -79,11 +79,10 @@ namespace CSharpBinding.Refactoring
public static void SetIssueSeveritySettings(IReadOnlyDictionary<Type, Severity> dict) public static void SetIssueSeveritySettings(IReadOnlyDictionary<Type, Severity> dict)
{ {
var prop = new Properties(); var prop = PropertyService.NestedProperties("CSharpIssueSeveritySettings");
foreach (var pair in dict) { foreach (var pair in dict) {
prop.Set(pair.Key.FullName, pair.Value); prop.Set(pair.Key.FullName, pair.Value);
} }
PropertyService.Set("CSharpIssueSeveritySettings", prop);
} }
readonly ITextEditor editor; readonly ITextEditor editor;

3
src/AddIns/BackendBindings/CSharpBinding/Tests/CSharpBinding.Tests.csproj

@ -7,7 +7,7 @@
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RootNamespace>CSharpBinding.Tests</RootNamespace> <RootNamespace>CSharpBinding.Tests</RootNamespace>
<AssemblyName>CSharpBinding.Tests</AssemblyName> <AssemblyName>CSharpBinding.Tests</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<SourceAnalysisOverrideSettingsFile>C:\Users\daniel\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis</SourceAnalysisOverrideSettingsFile> <SourceAnalysisOverrideSettingsFile>C:\Users\daniel\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis</SourceAnalysisOverrideSettingsFile>
<OutputPath>..\..\..\..\..\bin\UnitTests\</OutputPath> <OutputPath>..\..\..\..\..\bin\UnitTests\</OutputPath>
@ -15,6 +15,7 @@
<NoStdLib>False</NoStdLib> <NoStdLib>False</NoStdLib>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors> <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<TargetFrameworkProfile />
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>

6
src/AddIns/BackendBindings/CSharpBinding/Tests/app.config

@ -1,9 +1,11 @@
<configuration> <?xml version="1.0" encoding="utf-8"?><configuration>
<configSections> <configSections>
<sectionGroup name="NUnit"> <sectionGroup name="NUnit">
<section name="TestRunner" type="System.Configuration.NameValueSectionHandler" /> <section name="TestRunner" type="System.Configuration.NameValueSectionHandler" />
</sectionGroup> </sectionGroup>
</configSections> </configSections><startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<NUnit> <NUnit>
<TestRunner> <TestRunner>
<!-- Valid values are STA,MTA. Others ignored. --> <!-- Valid values are STA,MTA. Others ignored. -->

2
src/AddIns/BackendBindings/CppBinding/CppBinding/CppBinding.csproj

@ -6,7 +6,7 @@
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<AssemblyName>CppBinding</AssemblyName> <AssemblyName>CppBinding</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<SourceAnalysisOverrideSettingsFile>C:\Users\trecio\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis</SourceAnalysisOverrideSettingsFile> <SourceAnalysisOverrideSettingsFile>C:\Users\trecio\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis</SourceAnalysisOverrideSettingsFile>
<TargetFrameworkSubset> <TargetFrameworkSubset>
</TargetFrameworkSubset> </TargetFrameworkSubset>

2
src/AddIns/BackendBindings/FSharpBinding/FSharpBinding.csproj

@ -7,7 +7,7 @@
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RootNamespace>FSharpBinding</RootNamespace> <RootNamespace>FSharpBinding</RootNamespace>
<AssemblyName>FSharpBinding</AssemblyName> <AssemblyName>FSharpBinding</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<AppDesignerFolder>Properties</AppDesignerFolder> <AppDesignerFolder>Properties</AppDesignerFolder>
<SourceAnalysisOverrideSettingsFile>C:\Users\Daniel\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis</SourceAnalysisOverrideSettingsFile> <SourceAnalysisOverrideSettingsFile>C:\Users\Daniel\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis</SourceAnalysisOverrideSettingsFile>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks> <AllowUnsafeBlocks>False</AllowUnsafeBlocks>

2
src/AddIns/BackendBindings/XamlBinding/XamlBinding/Options/XamlBindingOptions.cs

@ -16,7 +16,7 @@ namespace ICSharpCode.XamlBinding
static XamlBindingOptions() static XamlBindingOptions()
{ {
properties = PropertyService.Get("XamlBinding.Options", new Properties()); properties = PropertyService.NestedProperties("XamlBinding.Options");
} }
static Properties Properties { static Properties Properties {

6
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/ContextActions/EditorActionsProvider.cs

@ -26,8 +26,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.ContextActions
internal static void LoadProviderVisibilities(IEnumerable<IContextActionProvider> providers) internal static void LoadProviderVisibilities(IEnumerable<IContextActionProvider> providers)
{ {
var list = PropertyService.Get(PropertyServiceKey, new List<string>()); var disabledActions = new HashSet<string>(PropertyService.GetList<string>(PropertyServiceKey));
var disabledActions = new HashSet<string>(list);
foreach (var provider in providers) { foreach (var provider in providers) {
provider.IsVisible = !(provider.AllowHiding && disabledActions.Contains(provider.ID)); provider.IsVisible = !(provider.AllowHiding && disabledActions.Contains(provider.ID));
} }
@ -35,8 +34,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.ContextActions
internal static void SaveProviderVisibilities(IEnumerable<IContextActionProvider> providers) internal static void SaveProviderVisibilities(IEnumerable<IContextActionProvider> providers)
{ {
List<string> disabledProviders = providers.Where(p => !p.IsVisible).Select(p => p.ID).ToList(); PropertyService.SetList(PropertyServiceKey, providers.Where(p => !p.IsVisible).Select(p => p.ID));
PropertyService.Set(PropertyServiceKey, disabledProviders);
} }
readonly IList<IContextActionProvider> providers; readonly IList<IContextActionProvider> providers;

14
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/CustomizedHighlightingColor.cs

@ -29,11 +29,9 @@ namespace ICSharpCode.AvalonEdit.AddIn
public bool Bold, Italic; public bool Bold, Italic;
public Color? Foreground, Background; public Color? Foreground, Background;
public static List<CustomizedHighlightingColor> LoadColors() public static IReadOnlyList<CustomizedHighlightingColor> LoadColors()
{ {
var list = PropertyService.Get("CustomizedHighlightingRules", new List<CustomizedHighlightingColor>()); return PropertyService.GetList<CustomizedHighlightingColor>("CustomizedHighlightingRules");
// Always make a copy of the list so that the original list cannot be modified without using SaveColors().
return new List<CustomizedHighlightingColor>(list);
} }
/// <summary> /// <summary>
@ -43,21 +41,21 @@ namespace ICSharpCode.AvalonEdit.AddIn
{ {
lock (staticLockObj) { lock (staticLockObj) {
activeColors = null; activeColors = null;
PropertyService.Set("CustomizedHighlightingRules", colors.ToList()); PropertyService.SetList("CustomizedHighlightingRules", colors);
} }
EventHandler e = ActiveColorsChanged; EventHandler e = ActiveColorsChanged;
if (e != null) if (e != null)
e(null, EventArgs.Empty); e(null, EventArgs.Empty);
} }
static ReadOnlyCollection<CustomizedHighlightingColor> activeColors; static IReadOnlyList<CustomizedHighlightingColor> activeColors;
static readonly object staticLockObj = new object(); static readonly object staticLockObj = new object();
public static ReadOnlyCollection<CustomizedHighlightingColor> ActiveColors { public static IReadOnlyList<CustomizedHighlightingColor> ActiveColors {
get { get {
lock (staticLockObj) { lock (staticLockObj) {
if (activeColors == null) if (activeColors == null)
activeColors = LoadColors().AsReadOnly(); activeColors = LoadColors();
return activeColors; return activeColors;
} }
} }

2
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Options/HighlightingOptions.xaml.cs

@ -128,7 +128,7 @@ namespace ICSharpCode.AvalonEdit.AddIn.Options
.OrderBy(def => def.Name) .OrderBy(def => def.Name)
.ToList(); .ToList();
} }
customizationList = CustomizedHighlightingColor.LoadColors(); customizationList = new List<CustomizedHighlightingColor>(CustomizedHighlightingColor.LoadColors());
languageComboBox.Items.Clear(); languageComboBox.Items.Clear();
languageComboBox.Items.Add(new XshdSyntaxDefinition { Name = "All languages" }); languageComboBox.Items.Add(new XshdSyntaxDefinition { Name = "All languages" });

4
src/AddIns/DisplayBindings/AvalonEdit.AddIn/Src/Snippets/SnippetManager.cs

@ -312,7 +312,7 @@ End Property${Caret}",
/// </summary> /// </summary>
public List<CodeSnippetGroup> LoadGroups() public List<CodeSnippetGroup> LoadGroups()
{ {
var savedSnippets = PropertyService.Get("CodeSnippets", new List<CodeSnippetGroup>()); var savedSnippets = new List<CodeSnippetGroup>(PropertyService.GetList<CodeSnippetGroup>("CodeSnippets"));
foreach (var group in savedSnippets) { foreach (var group in savedSnippets) {
var defaultGroup = defaultSnippets.FirstOrDefault(i => i.Extensions == group.Extensions); var defaultGroup = defaultSnippets.FirstOrDefault(i => i.Extensions == group.Extensions);
@ -382,7 +382,7 @@ End Property${Caret}",
modifiedGroups.Add(copy); modifiedGroups.Add(copy);
} }
PropertyService.Set("CodeSnippets", modifiedGroups); PropertyService.SetList("CodeSnippets", modifiedGroups);
} }
} }

2
src/AddIns/DisplayBindings/HexEditor/Project/HexEditor.csproj

@ -15,7 +15,7 @@
<DelaySign>False</DelaySign> <DelaySign>False</DelaySign>
<RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent> <RunPostBuildEvent>OnBuildSuccess</RunPostBuildEvent>
<RunCodeAnalysis>False</RunCodeAnalysis> <RunCodeAnalysis>False</RunCodeAnalysis>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile> <TargetFrameworkProfile>
</TargetFrameworkProfile> </TargetFrameworkProfile>
</PropertyGroup> </PropertyGroup>

2
src/AddIns/DisplayBindings/HexEditor/Project/Src/Util/Settings.cs

@ -15,7 +15,7 @@ namespace HexEditor.Util
/// </summary> /// </summary>
public class Settings public class Settings
{ {
static Properties properties = PropertyService.Get("HexEditorOptions", new Properties()); static Properties properties = PropertyService.NestedProperties("HexEditorOptions");
public static Properties Properties { public static Properties Properties {
get { get {

8
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XPathQueryControl.cs

@ -111,7 +111,7 @@ namespace ICSharpCode.XmlEditor
void SaveNamespaces(Properties properties) void SaveNamespaces(Properties properties)
{ {
properties.Set(NamespacesProperty, GetNamespaceStringArray()); properties.SetList(NamespacesProperty, GetNamespaceStringArray());
} }
void SaveNamespaceDataGridColumnWidths(Properties properties) void SaveNamespaceDataGridColumnWidths(Properties properties)
@ -128,7 +128,7 @@ namespace ICSharpCode.XmlEditor
void SaveXPathQueryHistory(Properties properties) void SaveXPathQueryHistory(Properties properties)
{ {
properties.Set(XPathComboBoxTextProperty, XPathComboBox.Text); properties.Set(XPathComboBoxTextProperty, XPathComboBox.Text);
properties.Set(XPathComboBoxItemsProperty, GetXPathHistory()); properties.SetList(XPathComboBoxItemsProperty, GetXPathHistory());
} }
/// <summary> /// <summary>
@ -150,7 +150,7 @@ namespace ICSharpCode.XmlEditor
void LoadNamespaces(Properties properties) void LoadNamespaces(Properties properties)
{ {
string[] namespaces = properties.Get(NamespacesProperty, new string[0]); string[] namespaces = properties.GetList<string>(NamespacesProperty);
foreach (string ns in namespaces) { foreach (string ns in namespaces) {
XmlNamespace xmlNamespace = XmlNamespace.FromString(ns); XmlNamespace xmlNamespace = XmlNamespace.FromString(ns);
AddNamespace(xmlNamespace.Prefix, xmlNamespace.Name); AddNamespace(xmlNamespace.Prefix, xmlNamespace.Name);
@ -171,7 +171,7 @@ namespace ICSharpCode.XmlEditor
void LoadXPathQueryHistory(Properties properties) void LoadXPathQueryHistory(Properties properties)
{ {
XPathComboBox.Text = properties.Get(XPathComboBoxTextProperty, string.Empty); XPathComboBox.Text = properties.Get(XPathComboBoxTextProperty, string.Empty);
string[] xpaths = properties.Get(XPathComboBoxItemsProperty, new string[0]); string[] xpaths = properties.GetList<string>(XPathComboBoxItemsProperty);
foreach (string xpath in xpaths) { foreach (string xpath in xpaths) {
xpathComboBox.Items.Add(xpath); xpathComboBox.Items.Add(xpath);
} }

4
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XPathQueryPad.cs

@ -20,7 +20,7 @@ namespace ICSharpCode.XmlEditor
{ {
xpathQueryControl = new XPathQueryControl(); xpathQueryControl = new XPathQueryControl();
WorkbenchSingleton.Workbench.ActiveViewContentChanged += ActiveViewContentChanged; WorkbenchSingleton.Workbench.ActiveViewContentChanged += ActiveViewContentChanged;
Properties properties = PropertyService.Get(XPathQueryControlProperties, new Properties()); Properties properties = PropertyService.NestedProperties(XPathQueryControlProperties);
xpathQueryControl.SetMemento(properties); xpathQueryControl.SetMemento(properties);
instance = this; instance = this;
} }
@ -42,7 +42,7 @@ namespace ICSharpCode.XmlEditor
disposed = true; disposed = true;
WorkbenchSingleton.Workbench.ActiveViewContentChanged -= ActiveViewContentChanged; WorkbenchSingleton.Workbench.ActiveViewContentChanged -= ActiveViewContentChanged;
Properties properties = xpathQueryControl.CreateMemento(); Properties properties = xpathQueryControl.CreateMemento();
PropertyService.Set(XPathQueryControlProperties, properties); PropertyService.PropertiesContainer.SetNestedProperties(XPathQueryControlProperties, properties);
xpathQueryControl.Dispose(); xpathQueryControl.Dispose();
} }
} }

4
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlEditorOptions.cs

@ -2,10 +2,12 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Globalization;
using System.IO; using System.IO;
using ICSharpCode.Core; using ICSharpCode.Core;
using System.Globalization;
namespace ICSharpCode.XmlEditor namespace ICSharpCode.XmlEditor
{ {

2
src/AddIns/DisplayBindings/XmlEditor/Project/Src/XmlEditorService.cs

@ -37,7 +37,7 @@ namespace ICSharpCode.XmlEditor
static void CreateXmlEditorProperties() static void CreateXmlEditorProperties()
{ {
xmlEditorProperties = PropertyService.Get(XmlEditorOptions.OptionsProperty, new Properties()); xmlEditorProperties = PropertyService.NestedProperties(XmlEditorOptions.OptionsProperty);
} }
public static bool ShowAttributesWhenFolded { public static bool ShowAttributesWhenFolded {

2
src/AddIns/DisplayBindings/XmlEditor/Project/XmlEditor.csproj

@ -7,7 +7,7 @@
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RootNamespace>ICSharpCode.XmlEditor</RootNamespace> <RootNamespace>ICSharpCode.XmlEditor</RootNamespace>
<AssemblyName>XmlEditor</AssemblyName> <AssemblyName>XmlEditor</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks> <AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<NoStdLib>False</NoStdLib> <NoStdLib>False</NoStdLib>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>

2
src/AddIns/Misc/AddInManager/Project/AddInManager.csproj

@ -16,7 +16,7 @@
<FileAlignment>4096</FileAlignment> <FileAlignment>4096</FileAlignment>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors> <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile> <TargetFrameworkProfile>
</TargetFrameworkProfile> </TargetFrameworkProfile>
</PropertyGroup> </PropertyGroup>

2
src/AddIns/Misc/FiletypeRegisterer/Project/FiletypeRegisterer.csproj

@ -22,7 +22,7 @@
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<FileAlignment>4096</FileAlignment> <FileAlignment>4096</FileAlignment>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors> <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile> <TargetFrameworkProfile>
</TargetFrameworkProfile> </TargetFrameworkProfile>
</PropertyGroup> </PropertyGroup>

3
src/AddIns/Misc/FiletypeRegisterer/Project/FiletypeRegisterer.csproj.user

@ -1,4 +1,5 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup> <PropertyGroup>
<LastOpenVersion>8.0.41115</LastOpenVersion> <LastOpenVersion>8.0.41115</LastOpenVersion>
<ProjectView>ShowAllFiles</ProjectView> <ProjectView>ShowAllFiles</ProjectView>

2
src/AddIns/Misc/HelpViewer/HelpViewer.csproj

@ -7,7 +7,7 @@
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RootNamespace>MSHelpSystem</RootNamespace> <RootNamespace>MSHelpSystem</RootNamespace>
<AssemblyName>HelpViewer</AssemblyName> <AssemblyName>HelpViewer</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks> <AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<NoStdLib>False</NoStdLib> <NoStdLib>False</NoStdLib>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>

2
src/AddIns/Misc/RegExpTk/Project/RegExpTk.csproj

@ -18,7 +18,7 @@
<BaseAddress>122683392</BaseAddress> <BaseAddress>122683392</BaseAddress>
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
<FileAlignment>4096</FileAlignment> <FileAlignment>4096</FileAlignment>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile> <TargetFrameworkProfile>
</TargetFrameworkProfile> </TargetFrameworkProfile>
</PropertyGroup> </PropertyGroup>

3
src/AddIns/Misc/RegExpTk/Project/RegExpTk.csproj.user

@ -1,4 +1,5 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<PropertyGroup> <PropertyGroup>
<LastOpenVersion>8.0.41115</LastOpenVersion> <LastOpenVersion>8.0.41115</LastOpenVersion>
<ProjectView>ShowAllFiles</ProjectView> <ProjectView>ShowAllFiles</ProjectView>

2
src/AddIns/Misc/SearchAndReplace/Project/Engine/SearchManager.cs

@ -286,7 +286,7 @@ namespace SearchAndReplace
var editor = GetActiveTextEditor(); var editor = GetActiveTextEditor();
if (editor == null) if (editor == null)
return -1; return -1;
return files.FindIndex(file => editor.FileName.Equals(file)); return Array.IndexOf(files, editor.FileName);
} }
public static SearchRegion CreateSearchRegion(FileName[] files, ISearchStrategy strategy, SearchLocation location) public static SearchRegion CreateSearchRegion(FileName[] files, ISearchStrategy strategy, SearchLocation location)

32
src/AddIns/Misc/SearchAndReplace/Project/SearchOptions.cs

@ -2,6 +2,8 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.AvalonEdit.Search; using ICSharpCode.AvalonEdit.Search;
using ICSharpCode.Core; using ICSharpCode.Core;
@ -29,11 +31,9 @@ namespace SearchAndReplace
set { set {
if (value != FindPattern) { if (value != FindPattern) {
findPattern = value; findPattern = value;
string[] oldPatterns = FindPatterns; List<string> patterns = FindPatterns.ToList();
string[] newPatterns = new string[oldPatterns.Length + 1]; patterns.Insert(0, value);
oldPatterns.CopyTo(newPatterns, 1); FindPatterns = patterns;
newPatterns[0] = value;
FindPatterns = newPatterns;
} }
} }
} }
@ -47,12 +47,12 @@ namespace SearchAndReplace
} }
} }
public static string[] FindPatterns { public static IReadOnlyList<string> FindPatterns {
get { get {
return properties.Get("FindPatterns", new string[0]); return properties.GetList<string>("FindPatterns");
} }
set { set {
properties.Set("FindPatterns", value); properties.SetList("FindPatterns", value);
} }
} }
@ -65,22 +65,20 @@ namespace SearchAndReplace
} }
set { set {
if (value != ReplacePattern) { if (value != ReplacePattern) {
string[] oldPatterns = ReplacePatterns; List<string> patterns = ReplacePatterns.ToList();
string[] newPatterns = new string[oldPatterns.Length + 1]; patterns.Insert(0, value);
oldPatterns.CopyTo(newPatterns, 1); ReplacePatterns = patterns;
newPatterns[0] = value;
ReplacePatterns = newPatterns;
replacePattern = value; replacePattern = value;
} }
} }
} }
public static string[] ReplacePatterns { public static IReadOnlyList<string> ReplacePatterns {
get { get {
return properties.Get("ReplacePatterns", new string[0]); return properties.GetList<string>("ReplacePatterns");
} }
set { set {
properties.Set("ReplacePatterns", value); properties.SetList("ReplacePatterns", value);
} }
} }
@ -150,7 +148,7 @@ namespace SearchAndReplace
static SearchOptions() static SearchOptions()
{ {
properties = PropertyService.Get(searchPropertyKey, new Properties()); properties = PropertyService.NestedProperties(searchPropertyKey);
} }
} }
} }

6
src/AddIns/Misc/UsageDataCollector/UsageDataCollector.AddIn/AnalyticsMonitor.cs

@ -28,7 +28,7 @@ namespace ICSharpCode.UsageDataCollector
public static bool EnabledIsUndecided { public static bool EnabledIsUndecided {
get { get {
return string.IsNullOrEmpty(PropertyService.Get("ICSharpCode.UsageDataCollector.Enabled")); return PropertyService.Contains("ICSharpCode.UsageDataCollector.Enabled");
} }
} }
@ -37,10 +37,10 @@ namespace ICSharpCode.UsageDataCollector
/// </summary> /// </summary>
public static bool Enabled { public static bool Enabled {
get { get {
return string.Equals(PropertyService.Get("ICSharpCode.UsageDataCollector.Enabled"), bool.TrueString, StringComparison.OrdinalIgnoreCase); return PropertyService.Get("ICSharpCode.UsageDataCollector.Enabled", false);
} }
set { set {
PropertyService.Set("ICSharpCode.UsageDataCollector.Enabled", value.ToString()); PropertyService.Set("ICSharpCode.UsageDataCollector.Enabled", value);
// Initially opening the session takes some time; which is bad for the startpage // Initially opening the session takes some time; which is bad for the startpage
// because the animation would start with a delay. We solve this by calling Open/CloseSession // because the animation would start with a delay. We solve this by calling Open/CloseSession
// on a background thread. // on a background thread.

1
src/AddIns/Misc/UsageDataCollector/UsageDataCollector.AddIn/StartPageMessage.xaml.cs

@ -38,6 +38,7 @@ namespace ICSharpCode.UsageDataCollector
mainPanel.IsCollapsed = true; mainPanel.IsCollapsed = true;
acceptedMessage.IsCollapsed = !accepted; acceptedMessage.IsCollapsed = !accepted;
declinedMessage.IsCollapsed = accepted; declinedMessage.IsCollapsed = accepted;
Core.PropertyService.Save();
} }
public static readonly DependencyProperty HeaderProperty = HeaderedContentControl.HeaderProperty.AddOwner(typeof(StartPageMessage)); public static readonly DependencyProperty HeaderProperty = HeaderedContentControl.HeaderProperty.AddOwner(typeof(StartPageMessage));

2
src/AddIns/Misc/UsageDataCollector/UsageDataCollector.AddIn/UsageDataCollector.AddIn.csproj

@ -7,7 +7,7 @@
<OutputType>Library</OutputType> <OutputType>Library</OutputType>
<RootNamespace>ICSharpCode.UsageDataCollector</RootNamespace> <RootNamespace>ICSharpCode.UsageDataCollector</RootNamespace>
<AssemblyName>UsageDataCollector.AddIn</AssemblyName> <AssemblyName>UsageDataCollector.AddIn</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<OutputPath>..\..\..\..\..\AddIns\Misc\UsageDataCollector\</OutputPath> <OutputPath>..\..\..\..\..\AddIns\Misc\UsageDataCollector\</OutputPath>
<AllowUnsafeBlocks>False</AllowUnsafeBlocks> <AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<NoStdLib>False</NoStdLib> <NoStdLib>False</NoStdLib>

2
src/AddIns/VersionControl/SubversionAddIn/Src/AddInOptions.cs

@ -14,7 +14,7 @@ namespace ICSharpCode.Svn
static AddInOptions() static AddInOptions()
{ {
properties = PropertyService.Get(OptionsProperty, new Properties()); properties = PropertyService.NestedProperties(OptionsProperty);
} }
#region Properties #region Properties

2
src/Main/Base/Project/Src/Commands/AutostartCommands.cs

@ -87,7 +87,7 @@ namespace ICSharpCode.SharpDevelop.Commands
// save the workbench memento in the ide properties // save the workbench memento in the ide properties
try { try {
PropertyService.Set(workbenchMemento, WorkbenchSingleton.Workbench.CreateMemento()); PropertyService.SetNestedProperties(workbenchMemento, WorkbenchSingleton.Workbench.CreateMemento());
} catch (Exception e) { } catch (Exception e) {
MessageService.ShowException(e, "Exception while saving workbench state."); MessageService.ShowException(e, "Exception while saving workbench state.");
} }

8
src/Main/Base/Project/Src/Gui/BrowserDisplayBinding/HtmlViewPane.cs

@ -4,8 +4,8 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Linq;
using System.Windows.Forms; using System.Windows.Forms;
using ICSharpCode.Core; using ICSharpCode.Core;
using ICSharpCode.Core.WinForms; using ICSharpCode.Core.WinForms;
using ICSharpCode.SharpDevelop.Gui; using ICSharpCode.SharpDevelop.Gui;
@ -244,7 +244,7 @@ namespace ICSharpCode.SharpDevelop.BrowserDisplayBinding
SetUrlBox(comboBox); SetUrlBox(comboBox);
comboBox.DropDownStyle = ComboBoxStyle.DropDown; comboBox.DropDownStyle = ComboBoxStyle.DropDown;
comboBox.Items.Clear(); comboBox.Items.Clear();
comboBox.Items.AddRange(PropertyService.Get("Browser.URLBoxHistory", new string[0])); comboBox.Items.AddRange(PropertyService.GetList<string>("Browser.URLBoxHistory"));
comboBox.AutoCompleteMode = AutoCompleteMode.Suggest; comboBox.AutoCompleteMode = AutoCompleteMode.Suggest;
comboBox.AutoCompleteSource = AutoCompleteSource.HistoryList; comboBox.AutoCompleteSource = AutoCompleteSource.HistoryList;
} }
@ -276,7 +276,7 @@ namespace ICSharpCode.SharpDevelop.BrowserDisplayBinding
comboBox.Items.Remove(text); comboBox.Items.Remove(text);
comboBox.Items.Insert(0, text); comboBox.Items.Insert(0, text);
// Add to URLBoxHistory: // Add to URLBoxHistory:
string[] history = PropertyService.Get("Browser.URLBoxHistory", new string[0]); string[] history = PropertyService.GetList<string>("Browser.URLBoxHistory").ToArray();
int pos = Array.IndexOf(history, text); int pos = Array.IndexOf(history, text);
if (pos < 0 && history.Length >= 20) { if (pos < 0 && history.Length >= 20) {
pos = history.Length - 1; // remove last entry and insert new at the beginning pos = history.Length - 1; // remove last entry and insert new at the beginning
@ -292,7 +292,7 @@ namespace ICSharpCode.SharpDevelop.BrowserDisplayBinding
} }
} }
history[0] = text; history[0] = text;
PropertyService.Set("Browser.URLBoxHistory", history); PropertyService.SetList("Browser.URLBoxHistory", history);
} }
} }

5
src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/CodeGenerationPanel.cs

@ -15,7 +15,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
{ {
SetupFromXmlStream(this.GetType().Assembly.GetManifestResourceStream("Resources.CodeGenerationOptionsPanel.xfrm")); SetupFromXmlStream(this.GetType().Assembly.GetManifestResourceStream("Resources.CodeGenerationOptionsPanel.xfrm"));
Properties p = (Properties)PropertyService.Get(codeGenerationProperty, new Properties()); Properties p = PropertyService.NestedProperties(codeGenerationProperty);
((CheckBox)ControlDictionary["generateAdditonalCommentsCheckBox"]).Checked = p.Get("GenerateAdditionalComments", true); ((CheckBox)ControlDictionary["generateAdditonalCommentsCheckBox"]).Checked = p.Get("GenerateAdditionalComments", true);
((CheckBox)ControlDictionary["generateDocCommentsCheckBox"]).Checked = p.Get("GenerateDocumentComments", true); ((CheckBox)ControlDictionary["generateDocCommentsCheckBox"]).Checked = p.Get("GenerateDocumentComments", true);
@ -28,14 +28,13 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
public override bool StorePanelContents() public override bool StorePanelContents()
{ {
Properties p = (Properties)PropertyService.Get(codeGenerationProperty, new Properties()); Properties p = PropertyService.NestedProperties(codeGenerationProperty);
p.Set("GenerateAdditionalComments", ((CheckBox)ControlDictionary["generateAdditonalCommentsCheckBox"]).Checked); p.Set("GenerateAdditionalComments", ((CheckBox)ControlDictionary["generateAdditonalCommentsCheckBox"]).Checked);
p.Set("GenerateDocumentComments", ((CheckBox)ControlDictionary["generateDocCommentsCheckBox"]).Checked); p.Set("GenerateDocumentComments", ((CheckBox)ControlDictionary["generateDocCommentsCheckBox"]).Checked);
p.Set("UseFullyQualifiedNames", ((CheckBox)ControlDictionary["useFullTypeNamesCheckBox"]).Checked); p.Set("UseFullyQualifiedNames", ((CheckBox)ControlDictionary["useFullTypeNamesCheckBox"]).Checked);
p.Set("BlankLinesBetweenMembers", ((CheckBox)ControlDictionary["blankLinesBetweenMemberCheckBox"]).Checked); p.Set("BlankLinesBetweenMembers", ((CheckBox)ControlDictionary["blankLinesBetweenMemberCheckBox"]).Checked);
p.Set("ElseOnClosing", ((CheckBox)ControlDictionary["elseOnClosingCheckbox"]).Checked); p.Set("ElseOnClosing", ((CheckBox)ControlDictionary["elseOnClosingCheckbox"]).Checked);
p.Set("StartBlockOnSameLine", ((CheckBox)ControlDictionary["startBlockOnTheSameLineCheckBox"]).Checked); p.Set("StartBlockOnSameLine", ((CheckBox)ControlDictionary["startBlockOnTheSameLineCheckBox"]).Checked);
PropertyService.Set(codeGenerationProperty, p);
return true; return true;
} }
} }

5
src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/OutputWindowOptionsPanel.cs

@ -24,7 +24,7 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
{ {
SetupFromXmlStream(this.GetType().Assembly.GetManifestResourceStream("Resources.OutputWindowOptionsPanel.xfrm")); SetupFromXmlStream(this.GetType().Assembly.GetManifestResourceStream("Resources.OutputWindowOptionsPanel.xfrm"));
Properties properties = (Properties)PropertyService.Get(OutputWindowsProperty, new Properties()); Properties properties = PropertyService.NestedProperties(OutputWindowsProperty);
fontSelectionPanel = new FontSelectionPanel(); fontSelectionPanel = new FontSelectionPanel();
fontSelectionPanel.Dock = DockStyle.Fill; fontSelectionPanel.Dock = DockStyle.Fill;
ControlDictionary["FontGroupBox"].Controls.Add(fontSelectionPanel); ControlDictionary["FontGroupBox"].Controls.Add(fontSelectionPanel);
@ -35,13 +35,12 @@ namespace ICSharpCode.SharpDevelop.Gui.OptionPanels
public override bool StorePanelContents() public override bool StorePanelContents()
{ {
Properties properties = (Properties)PropertyService.Get(OutputWindowsProperty, new Properties()); Properties properties = PropertyService.NestedProperties(OutputWindowsProperty);
properties.Set("WordWrap", ((CheckBox)ControlDictionary["wordWrapCheckBox"]).Checked); properties.Set("WordWrap", ((CheckBox)ControlDictionary["wordWrapCheckBox"]).Checked);
string currentFontString = fontSelectionPanel.CurrentFontString; string currentFontString = fontSelectionPanel.CurrentFontString;
if (currentFontString != null) if (currentFontString != null)
properties.Set("DefaultFont", currentFontString); properties.Set("DefaultFont", currentFontString);
PropertyService.Set(OutputWindowsProperty, properties);
return true; return true;
} }
} }

46
src/Main/Base/Project/Src/Gui/Dialogs/SharpDevelopColorDialog.cs

@ -3,9 +3,9 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text; using System.Text;
using System.Windows.Forms; using System.Windows.Forms;
using ICSharpCode.Core; using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop.Gui namespace ICSharpCode.SharpDevelop.Gui
@ -22,46 +22,6 @@ namespace ICSharpCode.SharpDevelop.Gui
LoadCustomColors(); LoadCustomColors();
} }
/// <summary>
/// Converts a string of colors separated by the '|' character
/// into an array of colors.
/// </summary>
public static int[] CustomColorsFromString(string s)
{
if (String.IsNullOrEmpty(s)) {
return null;
}
string[] items = s.Split('|');
List<int> colors = new List<int>();
foreach (string item in items) {
int color;
if (Int32.TryParse(item, out color)) {
colors.Add(color);
}
}
return colors.ToArray();
}
/// <summary>
/// Converts an integer array of colors into a string.
/// </summary>
public static string CustomColorsToString(int[] colors)
{
if (colors == null) {
return String.Empty;
}
StringBuilder s = new StringBuilder();
for (int i = 0; i < colors.Length; ++i) {
if (i != 0) {
s.Append('|');
}
s.Append(colors[i]);
}
return s.ToString();
}
protected override bool RunDialog(IntPtr hwndOwner) protected override bool RunDialog(IntPtr hwndOwner)
{ {
bool result = base.RunDialog(hwndOwner); bool result = base.RunDialog(hwndOwner);
@ -71,12 +31,12 @@ namespace ICSharpCode.SharpDevelop.Gui
void LoadCustomColors() void LoadCustomColors()
{ {
CustomColors = CustomColorsFromString(PropertyService.Get(CustomColorsPropertyName)); CustomColors = PropertyService.GetList<int>(CustomColorsPropertyName).ToArray();
} }
void SaveCustomColors() void SaveCustomColors()
{ {
PropertyService.Set(CustomColorsPropertyName, CustomColorsToString(CustomColors)); PropertyService.SetList(CustomColorsPropertyName, CustomColors);
} }
public bool? ShowWpfDialog() public bool? ShowWpfDialog()

7
src/Main/Base/Project/Src/Gui/Pads/CompilerMessageView/CompilerMessageView.cs

@ -3,6 +3,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -204,7 +205,7 @@ namespace ICSharpCode.SharpDevelop.Gui
textEditor.ContextMenu = MenuService.CreateContextMenu(this, "/SharpDevelop/Pads/CompilerMessageView/ContextMenu"); textEditor.ContextMenu = MenuService.CreateContextMenu(this, "/SharpDevelop/Pads/CompilerMessageView/ContextMenu");
properties = (Properties)PropertyService.Get(OutputWindowOptionsPanel.OutputWindowsProperty, new Properties()); properties = PropertyService.NestedProperties(OutputWindowOptionsPanel.OutputWindowsProperty);
var font = FontSelectionPanel.ParseFont(properties.Get("DefaultFont", Core.WinForms.WinFormsResourceService.DefaultMonospacedFont.ToString()).ToString()); var font = FontSelectionPanel.ParseFont(properties.Get("DefaultFont", Core.WinForms.WinFormsResourceService.DefaultMonospacedFont.ToString()).ToString());
@ -396,11 +397,11 @@ namespace ICSharpCode.SharpDevelop.Gui
/// </summary> /// </summary>
void PropertyChanged(object sender, PropertyChangedEventArgs e) void PropertyChanged(object sender, PropertyChangedEventArgs e)
{ {
if (e.Key == "WordWrap") { if (e.PropertyName == "WordWrap") {
SetWordWrap(); SetWordWrap();
ToolBarService.UpdateStatus(toolStrip.Items); ToolBarService.UpdateStatus(toolStrip.Items);
} }
if (e.Key == "DefaultFont") { if (e.PropertyName == "DefaultFont") {
var font = FontSelectionPanel.ParseFont(properties.Get("DefaultFont", Core.WinForms.WinFormsResourceService.DefaultMonospacedFont.ToString()).ToString()); var font = FontSelectionPanel.ParseFont(properties.Get("DefaultFont", Core.WinForms.WinFormsResourceService.DefaultMonospacedFont.ToString()).ToString());
textEditor.FontFamily = new FontFamily(font.FontFamily.Name); textEditor.FontFamily = new FontFamily(font.FontFamily.Name);

2
src/Main/Base/Project/Src/Gui/Pads/ErrorList/ErrorListPad.cs

@ -74,7 +74,7 @@ namespace ICSharpCode.SharpDevelop.Gui
public ErrorListPad() public ErrorListPad()
{ {
instance = this; instance = this;
properties = PropertyService.Get("ErrorListPad", new Properties()); properties = PropertyService.NestedProperties("ErrorListPad");
RedrawContent(); RedrawContent();
ResourceService.LanguageChanged += delegate { RedrawContent(); }; ResourceService.LanguageChanged += delegate { RedrawContent(); };

7
src/Main/Base/Project/Src/Gui/Workbench/WpfWorkbench.cs

@ -517,7 +517,7 @@ namespace ICSharpCode.SharpDevelop.Gui
Properties memento = mementoCapable.CreateMemento(); Properties memento = mementoCapable.CreateMemento();
Properties p = this.LoadOrCreateViewContentMementos(); Properties p = this.LoadOrCreateViewContentMementos();
p.Set(key, memento); p.SetNestedProperties(key, memento);
FileUtility.ObservedSave(new NamedFileOperationDelegate(p.Save), this.ViewContentMementosFileName, FileErrorPolicy.Inform); FileUtility.ObservedSave(new NamedFileOperationDelegate(p.Save), this.ViewContentMementosFileName, FileErrorPolicy.Inform);
} }
} }
@ -533,10 +533,7 @@ namespace ICSharpCode.SharpDevelop.Gui
string key = GetMementoKeyName(viewContent); string key = GetMementoKeyName(viewContent);
LoggingService.Debug("Trying to restore memento of '" + viewContent.ToString() + "' from key '" + key + "'"); LoggingService.Debug("Trying to restore memento of '" + viewContent.ToString() + "' from key '" + key + "'");
Properties memento = this.LoadOrCreateViewContentMementos().Get<Properties>(key, null); mementoCapable.SetMemento(this.LoadOrCreateViewContentMementos().NestedProperties(key));
if (memento != null) {
mementoCapable.SetMemento(memento);
}
} catch (Exception e) { } catch (Exception e) {
MessageService.ShowException(e, "Can't get/set memento"); MessageService.ShowException(e, "Can't get/set memento");
} }

2
src/Main/Base/Project/Src/Gui/WorkbenchSingleton.cs

@ -83,7 +83,7 @@ namespace ICSharpCode.SharpDevelop.Gui
} }
workbench.Initialize(); workbench.Initialize();
workbench.SetMemento(PropertyService.Get(workbenchMemento, new Properties())); workbench.SetMemento(PropertyService.NestedProperties(workbenchMemento));
workbench.WorkbenchLayout = layout; workbench.WorkbenchLayout = layout;
ApplicationStateInfoService.RegisterStateGetter(activeContentState, delegate { return WorkbenchSingleton.Workbench.ActiveContent; }); ApplicationStateInfoService.RegisterStateGetter(activeContentState, delegate { return WorkbenchSingleton.Workbench.ActiveContent; });

2
src/Main/Base/Project/Src/Project/AbstractProject.cs

@ -76,7 +76,7 @@ namespace ICSharpCode.SharpDevelop.Project
public void SetMemento(Properties memento) public void SetMemento(Properties memento)
{ {
// other project data // other project data
this.ProjectSpecificProperties = memento.Get("projectSavedData", new Properties()); this.ProjectSpecificProperties = memento.NestedProperties("projectSavedData");
GetOrCreateBehavior().SetMemento(memento); GetOrCreateBehavior().SetMemento(memento);
} }
#endregion #endregion

10
src/Main/Base/Project/Src/Project/Behaviors/DefaultProjectBehavior.cs

@ -93,17 +93,17 @@ namespace ICSharpCode.SharpDevelop.Project
// breakpoints and files // breakpoints and files
Properties properties = new Properties(); Properties properties = new Properties();
properties.Set("bookmarks", ICSharpCode.SharpDevelop.Bookmarks.BookmarkManager.GetProjectBookmarks(Project).ToArray()); properties.SetList("bookmarks", ICSharpCode.SharpDevelop.Bookmarks.BookmarkManager.GetProjectBookmarks(Project));
List<string> files = new List<string>(); List<string> files = new List<string>();
foreach (string fileName in FileService.GetOpenFiles()) { foreach (string fileName in FileService.GetOpenFiles()) {
if (fileName != null && Project.IsFileInProject(fileName)) { if (fileName != null && Project.IsFileInProject(fileName)) {
files.Add(fileName); files.Add(fileName);
} }
} }
properties.Set("files", files.ToArray()); properties.SetList("files", files);
// other project data // other project data
properties.Set("projectSavedData", Project.ProjectSpecificProperties ?? new Properties()); properties.SetNestedProperties("projectSavedData", Project.ProjectSpecificProperties.Clone());
return properties; return properties;
} }
@ -112,11 +112,11 @@ namespace ICSharpCode.SharpDevelop.Project
{ {
WorkbenchSingleton.AssertMainThread(); WorkbenchSingleton.AssertMainThread();
foreach (ICSharpCode.SharpDevelop.Bookmarks.SDBookmark mark in memento.Get("bookmarks", new ICSharpCode.SharpDevelop.Bookmarks.SDBookmark[0])) { foreach (var mark in memento.GetList<ICSharpCode.SharpDevelop.Bookmarks.SDBookmark>("bookmarks")) {
ICSharpCode.SharpDevelop.Bookmarks.BookmarkManager.AddMark(mark); ICSharpCode.SharpDevelop.Bookmarks.BookmarkManager.AddMark(mark);
} }
List<string> filesToOpen = new List<string>(); List<string> filesToOpen = new List<string>();
foreach (string fileName in memento.Get("files", new string[0])) { foreach (string fileName in memento.GetList<string>("files")) {
if (File.Exists(fileName)) { if (File.Exists(fileName)) {
filesToOpen.Add(fileName); filesToOpen.Add(fileName);
} }

2
src/Main/Base/Project/Src/Services/AmbienceService/AmbienceService.cs

@ -16,7 +16,7 @@ namespace ICSharpCode.SharpDevelop
public static Properties CodeGenerationProperties { public static Properties CodeGenerationProperties {
get { get {
return PropertyService.Get(codeGenerationProperty, new Properties()); return PropertyService.NestedProperties(codeGenerationProperty);
} }
} }

8
src/Main/Base/Project/Src/Services/DisplayBinding/DisplayBindingService.cs

@ -25,8 +25,8 @@ namespace ICSharpCode.SharpDevelop
internal static void InitializeService() internal static void InitializeService()
{ {
bindings = AddInTree.BuildItems<DisplayBindingDescriptor>(displayBindingPath, null, true); bindings = AddInTree.BuildItems<DisplayBindingDescriptor>(displayBindingPath, null, true);
displayBindingServiceProperties = PropertyService.Get("DisplayBindingService", new Properties()); displayBindingServiceProperties = PropertyService.NestedProperties("DisplayBindingService");
foreach (ExternalProcessDisplayBinding binding in displayBindingServiceProperties.Get("ExternalProcesses", new ExternalProcessDisplayBinding[0])) { foreach (var binding in displayBindingServiceProperties.GetList<ExternalProcessDisplayBinding>("ExternalProcesses")) {
if (binding != null) { if (binding != null) {
AddExternalProcessDisplayBindingInternal(binding); AddExternalProcessDisplayBindingInternal(binding);
} }
@ -45,7 +45,7 @@ namespace ICSharpCode.SharpDevelop
static void SaveExternalProcessDisplayBindings() static void SaveExternalProcessDisplayBindings()
{ {
displayBindingServiceProperties.Set("ExternalProcesses", externalProcessDisplayBindings.ToArray()); displayBindingServiceProperties.SetList("ExternalProcesses", externalProcessDisplayBindings);
} }
static DisplayBindingDescriptor AddExternalProcessDisplayBindingInternal(ExternalProcessDisplayBinding binding) static DisplayBindingDescriptor AddExternalProcessDisplayBindingInternal(ExternalProcessDisplayBinding binding)
@ -98,7 +98,7 @@ namespace ICSharpCode.SharpDevelop
{ {
WorkbenchSingleton.AssertMainThread(); WorkbenchSingleton.AssertMainThread();
string defaultCommandID = displayBindingServiceProperties.Get("Default" + Path.GetExtension(filename).ToLowerInvariant()) as string; string defaultCommandID = displayBindingServiceProperties.Get("Default" + Path.GetExtension(filename).ToLowerInvariant(), string.Empty);
if (!string.IsNullOrEmpty(defaultCommandID)) { if (!string.IsNullOrEmpty(defaultCommandID)) {
foreach (DisplayBindingDescriptor binding in bindings) { foreach (DisplayBindingDescriptor binding in bindings) {
if (binding.Id == defaultCommandID) { if (binding.Id == defaultCommandID) {

4
src/Main/Base/Project/Src/Services/File/FileService.cs

@ -26,7 +26,7 @@ namespace ICSharpCode.SharpDevelop
public static RecentOpen RecentOpen { public static RecentOpen RecentOpen {
get { get {
if (recentOpen == null) { if (recentOpen == null) {
recentOpen = RecentOpen.FromXmlElement(PropertyService.Get("RecentOpen", new Properties())); recentOpen = RecentOpen.FromXmlElement(PropertyService.NestedProperties("RecentOpen"));
} }
return recentOpen; return recentOpen;
} }
@ -41,7 +41,7 @@ namespace ICSharpCode.SharpDevelop
internal static void Unload() internal static void Unload()
{ {
if (recentOpen != null) { if (recentOpen != null) {
PropertyService.Set("RecentOpen", recentOpen.ToProperties()); PropertyService.SetNestedProperties("RecentOpen", recentOpen.ToProperties());
} }
ProjectService.SolutionLoaded -= ProjectServiceSolutionLoaded; ProjectService.SolutionLoaded -= ProjectServiceSolutionLoaded;
ParserService.LoadSolutionProjectsThreadEnded -= ParserServiceLoadSolutionProjectsThreadEnded; ParserService.LoadSolutionProjectsThreadEnded -= ParserServiceLoadSolutionProjectsThreadEnded;

14
src/Main/Base/Project/Src/Services/File/RecentOpen.cs

@ -48,14 +48,8 @@ namespace ICSharpCode.SharpDevelop
// don't check whether files exist because that might be slow (e.g. if file is on network // don't check whether files exist because that might be slow (e.g. if file is on network
// drive that's unavailable) // drive that's unavailable)
// if one of these entries is a string, then it's from a previous SharpDevelop version - don't try loading it lastfile.AddRange(p.GetList<string>("Files"));
if (p.Contains("Files") && !(p.Get("Files") is string)) { lastproject.AddRange(p.GetList<string>("Projects"));
lastfile.AddRange(p.Get("Files", new string[0]));
}
if (p.Contains("Projects") && !(p.Get("Files") is string)) {
lastproject.AddRange(p.Get("Projects", new string[0]));
}
} }
public void AddLastFile(string name) public void AddLastFile(string name)
@ -107,8 +101,8 @@ namespace ICSharpCode.SharpDevelop
public Properties ToProperties() public Properties ToProperties()
{ {
Properties p = new Properties(); Properties p = new Properties();
p.Set("Files", lastfile.ToArray()); p.SetList("Files", lastfile);
p.Set("Projects", lastproject.ToArray()); p.SetList("Projects", lastproject);
return p; return p;
} }

4
src/Main/Base/Project/Src/Services/ParserService/CodeCompletionOptions.cs

@ -6,14 +6,12 @@ using ICSharpCode.Core;
namespace ICSharpCode.SharpDevelop namespace ICSharpCode.SharpDevelop
{ {
// TODO: what is this class doing in the ParserService ??
/// <summary> /// <summary>
/// Class containing static properties for the code completion options. /// Class containing static properties for the code completion options.
/// </summary> /// </summary>
public static class CodeCompletionOptions public static class CodeCompletionOptions
{ {
static Properties properties = PropertyService.Get("CodeCompletionOptions", new Properties()); static Properties properties = PropertyService.NestedProperties("CodeCompletionOptions");
public static Properties Properties { public static Properties Properties {
get { get {

9
src/Main/Base/Project/Src/Services/ParserService/ParserService.cs

@ -170,8 +170,13 @@ namespace ICSharpCode.SharpDevelop.Parser
/// This property is thread-safe. /// This property is thread-safe.
/// </summary> /// </summary>
public static string[] TaskListTokens { public static string[] TaskListTokens {
get { return PropertyService.Get("SharpDevelop.TaskListTokens", DefaultTaskListTokens); } get {
set { PropertyService.Set("SharpDevelop.TaskListTokens", value); } if (PropertyService.Contains("SharpDevelop.TaskListTokens"))
return PropertyService.GetList<string>("SharpDevelop.TaskListTokens").ToArray();
else
return DefaultTaskListTokens;
}
set { PropertyService.SetList("SharpDevelop.TaskListTokens", value); }
} }
/// <summary> /// <summary>

23
src/Main/Base/Project/Src/Util/ExtensionMethods.cs

@ -110,6 +110,15 @@ namespace ICSharpCode.SharpDevelop
list.Add(o); list.Add(o);
} }
/// <summary>
/// Adds all <paramref name="elements"/> to <paramref name="list"/>.
/// </summary>
public static void AddRange(this WinForms.ComboBox.ObjectCollection list, IEnumerable elements)
{
foreach (var o in elements)
list.Add(o);
}
public static ReadOnlyCollection<T> AsReadOnly<T>(this IList<T> arr) public static ReadOnlyCollection<T> AsReadOnly<T>(this IList<T> arr)
{ {
return new ReadOnlyCollection<T>(arr); return new ReadOnlyCollection<T>(arr);
@ -471,6 +480,20 @@ namespace ICSharpCode.SharpDevelop
return -1; return -1;
} }
/// <summary>
/// Returns the index of the first element for which <paramref name="predicate"/> returns true.
/// If none of the items in the list fits the <paramref name="predicate"/>, -1 is returned.
/// </summary>
public static int FindIndex<T>(this IReadOnlyList<T> list, Func<T, bool> predicate)
{
for (int i = 0; i < list.Count; i++) {
if (predicate(list[i]))
return i;
}
return -1;
}
/// <summary> /// <summary>
/// Adds item to the list if the item is not null. /// Adds item to the list if the item is not null.
/// </summary> /// </summary>

1
src/Main/Base/Test/ICSharpCode.SharpDevelop.Tests.csproj

@ -155,7 +155,6 @@
<Compile Include="NavigationServiceTests\INavigationPointTextFixture.cs" /> <Compile Include="NavigationServiceTests\INavigationPointTextFixture.cs" />
<Compile Include="NavigationServiceTests\TestNavigationPoint.cs" /> <Compile Include="NavigationServiceTests\TestNavigationPoint.cs" />
<Compile Include="NavigationServiceTests\NavigationServiceTestFixture.cs" /> <Compile Include="NavigationServiceTests\NavigationServiceTestFixture.cs" />
<Compile Include="SharpDevelopColorDialogTests.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\..\Libraries\AvalonEdit\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj"> <ProjectReference Include="..\..\..\Libraries\AvalonEdit\ICSharpCode.AvalonEdit\ICSharpCode.AvalonEdit.csproj">

78
src/Main/Base/Test/SharpDevelopColorDialogTests.cs

@ -1,78 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using ICSharpCode.SharpDevelop.Gui;
using NUnit.Framework;
using System;
namespace ICSharpCode.SharpDevelop.Tests
{
[TestFixture]
public class SharpDevelopColorDialogTests
{
[Test]
public void NullString()
{
Assert.IsNull(SharpDevelopColorDialog.CustomColorsFromString(null));
}
[Test]
public void EmptyString()
{
Assert.IsNull(SharpDevelopColorDialog.CustomColorsFromString(String.Empty));
}
[Test]
public void OneColorInString()
{
int[] colors = SharpDevelopColorDialog.CustomColorsFromString("34");
Assert.AreEqual(1, colors.Length);
Assert.AreEqual(34, colors[0]);
}
[Test]
public void TwoColorsInString()
{
int[] colors = SharpDevelopColorDialog.CustomColorsFromString("20|30");
Assert.AreEqual(2, colors.Length);
Assert.AreEqual(20, colors[0]);
Assert.AreEqual(30, colors[1]);
}
[Test]
public void SecondColorIsInvalid()
{
int[] colors = SharpDevelopColorDialog.CustomColorsFromString("20|Test");
Assert.AreEqual(1, colors.Length);
Assert.AreEqual(20, colors[0]);
}
[Test]
public void FirstColorIsInvalid()
{
int[] colors = SharpDevelopColorDialog.CustomColorsFromString("Test|20");
Assert.AreEqual(1, colors.Length);
Assert.AreEqual(20, colors[0]);
}
[Test]
public void NullIntColorsArray()
{
Assert.AreEqual(String.Empty, SharpDevelopColorDialog.CustomColorsToString(null));
}
[Test]
public void OneCustomColor()
{
int[] colors = new int[] { 10 };
Assert.AreEqual("10", SharpDevelopColorDialog.CustomColorsToString(colors));
}
[Test]
public void TwoCustomColors()
{
int[] colors = new int[] { 10, 20 };
Assert.AreEqual("10|20", SharpDevelopColorDialog.CustomColorsToString(colors));
}
}
}

2
src/Main/Base/Test/Utils/MockTextMarker.cs

@ -49,7 +49,7 @@ namespace ICSharpCode.SharpDevelop.Tests.Utils
public Nullable<Color> BackgroundColor { get; set; } public Nullable<Color> BackgroundColor { get; set; }
public Nullable<Color> ForegroundColor { get; set; } public Nullable<Color> ForegroundColor { get; set; }
public TextMarkerType MarkerType { get; set; } public TextMarkerTypes MarkerTypes { get; set; }
public Color MarkerColor { get; set; } public Color MarkerColor { get; set; }
public object Tag { get; set; } public object Tag { get; set; }
public object ToolTip { get; set; } public object ToolTip { get; set; }

10
src/Main/Core/Project/ICSharpCode.Core.csproj

@ -22,7 +22,8 @@
<AllowUnsafeBlocks>False</AllowUnsafeBlocks> <AllowUnsafeBlocks>False</AllowUnsafeBlocks>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors> <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<SourceAnalysisOverrideSettingsFile>C:\Users\daniel\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis</SourceAnalysisOverrideSettingsFile> <SourceAnalysisOverrideSettingsFile>C:\Users\daniel\AppData\Roaming\ICSharpCode/SharpDevelop3.0\Settings.SourceAnalysis</SourceAnalysisOverrideSettingsFile>
<TargetFrameworkProfile>Client</TargetFrameworkProfile> <TargetFrameworkProfile>
</TargetFrameworkProfile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@ -56,7 +57,13 @@
<Reference Include="System.Core"> <Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework> <RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference> </Reference>
<Reference Include="System.Runtime.Serialization">
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Configuration\AssemblyInfo.cs" /> <Compile Include="Configuration\AssemblyInfo.cs" />
@ -107,7 +114,6 @@
<Compile Include="Src\Services\MessageService\IMessageService.cs" /> <Compile Include="Src\Services\MessageService\IMessageService.cs" />
<Compile Include="Src\Services\MessageService\MessageService.cs" /> <Compile Include="Src\Services\MessageService\MessageService.cs" />
<Compile Include="Src\Services\PropertyService\Properties.cs" /> <Compile Include="Src\Services\PropertyService\Properties.cs" />
<Compile Include="Src\Services\PropertyService\PropertyChangedEvent.cs" />
<Compile Include="Src\Services\PropertyService\PropertyService.cs" /> <Compile Include="Src\Services\PropertyService\PropertyService.cs" />
<Compile Include="Src\Services\RegistryService\RegistryService.cs" /> <Compile Include="Src\Services\RegistryService\RegistryService.cs" />
<Compile Include="Src\Services\ResourceService\ResourceNotFoundException.cs" /> <Compile Include="Src\Services\ResourceService\ResourceNotFoundException.cs" />

1
src/Main/Core/Project/Src/AddInTree/CoreStartup.cs

@ -200,7 +200,6 @@ namespace ICSharpCode.Core
PropertyService.InitializeService(configDirectory, PropertyService.InitializeService(configDirectory,
dataDirectory ?? Path.Combine(FileUtility.ApplicationRootPath, "data"), dataDirectory ?? Path.Combine(FileUtility.ApplicationRootPath, "data"),
propertiesName); propertiesName);
PropertyService.Load();
ResourceService.InitializeService(Path.Combine(PropertyService.DataDirectory, "resources")); ResourceService.InitializeService(Path.Combine(PropertyService.DataDirectory, "resources"));
StringParser.RegisterStringTagProvider(new AppNameProvider { appName = applicationName }); StringParser.RegisterStringTagProvider(new AppNameProvider { appName = applicationName });
} }

748
src/Main/Core/Project/Src/Services/PropertyService/Properties.cs

@ -5,11 +5,15 @@ using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using System.Diagnostics;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.Serialization;
using System.Text; using System.Text;
using System.Threading;
using System.Xml; using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization; using System.Xml.Serialization;
namespace ICSharpCode.Core namespace ICSharpCode.Core
@ -34,116 +38,462 @@ namespace ICSharpCode.Core
} }
/// <summary> /// <summary>
/// Description of PropertyGroup. /// A container for settings - key/value pairs where keys are strings, and values are arbitrary objects.
/// Instances of this class are thread-safe.
/// </summary> /// </summary>
public class Properties public sealed class Properties : INotifyPropertyChanged, ICloneable
{ {
/// <summary> Needed for support of late deserialization </summary> // Properties instances form a tree due to the nested properties containers.
class SerializedValue { // All nodes in such a tree share the same syncRoot in order to simplify synchronization.
string content; // When an existing node is added to a tree, its syncRoot needs to change.
object syncRoot;
public string Content { Properties parent;
get { return content; } // Objects in the dictionary are one of:
// - string: value stored using TypeConverter
// - XElement: serialized object
// - object[]: a stored list (array elements are null, string or XElement)
// - Properties: nested properties container
Dictionary<string, object> dict = new Dictionary<string, object>();
#region Constructor
public Properties()
{
this.syncRoot = new object();
}
private Properties(Properties parent)
{
this.parent = parent;
this.syncRoot = parent.syncRoot;
}
#endregion
#region PropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string key)
{
var handler = Volatile.Read(ref PropertyChanged);
if (handler != null)
handler(this, new PropertyChangedEventArgs("key"));
}
#endregion
#region IsDirty
bool isDirty;
/// <summary>
/// Gets/Sets whether this properties container is dirty.
/// IsDirty automatically gets set to <c>true</c> when a property in this container (or a nested container)
/// changes.
/// </summary>
public bool IsDirty {
get { return isDirty; }
set {
lock (syncRoot) {
if (value)
MakeDirty();
else
CleanDirty();
}
} }
}
public T Deserialize<T>()
{ void MakeDirty()
XmlSerializer serializer = new XmlSerializer(typeof(T)); {
return (T)serializer.Deserialize(new StringReader(content)); // called within syncroot
if (!isDirty) {
isDirty = true;
if (parent != null)
parent.MakeDirty();
} }
}
public SerializedValue(string content)
{ void CleanDirty()
this.content = content; {
if (isDirty) {
isDirty = false;
foreach (var properties in dict.Values.OfType<Properties>()) {
properties.CleanDirty();
}
} }
} }
#endregion
Dictionary<string, object> properties = new Dictionary<string, object>(); #region Keys/Contains
public IReadOnlyList<string> Keys {
get {
lock (syncRoot) {
return dict.Keys.ToArray();
}
}
}
public string this[string property] { /// <summary>
/// Gets whether this properties instance contains any entry (value, list, or nested container)
/// with the specified key.
/// </summary>
public bool Contains(string key)
{
lock (syncRoot) {
return dict.ContainsKey(key);
}
}
#endregion
#region Get and Set
/// <summary>
/// Retrieves a string value from this Properties-container.
/// Using this indexer is equivalent to calling <c>Get(key, string.Empty)</c>.
/// </summary>
public string this[string key] {
get { get {
return Convert.ToString(Get(property), CultureInfo.InvariantCulture); lock (syncRoot) {
object val;
dict.TryGetValue(key, out val);
return val as string ?? string.Empty;
}
} }
set { set {
Set(property, value); Set(key, value);
} }
} }
public string[] Elements /// <summary>
/// Retrieves a single element from this Properties-container.
/// </summary>
/// <param name="key">Key of the item to retrieve</param>
/// <param name="defaultValue">Default value to be returned if the key is not present.</param>
public T Get<T>(string key, T defaultValue)
{ {
get { lock (syncRoot) {
lock (properties) { object val;
return properties.Keys.ToArray(); if (dict.TryGetValue(key, out val)) {
return (T)Deserialize(val, typeof(T));
} else {
return defaultValue;
}
}
}
/// <summary>
/// Sets a single element in this Properties-container.
/// The element will be serialized using a TypeConverter if possible, or DataContractSerializer otherwise.
/// </summary>
/// <remarks>Setting a key to <c>null</c> has the same effect as calling <see cref="Remove"/>.</remarks>
public void Set<T>(string key, T value)
{
object serializedValue = Serialize(value, typeof(T), key);
SetSerializedValue(key, serializedValue);
}
void SetSerializedValue(string key, object serializedValue)
{
if (serializedValue == null) {
Remove(key);
return;
}
lock (syncRoot) {
object oldValue;
if (dict.TryGetValue(key, out oldValue)) {
if (object.Equals(serializedValue, oldValue))
return;
HandleOldValue(oldValue);
} }
dict[key] = serializedValue;
} }
OnPropertyChanged(key);
} }
#endregion
public object Get(string property) #region GetList/SetList
/// <summary>
/// Retrieves the list of items stored with the specified key.
/// If no entry with the specified key exists, this method returns an empty list.
/// </summary>
/// <remarks>
/// This method returns a copy of the list used internally; you need to call
/// <see cref="SetList"/> if you want to store the changed list.
/// </remarks>
public IReadOnlyList<T> GetList<T>(string key)
{ {
lock (properties) { lock (syncRoot) {
object val; object val;
properties.TryGetValue(property, out val); if (dict.TryGetValue(key, out val)) {
return val; object[] serializedArray = val as object[];
if (serializedArray != null) {
T[] array = new T[serializedArray.Length];
for (int i = 0; i < array.Length; i++) {
array[i] = (T)Deserialize(serializedArray[i], typeof(T));
}
return array;
} else {
LoggingService.Warn("Properties.GetList(" + key + ") - this entry is not a list");
}
}
return new T[0];
} }
} }
public void Set<T>(string property, T value) /// <summary>
/// Sets a list of elements in this Properties-container.
/// The elements will be serialized using a TypeConverter if possible, or DataContractSerializer otherwise.
/// </summary>
/// <remarks>Passing <c>null</c> or an empty list as value has the same effect as calling <see cref="Remove"/>.</remarks>
public void SetList<T>(string key, IEnumerable<T> value)
{
if (value == null) {
Remove(key);
return;
}
T[] array = value.ToArray();
if (array.Length == 0) {
Remove(key);
return;
}
object[] serializedArray = new object[array.Length];
for (int i = 0; i < array.Length; i++) {
serializedArray[i] = Serialize(array[i], typeof(T), null);
}
SetSerializedValue(key, serializedArray);
}
[Obsolete("Use the GetList method instead", true)]
public T[] Get<T>(string key, T[] defaultValue)
{
throw new InvalidOperationException();
}
[Obsolete("Use the SetList method instead", true)]
public void Set<T>(string key, T[] value)
{
throw new InvalidOperationException();
}
[Obsolete("Use the GetList method instead", true)]
public List<T> Get<T>(string key, List<T> defaultValue)
{
throw new InvalidOperationException();
}
[Obsolete("Use the SetList method instead", true)]
public void Set<T>(string key, List<T> value)
{
throw new InvalidOperationException();
}
[Obsolete("Use the GetList method instead", true)]
public ArrayList Get<T>(string key, ArrayList defaultValue)
{
throw new InvalidOperationException();
}
[Obsolete("Use the SetList method instead", true)]
public void Set<T>(string key, ArrayList value)
{
throw new InvalidOperationException();
}
#endregion
#region Serialization
object Serialize(object value, Type sourceType, string key)
{ {
if (property == null)
throw new ArgumentNullException("property");
if (value == null) if (value == null)
throw new ArgumentNullException("value"); return null;
T oldValue = default(T); TypeConverter c = TypeDescriptor.GetConverter(sourceType);
lock (properties) { if (c != null && c.CanConvertTo(typeof(string)) && c.CanConvertFrom(typeof(string))) {
if (!properties.ContainsKey(property)) { return c.ConvertToInvariantString(value);
properties.Add(property, value); }
} else {
oldValue = Get<T>(property, value); var element = new XElement("SerializedObject");
properties[property] = value; if (key != null) {
element.Add(new XAttribute("key", key));
}
var s = new DataContractSerializer(sourceType);
using (var xmlWriter = element.CreateWriter()) {
s.WriteObject(xmlWriter, value);
}
return element;
}
object Deserialize(object serializedVal, Type targetType)
{
if (serializedVal == null)
return null;
XElement element = serializedVal as XElement;
if (element != null) {
var s = new DataContractSerializer(targetType);
using (var xmlReader = element.CreateReader()) {
xmlReader.MoveToContent();
xmlReader.Read(); // skip <SerializedObject>
xmlReader.MoveToContent();
return s.ReadObject(xmlReader);
} }
} else {
string text = serializedVal as string;
if (text == null)
throw new InvalidOperationException("Cannot read a properties container as a single value");
TypeConverter c = TypeDescriptor.GetConverter(targetType);
return c.ConvertFromInvariantString(text);
} }
OnPropertyChanged(new PropertyChangedEventArgs(this, property, oldValue, value));
} }
#endregion
public bool Contains(string property) #region Remove
/// <summary>
/// Removes the entry (value, list, or nested container) with the specified key.
/// </summary>
public bool Remove(string key)
{ {
lock (properties) { bool removed = false;
return properties.ContainsKey(property); lock (syncRoot) {
object oldValue;
if (dict.TryGetValue(key, out oldValue)) {
removed = true;
HandleOldValue(oldValue);
MakeDirty();
}
} }
if (removed)
OnPropertyChanged(key);
return removed;
} }
#endregion
public int Count {
#region Nested Properties
/// <summary>
/// Gets the parent property container.
/// </summary>
public Properties Parent {
get { get {
lock (properties) { lock (syncRoot) {
return properties.Count; return parent;
}
}
}
[Obsolete("Use the NestedProperties method instead", true)]
public Properties Get(string key, Properties defaultValue)
{
throw new InvalidOperationException();
}
[Obsolete("Use the SetNestedProperties method instead", true)]
public void Set(string key, Properties value)
{
throw new InvalidOperationException();
}
/// <summary>
/// Retrieves a nested property container; creating a new one on demand.
/// Multiple calls to this method will return the same instance (unless the entry at this key
/// is overwritten by one of the Set-methods).
/// Changes performed on the nested container will be persisted together with the parent container.
/// </summary>
public Properties NestedProperties(string key)
{
bool isNewContainer = false;
Properties result;
lock (syncRoot) {
object oldValue;
dict.TryGetValue(key, out oldValue);
result = oldValue as Properties;
if (result == null) {
result = new Properties(this);
dict[key] = result;
result.MakeDirty();
} }
} }
if (isNewContainer)
OnPropertyChanged(key);
return result;
} }
public bool Remove(string property) void HandleOldValue(object oldValue)
{ {
lock (properties) { Properties p = oldValue as Properties;
return properties.Remove(property); if (p != null) {
Debug.Assert(p.parent == this);
p.parent = null;
} }
} }
public override string ToString() /// <summary>
/// Attaches the specified properties container as nested properties.
///
/// This method is intended to be used in conjunction with the <see cref="IMementoCapable"/> pattern
/// where a new unattached properties container is created and then later attached to a parent container.
/// </summary>
public void SetNestedProperties(string key, Properties properties)
{ {
lock (properties) { if (properties == null) {
StringBuilder sb = new StringBuilder(); Remove(key);
sb.Append("[Properties:{"); return;
foreach (KeyValuePair<string, object> entry in properties) { }
sb.Append(entry.Key); lock (syncRoot) {
sb.Append("="); for (Properties ancestor = this; ancestor != null; ancestor = ancestor.parent) {
sb.Append(entry.Value); if (ancestor == properties)
sb.Append(","); throw new InvalidOperationException("Cannot add a properties container to itself.");
}
object oldValue;
if (dict.TryGetValue(key, out oldValue)) {
if (oldValue == properties)
return;
HandleOldValue(oldValue);
}
lock (properties.syncRoot) {
if (properties.parent != null)
throw new InvalidOperationException("Cannot attach nested properties that already have a parent.");
MakeDirty();
properties.SetSyncRoot(syncRoot);
properties.parent = this;
dict[key] = properties;
} }
sb.Append("}]");
return sb.ToString();
} }
OnPropertyChanged(key);
} }
public static Properties ReadFromAttributes(XmlReader reader) void SetSyncRoot(object newSyncRoot)
{
this.syncRoot = newSyncRoot;
foreach (var properties in dict.Values.OfType<Properties>()) {
properties.SetSyncRoot(newSyncRoot);
}
}
#endregion
#region Clone
/// <summary>
/// Creates a deep clone of this Properties container.
/// </summary>
public Properties Clone()
{
lock (syncRoot) {
return CloneWithParent(null);
}
}
Properties CloneWithParent(Properties parent)
{
Properties copy = parent != null ? new Properties(parent) : new Properties();
foreach (var pair in dict) {
Properties child = pair.Value as Properties;
if (child != null)
copy.dict.Add(pair.Key, child.CloneWithParent(copy));
else
copy.dict.Add(pair.Key, pair.Value);
}
return copy;
}
object ICloneable.Clone()
{
return Clone();
}
#endregion
#region ReadFromAttributes
internal static Properties ReadFromAttributes(XmlReader reader)
{ {
Properties properties = new Properties(); Properties properties = new Properties();
if (reader.HasAttributes) { if (reader.HasAttributes) {
@ -159,231 +509,109 @@ namespace ICSharpCode.Core
} }
return properties; return properties;
} }
#endregion
internal void ReadProperties(XmlReader reader, string endElement) #region Load/Save
public static Properties Load(string fileName)
{ {
if (reader.IsEmptyElement) { return Load(XDocument.Load(fileName).Root);
return;
}
while (reader.Read()) {
switch (reader.NodeType) {
case XmlNodeType.EndElement:
if (reader.LocalName == endElement) {
return;
}
break;
case XmlNodeType.Element:
string propertyName = reader.LocalName;
if (propertyName == "Properties") {
propertyName = reader.GetAttribute(0);
Properties p = new Properties();
p.ReadProperties(reader, "Properties");
properties[propertyName] = p;
} else if (propertyName == "Array") {
propertyName = reader.GetAttribute(0);
properties[propertyName] = ReadArray(reader);
} else if (propertyName == "SerializedValue") {
propertyName = reader.GetAttribute(0);
properties[propertyName] = new SerializedValue(reader.ReadInnerXml());
} else {
properties[propertyName] = reader.HasAttributes ? reader.GetAttribute(0) : null;
}
break;
}
}
} }
ArrayList ReadArray(XmlReader reader) public static Properties Load(XElement element)
{ {
if (reader.IsEmptyElement) Properties properties = new Properties();
return new ArrayList(0); properties.LoadContents(element.Elements());
ArrayList l = new ArrayList(); return properties;
while (reader.Read()) { }
switch (reader.NodeType) {
case XmlNodeType.EndElement: void LoadContents(IEnumerable<XElement> elements)
if (reader.LocalName == "Array") { {
return l; foreach (var element in elements) {
} string key = (string)element.Attribute("key");
if (key == null)
continue;
switch (element.Name.LocalName) {
case "Property":
dict[key] = element.Value;
break; break;
case XmlNodeType.Element: case "Array":
l.Add(reader.HasAttributes ? reader.GetAttribute(0) : null); dict[key] = LoadArray(element.Elements());
break;
case "SerializedObject":
dict[key] = new XElement(element);
break;
case "Properties":
Properties child = new Properties(this);
child.LoadContents(element.Elements());
dict[key] = child;
break; break;
}
}
return l;
}
public void WriteProperties(XmlWriter writer)
{
lock (properties) {
List<KeyValuePair<string, object>> sortedProperties = new List<KeyValuePair<string, object>>(properties);
sortedProperties.Sort((a, b) => StringComparer.OrdinalIgnoreCase.Compare(a.Key, b.Key));
foreach (KeyValuePair<string, object> entry in sortedProperties) {
object val = entry.Value;
if (val is Properties) {
writer.WriteStartElement("Properties");
writer.WriteAttributeString("name", entry.Key);
((Properties)val).WriteProperties(writer);
writer.WriteEndElement();
} else if (val is Array || val is ArrayList) {
writer.WriteStartElement("Array");
writer.WriteAttributeString("name", entry.Key);
foreach (object o in (IEnumerable)val) {
writer.WriteStartElement("Element");
WriteValue(writer, o);
writer.WriteEndElement();
}
writer.WriteEndElement();
} else if (TypeDescriptor.GetConverter(val).CanConvertFrom(typeof(string))) {
writer.WriteStartElement(entry.Key);
WriteValue(writer, val);
writer.WriteEndElement();
} else if (val is SerializedValue) {
writer.WriteStartElement("SerializedValue");
writer.WriteAttributeString("name", entry.Key);
writer.WriteRaw(((SerializedValue)val).Content);
writer.WriteEndElement();
} else {
writer.WriteStartElement("SerializedValue");
writer.WriteAttributeString("name", entry.Key);
XmlSerializer serializer = new XmlSerializer(val.GetType());
serializer.Serialize(writer, val, null);
writer.WriteEndElement();
}
} }
} }
} }
void WriteValue(XmlWriter writer, object val) static object[] LoadArray(IEnumerable<XElement> elements)
{ {
if (val != null) { List<object> result = new List<object>();
if (val is string) { foreach (var element in elements) {
writer.WriteAttributeString("value", val.ToString()); switch (element.Name.LocalName) {
} else { case "Null":
TypeConverter c = TypeDescriptor.GetConverter(val.GetType()); result.Add(null);
writer.WriteAttributeString("value", c.ConvertToInvariantString(val)); break;
case "Element":
result.Add(element.Value);
break;
case "SerializedObject":
result.Add(new XElement(element));
break;
} }
} }
return result.ToArray();
} }
public void Save(string fileName) public void Save(string fileName)
{ {
XmlTextWriter writer = new XmlTextWriter(fileName, Encoding.UTF8); new XDocument(Save()).Save(fileName);
writer.Formatting = Formatting.Indented;
Save(writer);
}
public void Save(XmlWriter writer)
{
using (writer) {
writer.WriteStartElement("Properties");
WriteProperties(writer);
writer.WriteEndElement();
}
} }
// public void BinarySerialize(BinaryWriter writer) public XElement Save()
// {
// writer.Write((byte)properties.Count);
// foreach (KeyValuePair<string, object> entry in properties) {
// writer.Write(AddInTree.GetNameOffset(entry.Key));
// writer.Write(AddInTree.GetNameOffset(entry.Value.ToString()));
// }
// }
public static Properties Load(string fileName)
{ {
if (!File.Exists(fileName)) { lock (syncRoot) {
return null; return new XElement("Properties", SaveContents());
} }
XmlTextReader reader = new XmlTextReader(fileName);
return Load(reader);
} }
public static Properties Load(XmlReader reader) IReadOnlyList<XElement> SaveContents()
{ {
using (reader) { List<XElement> result = new List<XElement>();
while (reader.Read()){ foreach (var pair in dict) {
if (reader.IsStartElement()) { XAttribute key = new XAttribute("key", pair.Key);
switch (reader.LocalName) { Properties child = pair.Value as Properties;
case "Properties": if (child != null) {
Properties properties = new Properties(); var contents = child.SaveContents();
properties.ReadProperties(reader, "Properties"); if (contents.Count > 0)
return properties; result.Add(new XElement("Properties", key, contents));
} } else if (pair.Value is object[]) {
} object[] array = (object[])pair.Value;
} XElement[] elements = new XElement[array.Length];
} for (int i = 0; i < array.Length; i++) {
return null; XElement obj = array[i] as XElement;
} if (obj != null) {
elements[i] = new XElement(obj);
public T Get<T>(string property, T defaultValue) } else if (array[i] == null) {
{ elements[i] = new XElement("Null");
lock (properties) { } else {
object o; elements[i] = new XElement("Element", (string)array[i]);
if (!properties.TryGetValue(property, out o)) {
properties.Add(property, defaultValue);
return defaultValue;
}
if (o is string && typeof(T) != typeof(string)) {
TypeConverter c = TypeDescriptor.GetConverter(typeof(T));
try {
o = c.ConvertFromInvariantString(o.ToString());
} catch (Exception ex) {
MessageService.ShowWarning("Error loading property '" + property + "': " + ex.Message);
o = defaultValue;
}
properties[property] = o; // store for future look up
} else if (o is ArrayList && typeof(T).IsArray) {
ArrayList list = (ArrayList)o;
Type elementType = typeof(T).GetElementType();
Array arr = System.Array.CreateInstance(elementType, list.Count);
TypeConverter c = TypeDescriptor.GetConverter(elementType);
try {
for (int i = 0; i < arr.Length; ++i) {
if (list[i] != null) {
arr.SetValue(c.ConvertFromInvariantString(list[i].ToString()), i);
}
} }
o = arr;
} catch (Exception ex) {
MessageService.ShowWarning("Error loading property '" + property + "': " + ex.Message);
o = defaultValue;
} }
properties[property] = o; // store for future look up result.Add(new XElement("Array", key, elements));
} else if (!(o is string) && typeof(T) == typeof(string)) { } else if (pair.Value is XElement) {
TypeConverter c = TypeDescriptor.GetConverter(typeof(T)); result.Add(new XElement((XElement)pair.Value));
if (c.CanConvertTo(typeof(string))) { } else {
o = c.ConvertToInvariantString(o); result.Add(new XElement("Property", key, (string)pair.Value));
} else {
o = o.ToString();
}
} else if (o is SerializedValue) {
try {
o = ((SerializedValue)o).Deserialize<T>();
} catch (Exception ex) {
MessageService.ShowWarning("Error loading property '" + property + "': " + ex.Message);
o = defaultValue;
}
properties[property] = o; // store for future look up
}
try {
return (T)o;
} catch (NullReferenceException) {
// can happen when configuration is invalid -> o is null and a value type is expected
return defaultValue;
} }
} }
return result;
} }
#endregion
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null) {
PropertyChanged(this, e);
}
}
public event PropertyChangedEventHandler PropertyChanged;
} }
} }

61
src/Main/Core/Project/Src/Services/PropertyService/PropertyChangedEvent.cs

@ -1,61 +0,0 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
namespace ICSharpCode.Core
{
public delegate void PropertyChangedEventHandler(object sender, PropertyChangedEventArgs e);
public class PropertyChangedEventArgs : EventArgs
{
Properties properties;
string key;
object newValue;
object oldValue;
/// <returns>
/// returns the changed property object
/// </returns>
public Properties Properties {
get {
return properties;
}
}
/// <returns>
/// The key of the changed property
/// </returns>
public string Key {
get {
return key;
}
}
/// <returns>
/// The new value of the property
/// </returns>
public object NewValue {
get {
return newValue;
}
}
/// <returns>
/// The new value of the property
/// </returns>
public object OldValue {
get {
return oldValue;
}
}
public PropertyChangedEventArgs(Properties properties, string key, object oldValue, object newValue)
{
this.properties = properties;
this.key = key;
this.oldValue = oldValue;
this.newValue = newValue;
}
}
}

169
src/Main/Core/Project/Src/Services/PropertyService/PropertyService.cs

@ -2,6 +2,9 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO; using System.IO;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
@ -12,7 +15,6 @@ namespace ICSharpCode.Core
public static class PropertyService public static class PropertyService
{ {
static string propertyFileName; static string propertyFileName;
static string propertyXmlRootNodeName;
static string configDirectory; static string configDirectory;
static string dataDirectory; static string dataDirectory;
@ -26,19 +28,20 @@ namespace ICSharpCode.Core
public static void InitializeServiceForUnitTests() public static void InitializeServiceForUnitTests()
{ {
properties = null; properties = null;
InitializeService(null, null, null); configDirectory = null;
dataDirectory = null;
propertyFileName = null;
properties = new Properties();
} }
public static void InitializeService(string configDirectory, string dataDirectory, string propertiesName) public static void InitializeService(string configDirectory, string dataDirectory, string propertiesName)
{ {
if (properties != null) if (properties != null)
throw new InvalidOperationException("Service is already initialized."); throw new InvalidOperationException("Service is already initialized.");
properties = new Properties();
PropertyService.configDirectory = configDirectory; PropertyService.configDirectory = configDirectory;
PropertyService.dataDirectory = dataDirectory; PropertyService.dataDirectory = dataDirectory;
propertyXmlRootNodeName = propertiesName;
propertyFileName = propertiesName + ".xml"; propertyFileName = propertiesName + ".xml";
properties.PropertyChanged += new PropertyChangedEventHandler(PropertiesPropertyChanged); LoadPropertiesFromStream(Path.Combine(configDirectory, propertyFileName));
} }
public static string ConfigDirectory { public static string ConfigDirectory {
@ -53,79 +56,135 @@ namespace ICSharpCode.Core
} }
} }
public static string Get(string property) /// <inheritdoc cref="Properties.Get{T}(string, T)"/>
public static T Get<T>(string key, T defaultValue)
{ {
return properties[property]; return properties.Get(key, defaultValue);
} }
public static T Get<T>(string property, T defaultValue) [Obsolete("Use the NestedProperties method instead", true)]
public static Properties Get(string key, Properties defaultValue)
{ {
return properties.Get(property, defaultValue); return properties.Get(key, defaultValue);
} }
public static void Set<T>(string property, T value) /// <inheritdoc cref="Properties.NestedProperties"/>
public static Properties NestedProperties(string key)
{ {
properties.Set(property, value); return properties.NestedProperties(key);
} }
public static void Load() /// <inheritdoc cref="Properties.SetNestedProperties"/>
public static void SetNestedProperties(string key, Properties nestedProperties)
{ {
if (properties == null) properties.SetNestedProperties(key, nestedProperties);
throw new InvalidOperationException("Service is not initialized."); }
if (string.IsNullOrEmpty(configDirectory) || string.IsNullOrEmpty(propertyXmlRootNodeName))
throw new InvalidOperationException("No file name was specified on service creation"); /// <inheritdoc cref="Properties.Contains"/>
if (!Directory.Exists(configDirectory)) { public static bool Contains(string key)
Directory.CreateDirectory(configDirectory); {
} return properties.Contains(key);
if (!LoadPropertiesFromStream(Path.Combine(configDirectory, propertyFileName))) {
LoadPropertiesFromStream(Path.Combine(DataDirectory, "options", propertyFileName));
}
} }
public static bool LoadPropertiesFromStream(string fileName) /// <summary>
/// Gets the main property container.
/// </summary>
internal static Properties PropertiesContainer {
get { return properties; }
}
/// <inheritdoc cref="Properties.Set{T}(string, T)"/>
public static void Set<T>(string key, T value)
{
properties.Set(key, value);
}
[Obsolete("Use the SetNestedProperties method instead", true)]
public static void Set(string key, Properties value)
{
properties.Set(key, value);
}
/// <inheritdoc cref="Properties.GetList"/>
public static IReadOnlyList<T> GetList<T>(string key)
{
return properties.GetList<T>(key);
}
/// <inheritdoc cref="Properties.SetList"/>
public static void SetList<T>(string key, IEnumerable<T> value)
{
properties.SetList(key, value);
}
[Obsolete("Use the GetList method instead", true)]
public static T[] Get<T>(string key, T[] defaultValue)
{
throw new InvalidOperationException();
}
[Obsolete("Use the SetList method instead", true)]
public static void Set<T>(string key, T[] value)
{
throw new InvalidOperationException();
}
[Obsolete("Use the GetList method instead", true)]
public static List<T> Get<T>(string key, List<T> defaultValue)
{
throw new InvalidOperationException();
}
[Obsolete("Use the SetList method instead", true)]
public static void Set<T>(string key, List<T> value)
{
throw new InvalidOperationException();
}
[Obsolete("Use the GetList method instead", true)]
public static ArrayList Get<T>(string key, ArrayList defaultValue)
{
throw new InvalidOperationException();
}
[Obsolete("Use the SetList method instead", true)]
public static void Set<T>(string key, ArrayList value)
{
throw new InvalidOperationException();
}
/// <inheritdoc cref="Properties.Remove"/>
public static void Remove(string key)
{
properties.Remove(key);
}
static bool LoadPropertiesFromStream(string fileName)
{ {
if (!File.Exists(fileName)) { if (!File.Exists(fileName)) {
properties = new Properties();
return false; return false;
} }
try { try {
using (LockPropertyFile()) { using (LockPropertyFile()) {
using (XmlTextReader reader = new XmlTextReader(fileName)) { properties = Properties.Load(fileName);
while (reader.Read()){ return true;
if (reader.IsStartElement()) {
if (reader.LocalName == propertyXmlRootNodeName) {
properties.ReadProperties(reader, propertyXmlRootNodeName);
return true;
}
}
}
}
} }
} catch (XmlException ex) { } catch (XmlException ex) {
MessageService.ShowError("Error loading properties: " + ex.Message + "\nSettings have been restored to default values."); MessageService.ShowError("Error loading properties: " + ex.Message + "\nSettings have been restored to default values.");
} }
properties = new Properties();
return false; return false;
} }
public static void Save() public static void Save()
{ {
if (string.IsNullOrEmpty(configDirectory) || string.IsNullOrEmpty(propertyXmlRootNodeName)) if (string.IsNullOrEmpty(configDirectory) || string.IsNullOrEmpty(propertyFileName))
throw new InvalidOperationException("No file name was specified on service creation"); throw new InvalidOperationException("No file name was specified on service creation");
using (MemoryStream ms = new MemoryStream()) {
XmlTextWriter writer = new XmlTextWriter(ms, Encoding.UTF8); string fileName = Path.Combine(configDirectory, propertyFileName);
writer.Formatting = Formatting.Indented; using (LockPropertyFile()) {
writer.WriteStartElement(propertyXmlRootNodeName); properties.Save(fileName);
properties.WriteProperties(writer);
writer.WriteEndElement();
writer.Flush();
ms.Position = 0;
string fileName = Path.Combine(configDirectory, propertyFileName);
using (LockPropertyFile()) {
using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) {
ms.WriteTo(fs);
}
}
} }
} }
@ -143,13 +202,9 @@ namespace ICSharpCode.Core
}); });
} }
static void PropertiesPropertyChanged(object sender, PropertyChangedEventArgs e) public static event PropertyChangedEventHandler PropertyChanged {
{ add { properties.PropertyChanged += value; }
if (PropertyChanged != null) { remove { properties.PropertyChanged -= value; }
PropertyChanged(null, e);
}
} }
public static event PropertyChangedEventHandler PropertyChanged;
} }
} }

5
src/Main/Core/Project/Src/Services/ResourceService/ResourceService.cs

@ -4,6 +4,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Resources; using System.Resources;
@ -164,8 +165,8 @@ namespace ICSharpCode.Core
static void OnPropertyChange(object sender, PropertyChangedEventArgs e) static void OnPropertyChange(object sender, PropertyChangedEventArgs e)
{ {
if (e.Key == uiLanguageProperty && e.NewValue != e.OldValue) { if (e.PropertyName == uiLanguageProperty) {
LoadLanguageResources((string)e.NewValue); LoadLanguageResources(Language);
EventHandler handler = LanguageChanged; EventHandler handler = LanguageChanged;
if (handler != null) if (handler != null)
handler(null, e); handler(null, e);

13
src/Main/Core/Project/Src/Services/StringParser/StringParser.cs

@ -241,19 +241,14 @@ namespace ICSharpCode.Core
defaultValue = propertyName.Substring(pos + 2); defaultValue = propertyName.Substring(pos + 2);
propertyName = propertyName.Substring(0, pos); propertyName = propertyName.Substring(0, pos);
} }
Properties properties = PropertyService.PropertiesContainer;
pos = propertyName.IndexOf('/'); pos = propertyName.IndexOf('/');
if (pos >= 0) { while (pos >= 0) {
Properties properties = PropertyService.Get(propertyName.Substring(0, pos), new Properties()); properties = properties.NestedProperties(propertyName.Substring(0, pos));
propertyName = propertyName.Substring(pos + 1); propertyName = propertyName.Substring(pos + 1);
pos = propertyName.IndexOf('/'); pos = propertyName.IndexOf('/');
while (pos >= 0) {
properties = properties.Get(propertyName.Substring(0, pos), new Properties());
propertyName = propertyName.Substring(pos + 1);
}
return properties.Get(propertyName, defaultValue);
} else {
return PropertyService.Get(propertyName, defaultValue);
} }
return properties.Get(propertyName, defaultValue);
} }
} }

3
src/Main/Core/Test/ICSharpCode.Core.Tests.csproj

@ -28,7 +28,8 @@
<DelaySign>False</DelaySign> <DelaySign>False</DelaySign>
<AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode> <AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode>
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
<TargetFrameworkProfile>Client</TargetFrameworkProfile> <TargetFrameworkProfile>
</TargetFrameworkProfile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DefineConstants>DEBUG</DefineConstants> <DefineConstants>DEBUG</DefineConstants>

3
src/Main/ICSharpCode.Core.Presentation/ICSharpCode.Core.Presentation.csproj

@ -21,7 +21,8 @@
<AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode> <AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode>
<RunCodeAnalysis>False</RunCodeAnalysis> <RunCodeAnalysis>False</RunCodeAnalysis>
<CodeAnalysisRules>-Microsoft.Performance#CA1810</CodeAnalysisRules> <CodeAnalysisRules>-Microsoft.Performance#CA1810</CodeAnalysisRules>
<TargetFrameworkProfile>Client</TargetFrameworkProfile> <TargetFrameworkProfile>
</TargetFrameworkProfile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>

3
src/Main/ICSharpCode.Core.WinForms/ICSharpCode.Core.WinForms.csproj

@ -18,7 +18,8 @@
<AssemblyOriginatorKeyFile>..\ICSharpCode.SharpDevelop.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>..\ICSharpCode.SharpDevelop.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign> <DelaySign>False</DelaySign>
<AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode> <AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode>
<TargetFrameworkProfile>Client</TargetFrameworkProfile> <TargetFrameworkProfile>
</TargetFrameworkProfile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>

3
src/Main/ICSharpCode.SharpDevelop.Widgets/Project/ICSharpCode.SharpDevelop.Widgets.csproj

@ -17,7 +17,8 @@
<DelaySign>False</DelaySign> <DelaySign>False</DelaySign>
<AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode> <AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkProfile>Client</TargetFrameworkProfile> <TargetFrameworkProfile>
</TargetFrameworkProfile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' "> <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<Optimize>False</Optimize> <Optimize>False</Optimize>

Loading…
Cancel
Save