diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin index 6124fdd18c..6a15121bb0 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin @@ -148,6 +148,9 @@ label="Code inspection" class="CSharpBinding.Refactoring.IssueOptions"/> + diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj index dc6723019d..b09c7a9735 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj @@ -89,6 +89,18 @@ + + CSharpFormattingEditor.xaml + Code + + + CSharpFormattingOptionPanel.xaml + Code + + + CSharpProjectFormattingOptions.xaml + Code + @@ -235,6 +247,9 @@ + + + diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingOptionsContainer.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingOptionsContainer.cs index 4613e417c5..25b247390b 100644 --- a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingOptionsContainer.cs +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingOptionsContainer.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.ComponentModel; using System.Linq.Expressions; using System.Reflection; using ICSharpCode.NRefactory.CSharp; @@ -28,33 +29,77 @@ namespace CSharpBinding.FormattingStrategy /// Generic container for C# formatting options that can be chained together from general to specific and inherit /// options from parent. /// - public class CSharpFormattingOptionsContainer + public class CSharpFormattingOptionsContainer : INotifyPropertyChanged { CSharpFormattingOptionsContainer parent; - CSharpFormattingOptionsContainer child; + CSharpFormattingOptions cachedOptions; - Dictionary options; + HashSet activeOptions; internal CSharpFormattingOptionsContainer() { parent = null; - child = null; + activeOptions = new HashSet(); + cachedOptions = FormattingOptionsFactory.CreateEmpty(); + } + + internal CSharpFormattingOptionsContainer(CSharpFormattingOptions options) + { + parent = null; + activeOptions = new HashSet(); - options = new Dictionary(); + cachedOptions = options; + // Activate all options + foreach (var property in typeof(CSharpFormattingOptions).GetProperties()) { + activeOptions.Add(property.Name); + } } - public CSharpFormattingOptionsContainer Child + public CSharpFormattingOptionsContainer Parent { get { - return child; + return parent; } set { - if (child != null) { - child.parent = this; + if (parent != null) { + parent.PropertyChanged += HandlePropertyChanged; + } + parent = value; + parent.PropertyChanged += HandlePropertyChanged; + cachedOptions = CreateOptions(); + OnPropertyChanged("Parent"); + } + } + + #region INotifyPropertyChanged implementation + + public event PropertyChangedEventHandler PropertyChanged; + + private void OnPropertyChanged(string propertyName) + { + if (PropertyChanged != null) { + PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); + } + } + + #endregion + + private void HandlePropertyChanged(object sender, PropertyChangedEventArgs e) + { + if (e.PropertyName == "Parent") { + // Parent of parent has been updated, recreate options object + cachedOptions = CreateOptions(); + } else { + // Some other property has changed, check if we have our own value for it + if (!activeOptions.Contains(e.PropertyName)) { + // We rely on property value from some of the parents and have to update it from there + PropertyInfo propertyInfo = typeof(CSharpFormattingOptions).GetProperty(e.PropertyName); + if (propertyInfo != null) { + propertyInfo.SetValue(cachedOptions, GetOption(e.PropertyName)); + } } - child = value; } } @@ -69,6 +114,7 @@ namespace CSharpBinding.FormattingStrategy /// /// True, if option with given type could be found in hierarchy. False otherwise. public T GetOption(Expression> propertyGetter) + where T : struct { // Get name of property (to look for in dictionary) string optionName = null; @@ -93,10 +139,9 @@ namespace CSharpBinding.FormattingStrategy CSharpFormattingOptionsContainer container = this; do { - object val; - container.options.TryGetValue(option, out val); - if (val is T) { - return (T) val; + PropertyInfo propertyInfo = typeof(CSharpFormattingOptions).GetProperty(option); + if ((propertyInfo != null) && (propertyInfo.PropertyType == typeof(T))) { + return (T) propertyInfo.GetValue(container.cachedOptions); } container = container.parent; } while (container != null); @@ -104,12 +149,49 @@ namespace CSharpBinding.FormattingStrategy return default(T); } + /// + /// Sets an option. + /// + /// Option name. + /// Option value, null to reset. + public void SetOption(string option, T? value) + where T : struct + { + if (value.HasValue) { + // Save value in option values and cached options + activeOptions.Add(option); + PropertyInfo propertyInfo = typeof(CSharpFormattingOptions).GetProperty(option); + if ((propertyInfo != null) && (propertyInfo.PropertyType == typeof(T))) { + propertyInfo.SetValue(cachedOptions, value.Value); + } + } else { + // Reset this option + activeOptions.Remove(option); + // Update formatting options object from parents + PropertyInfo propertyInfo = typeof(CSharpFormattingOptions).GetProperty(option); + if ((propertyInfo != null) && (propertyInfo.PropertyType == typeof(T))) { + propertyInfo.SetValue(cachedOptions, GetOption(option)); + } + } + } + + /// + /// Retrieves a instance from current + /// container, resolving all options throughout container hierarchy. + /// + /// Filled instance. + public CSharpFormattingOptions GetEffectiveOptions() + { + // Use copy of cached options instance + return cachedOptions.Clone(); + } + /// /// Creates a instance from current - /// container, resolving all options through container hierarchy. + /// container, resolving all options throughout container hierarchy. /// /// Created and filled instance. - public CSharpFormattingOptions CreateOptions() + private CSharpFormattingOptions CreateOptions() { var outputOptions = FormattingOptionsFactory.CreateEmpty(); diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingEditor.xaml b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingEditor.xaml new file mode 100644 index 0000000000..1c257bb20c --- /dev/null +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingEditor.xaml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingEditor.xaml.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingEditor.xaml.cs new file mode 100644 index 0000000000..e859938c6e --- /dev/null +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingEditor.xaml.cs @@ -0,0 +1,250 @@ +// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Windows.Controls; + +namespace CSharpBinding.OptionPanels +{ + internal class IFormattingItemContainer + { + string Text { get; set; } + } + + /// + /// Represents a container item for other container items in formatting editor list + /// + internal class FormattingGroupContainer : IFormattingItemContainer + { + public string Text + { + get; + set; + } + + public IEnumerable Children + { + get; + set; + } + } + + /// + /// Represents a container for formatting options. + /// + internal class FormattingOptionContainer : IFormattingItemContainer + { + public string Text + { + get; + set; + } + + public IEnumerable Children + { + get; + set; + } + } + + /// + /// Represents a single formatting option in formatting editor. + /// + internal class FormattingOption + { + public string OptionName + { + get; + set; + } + public string Text + { + get; + set; + } + } + + /// + /// Interaction logic for CSharpFormattingEditor.xaml + /// + public partial class CSharpFormattingEditor : UserControl + { + readonly List rootEntries; + + public CSharpFormattingEditor() + { + rootEntries = new List(); + + InitializeComponent(); + BuildOptionItems(); + this.DataContext = rootEntries; + } + + void BuildOptionItems() + { + rootEntries.AddRange( + new IFormattingItemContainer[] + { + new FormattingGroupContainer { Text = "Indentation", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "Indent namespace body" }, + new FormattingOption { Text = "Indent class body" }, + new FormattingOption { Text = "Indent interface body" }, + new FormattingOption { Text = "Indent struct body" }, + new FormattingOption { Text = "Indent enum body" }, + new FormattingOption { Text = "Indent method body" }, + new FormattingOption { Text = "Indent property body" }, + new FormattingOption { Text = "Indent event body" }, + new FormattingOption { Text = "Indent blocks" }, + new FormattingOption { Text = "Indent switch body" }, + new FormattingOption { Text = "Indent case body" }, + new FormattingOption { Text = "Indent break statements" }, + new FormattingOption { Text = "Align embedded using statements" }, + new FormattingOption { Text = "Align embedded if statements" }, + new FormattingOption { Text = "Align else in if statements" }, + new FormattingOption { Text = "Auto property formatting" }, + new FormattingOption { Text = "Simple property formatting" }, + new FormattingOption { Text = "Empty line formatting" }, + new FormattingOption { Text = "Indent preprocessor directives" }, + new FormattingOption { Text = "Align to member reference dot" }, + } + } + } + }, + new FormattingGroupContainer { Text = "Braces", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "-" } + } + } + } + }, + new FormattingGroupContainer { Text = "New lines", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "-" } + } + } + } + }, + new FormattingGroupContainer { Text = "Spaces", + Children = new [] { + new FormattingGroupContainer { Text = "Methods", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "-" } + } + } + } + }, + new FormattingGroupContainer { Text = "Method calls", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "-" } + } + } + } + }, + new FormattingGroupContainer { Text = "Fields", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "-" } + } + } + } + }, + new FormattingGroupContainer { Text = "Local variables", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "-" } + } + } + } + }, + new FormattingGroupContainer { Text = "Constructors", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "-" } + } + } + } + }, + new FormattingGroupContainer { Text = "Indexers", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "-" } + } + } + } + }, + new FormattingGroupContainer { Text = "Delegates", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "-" } + } + } + } + }, + new FormattingGroupContainer { Text = "Statements", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "-" } + } + } + } + }, + new FormattingGroupContainer { Text = "Operators", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "-" } + } + } + } + }, + new FormattingGroupContainer { Text = "Brackets", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "-" } + } + } + } + } + } + }, + new FormattingGroupContainer { Text = "Blank lines", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "-" } + } + } + } + }, + new FormattingGroupContainer { Text = "Keep formatting", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "-" } + } + } + } + }, + new FormattingGroupContainer { Text = "Wrapping", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "-" } + } + } + } + }, + new FormattingGroupContainer { Text = "Using declarations", Children = new [] { new FormattingOptionContainer { + Children = new [] { + new FormattingOption { Text = "-" } + } + } + } + } + } + ); + } + } +} \ No newline at end of file diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingOptionPanel.xaml b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingOptionPanel.xaml new file mode 100644 index 0000000000..384c8a5103 --- /dev/null +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingOptionPanel.xaml @@ -0,0 +1,16 @@ + + + + + + + \ No newline at end of file diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingOptionPanel.xaml.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingOptionPanel.xaml.cs new file mode 100644 index 0000000000..00df2919a8 --- /dev/null +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingOptionPanel.xaml.cs @@ -0,0 +1,42 @@ +// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using ICSharpCode.SharpDevelop.Gui; + +namespace CSharpBinding.OptionPanels +{ + /// + /// Interaction logic for CSharpFormattingOptionPanel.xaml + /// + public partial class CSharpFormattingOptionPanel : OptionPanel + { + public CSharpFormattingOptionPanel() + { + InitializeComponent(); + } + } +} \ No newline at end of file diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpProjectFormattingOptions.xaml b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpProjectFormattingOptions.xaml new file mode 100644 index 0000000000..9642f3259e --- /dev/null +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpProjectFormattingOptions.xaml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpProjectFormattingOptions.xaml.cs b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpProjectFormattingOptions.xaml.cs new file mode 100644 index 0000000000..b04aa8aedc --- /dev/null +++ b/src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpProjectFormattingOptions.xaml.cs @@ -0,0 +1,42 @@ +// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using ICSharpCode.SharpDevelop.Gui.OptionPanels; + +namespace CSharpBinding.OptionPanels +{ + /// + /// Interaction logic for CSharpProjectFormattingOptionPanel.xaml + /// + public partial class CSharpProjectFormattingOptionPanel : ProjectOptionPanel + { + public CSharpProjectFormattingOptionPanel() + { + InitializeComponent(); + } + } +} \ No newline at end of file